/**
* Copyright o_healer ( http://wonderfl.net/user/o_healer )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/5cfY
*/
// forked from osamX's ワンダフルクエスト
// forked from clockmaker's [Alternativa3D] Wonderfl Quest 3D
// forked from o_healer's 簡易2Dアクションゲームテンプレート
/*
「Wonderfl Fantasy Code Chronicle」
・FFCC的な「ドット絵3Dアクション」
操作方法
・十字キー:移動
・SPACE or Z:ジャンプ
・キーボードによっては「左と上を押しながらSPACEを押してもジャンプしない」などの現象が起こります
アルゴリズム
・表示まわりは「Wonderfl Quest 3D」を少し拡張しただけ
・移動まわりは「簡易2Dアクションゲームテンプレート」を3次元に拡張したもの
その他
・もう少しだけ高速化できそうだけど、対応は保留中。
・並んでるパネルを一体化すればもう少しだけ早くなるはず
*/
package {
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.ui.Keyboard;
import flash.filters.*;
import alternativ5.engine3d.materials.*;
import alternativ5.engine3d.primitives.*;
import alternativ5.types.Texture;
import alternativ5.utils.MathUtils;
[SWF(width="465", height="465", frameRate="60", backgroundColor="0x000000")]
public class GameMain extends Sprite{
//==Const==
//マップ要素
static private var MapIndexIter:int = 0;
static public const O:int = MapIndexIter++;//0:空
static public const G:int = MapIndexIter++;//Grass:芝生
static public const S:int = MapIndexIter++;//Sand:砂
static public const T:int = MapIndexIter++;//Tile:石畳
static public const F:int = MapIndexIter++;//Flooring:フローリング
static public const MAP_INDEX_NUM:int = MapIndexIter;
//マップ
static public const MAP_DATA:Array = [
//1F
[
[G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G],
[G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G],
[G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G],
[G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G],
[G, G, T, G, G, G, G, G, G, G, G, G, G, G, G, G, G],
[G, G, T, G, G, G, G, G, G, G, G, G, G, G, G, G, G],
[G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G],
[G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G],
[G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G],
[G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G],
],
//2F
[
[T, T, T, T, T, O, O, O, O, O, O, O, O, O, O, O, O],
[T, T, T, T, T, O, O, O, O, O, O, O, O, O, O, O, O],
[T, T, T, T, T, O, O, O, O, O, O, O, O, O, O, T, O],
[T, T, T, T, T, O, O, O, O, O, O, O, O, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
],
//3F
[
[O, T, T, T, O, O, O, O, O, O, O, O, O, O, O, O, O],
[O, T, T, T, O, O, O, O, O, O, O, O, O, O, O, T, O],
[O, T, T, T, O, O, O, O, O, O, O, O, O, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
],
//4F
[
[O, O, T, T, T, T, T, O, O, O, O, O, O, O, O, O, O],
[O, O, T, T, T, T, T, O, O, O, O, T, T, O, T, O, O],
[O, O, O, O, O, O, T, O, O, O, O, T, T, O, O, O, O],
[O, O, O, O, O, O, T, O, O, O, O, T, T, O, O, O, O],
[O, O, O, O, O, O, T, T, T, O, O, T, T, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
[O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
],
];
//マップの長さ
static public const MAP_NUM_X:int = MAP_DATA[0][0].length;
static public const MAP_NUM_Y:int = MAP_DATA[0].length;
static public const MAP_NUM_Z:int = MAP_DATA.length;
//1パネルの長さ
static public const PANEL_SIZE:int = 48;
//全体の拡大率
static public const SCALE:Number = 3;
//画像URL:フィールド
static public const FIELD_IMG_URLS:Array = [
{index:G, url:"http://flash-scope.com/wonderfl/WonderflQuest/map/map0.png"},//芝生
{index:S, url:"http://flash-scope.com/wonderfl/WonderflQuest/map/map1.png"},//砂
{index:T, url:"http://flash-scope.com/wonderfl/WonderflQuest/map/map2.png"},//石畳
{index:F, url:"http://flash-scope.com/wonderfl/WonderflQuest/map/map3.png"},//フローリング
];
//画像URL:プレイヤー
static public const PLAYER_IMG_URLS:Array = [
"http://flash-scope.com/wonderfl/WonderflQuest/yuusha/yuushaF1.png", //前向き1
"http://flash-scope.com/wonderfl/WonderflQuest/yuusha/yuushaF2.png", //前向き2
"http://flash-scope.com/wonderfl/WonderflQuest/yuusha/yuushaB1.png", //後ろ向き1
"http://flash-scope.com/wonderfl/WonderflQuest/yuusha/yuushaB2.png", //後ろ向き2
"http://flash-scope.com/wonderfl/WonderflQuest/yuusha/yuushaL1.png", //左向き1
"http://flash-scope.com/wonderfl/WonderflQuest/yuusha/yuushaL2.png", //左向き2
"http://flash-scope.com/wonderfl/WonderflQuest/yuusha/yuushaR1.png", //右向き1
"http://flash-scope.com/wonderfl/WonderflQuest/yuusha/yuushaR2.png" //右向き2
];
//画像URL:空
static public const SKY_URL:String = "http://clockmaker.jp/labs/100109_wonderfl_quest/imgs/sky.png";
//コリジョン:1パネルを何分割するか
static public const COLLISION_SCALE:Number = 16;
//そのうちいくつをパネルからはみ出して採用するか
static public const COLLISION_OFFSET:Number = 4;
//コリジョン判定用
static public const COLLISION_COLOR_EMPTY:uint = 0x000000;
static public const COLLISION_COLOR_BLOCK:uint = 0xFFFFFF;
//Utility
static public const POS_ZERO:Point = new Point(0,0);
//==Var==
//【似非】Singleton【ていうかGlobalアクセス用】
static public var Instance:GameMain;
//3次元表示
public var m_World:BasicTemplate;
//コリジョン処理用Bitmap
public var m_Collision:Array;
//画像:フィールド
public var m_BitmapData_Field:Array = new Array(MAP_INDEX_NUM);
//画像:プレイヤー
public var m_BitmapData_Player:Array = new Array(PLAYER_IMG_URLS.length);
//画像:空
public var m_BitmapData_Sky:BitmapData;
//プレイヤー
public var m_Player:Player;
//==Function==
//#Sequence
//Init
public function GameMain(){
//Singleton
Instance = this;
//ロード開始
Load();
}
//Load
public function Load():void{
var i:int;
var num:int;
var count:int = 0;
var IncCount:Function = function():void{
count++;
};
var DecCount:Function = function():void{
count--;
if(count <= 0){//全てのロードが完了したら
Reset();//初期化に移る
}
};
//Load:Field
{
//Init
//→Load時に行う。ロードされなかったものは空白として扱うため。
//Load
{
FIELD_IMG_URLS.forEach(function(item:Object, index:int, arr:Array):void{
var map_index:int = item.index;
var url:String = item.url;
IncCount();
var ldr:Loader = new Loader();
ldr.load(new URLRequest(url), new LoaderContext(true));
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event):void {
//画像保存
{
/*
m_BitmapData_Field[map_index] = new BitmapData(PANEL_SIZE, PANEL_SIZE, true, 0x00000000);
m_BitmapData_Field[map_index].draw(ldr.content);
/*/
//最初から拡大して保存しておく
m_BitmapData_Field[map_index] = new BitmapData(PANEL_SIZE, PANEL_SIZE, true, 0x00000000);
const mtx:Matrix = new Matrix(SCALE,0,0,SCALE, 0,0);
m_BitmapData_Field[map_index].draw(ldr.content, mtx);
//*/
}
//残ロード数監視
{
DecCount();
}
});
});
}
}
//Load:Player
{
//Init
{
num = m_BitmapData_Player.length;
for(i = 0; i < num; i++){
m_BitmapData_Player[i] = new BitmapData(PANEL_SIZE, PANEL_SIZE, true, 0x00000000)
}
}
//Load
{
PLAYER_IMG_URLS.forEach(function(item:Object, index:int, arr:Array):void{
var url:String = item as String;
IncCount();
var ldr:Loader = new Loader();
ldr.load(new URLRequest(url), new LoaderContext(true));
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event):void {
//画像保存
{
m_BitmapData_Player[index].draw(ldr.content);
}
//残ロード数監視
{
DecCount();
}
});
});
}
}
//Load:Sky
{
//Init
{
m_BitmapData_Sky = new BitmapData(465, 465, true, 0x00000000)
addChild(new Bitmap(m_BitmapData_Sky));
}
//Load
{
var url:String = SKY_URL;
IncCount();
var ldr:Loader = new Loader();
ldr.load(new URLRequest(url), new LoaderContext(true));
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event):void {
//画像保存
{
m_BitmapData_Sky.draw(ldr.content);
}
//残ロード数監視
{
DecCount();
}
});
}
}
}
//Reset
public function Reset():void{
var x:int;
var y:int;
var z:int;
//3D
{
//Create
{
if(m_World == null){
m_World = new BasicTemplate(465, 465, true);
addChild(m_World);
}
}
//Param
{
m_World.camera.rotationY = Math.PI;
m_World.camera.rotationX = -Math.PI * 100/180;
m_World.camera.rotationZ = Math.PI;
// m_World.camera.x = yuushaPos.x + FLDSIZE / 2;
// m_World.camera.y = yuushaPos.y + FLDSIZE + 100;
}
}
//Player
{
//Create
{
if(m_Player == null){
m_Player = new Player();
m_World.scene.root.addChild(m_Player);
}
}
//*
//Param
{
m_Player.x = PANEL_SIZE * MAP_NUM_X / 2;
m_Player.y = PANEL_SIZE * (MAP_NUM_Y-1);
m_Player.z = -100;
}
//*/
//Key
{
stage.addEventListener(KeyboardEvent.KEY_DOWN, m_Player.onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, m_Player.onKeyUp);
}
}
//Field
{
//
const IsTwoSided:Boolean = false;
//1Fの地面だけは一体化
var ground:Plane;
//地面
ground = new Plane(PANEL_SIZE*MAP_NUM_X, PANEL_SIZE*MAP_NUM_Y, 1, 1, IsTwoSided);
ground.rotationY = Math.PI;
ground.x = PANEL_SIZE * MAP_NUM_X/2;
ground.y = PANEL_SIZE * MAP_NUM_Y/2;
ground.z = -PANEL_SIZE/2;
//地面の画像はこれに描く
var bmd_ground:BitmapData = new BitmapData(PANEL_SIZE*MAP_NUM_X, PANEL_SIZE*MAP_NUM_Y, true, 0x00000000);
var mtx:Matrix = new Matrix(1,0,0,1, 0,0);
//面を作るかのチェックのための関数(そちらにブロックがあるか)
const IsEmpty:Function = function(in_X:int, in_Y:int, in_Z:int):Boolean{
//範囲チェック
{
if(in_X < 0){return true;}
if(in_X >= MAP_NUM_X){return true;}
if(in_Y < 0){return true;}
if(in_Y >= MAP_NUM_Y){return true;}
if(in_Z < 0){return true;}
if(in_Z >= MAP_NUM_Z){return true;}
}
//空白かどうか
return (MAP_DATA[in_Z][in_Y][in_X] == O);
};
//陰の実現のためのFilterを作る関数
const CreateDarkFilter:Function = function(in_Ratio:Number):ColorMatrixFilter{
var r:Number = in_Ratio;
return new ColorMatrixFilter([
r, 0, 0, 0, 0,
0, r, 0, 0, 0,
0, 0, r, 0, 0,
0, 0, 0, 1, 0
]);
};
var tex:Texture;
var mat:TextureMaterial;
for(z = 0; z < MAP_NUM_Z; z++){
for(y = 0; y < MAP_NUM_Y; y++){
for(x = 0; x < MAP_NUM_X; x++){
var bmd_ori:BitmapData = m_BitmapData_Field[MAP_DATA[z][y][x]];
//Check
if(bmd_ori == null){continue;}
var bmd:BitmapData = bmd_ori;
var fieldPlane:Plane;
if(z == 0){
//1Fの地面はひとまとめ
mtx.tx = (MAP_NUM_X-1-x)*PANEL_SIZE;
mtx.ty = (MAP_NUM_Y-1-y)*PANEL_SIZE;
bmd_ground.draw(bmd, mtx);
}else{
//2Fより上は個別対応
//上面
if(IsEmpty(x,y,z+1)){
fieldPlane = new Plane(bmd.width, bmd.height, 1, 1, IsTwoSided);
fieldPlane.rotationY = Math.PI;
fieldPlane.x = PANEL_SIZE * x + PANEL_SIZE/2;
fieldPlane.y = PANEL_SIZE * y + PANEL_SIZE/2;
fieldPlane.z = PANEL_SIZE * -z - PANEL_SIZE/2;
tex = new Texture(bmd);
mat = new TextureMaterial(tex);
fieldPlane.cloneMaterialToAllSurfaces(mat);
m_World.scene.root.addChild(fieldPlane);
}
//下面
if(IsEmpty(x,y,z-1)){
bmd = bmd_ori.clone();
fieldPlane = new Plane(bmd.width, bmd.height, 1, 1, IsTwoSided);
fieldPlane.rotationY = 0;
fieldPlane.x = PANEL_SIZE * x + PANEL_SIZE/2;
fieldPlane.y = PANEL_SIZE * y + PANEL_SIZE/2;
fieldPlane.z = PANEL_SIZE * -z + PANEL_SIZE/2;
//暗くする
const filter_bottom:ColorMatrixFilter = CreateDarkFilter(0.2);
bmd.applyFilter(bmd, bmd.rect, POS_ZERO, filter_bottom);
tex = new Texture(bmd);
mat = new TextureMaterial(tex);
fieldPlane.cloneMaterialToAllSurfaces(mat);
m_World.scene.root.addChild(fieldPlane);
}
//正面
if(IsEmpty(x,y+1,z)){
bmd = bmd_ori.clone();
fieldPlane = new Plane(bmd.width, bmd.height, 1, 1, IsTwoSided);
fieldPlane.rotationX = -Math.PI/2;
fieldPlane.x = PANEL_SIZE * x + PANEL_SIZE/2;
fieldPlane.y = PANEL_SIZE * y + PANEL_SIZE;
fieldPlane.z = PANEL_SIZE * -z;
//暗くする
const filter_front:ColorMatrixFilter = CreateDarkFilter(0.6);
bmd.applyFilter(bmd, bmd.rect, POS_ZERO, filter_front);
tex = new Texture(bmd);
mat = new TextureMaterial(tex);
fieldPlane.cloneMaterialToAllSurfaces(mat);
m_World.scene.root.addChild(fieldPlane);
}
//左面
if(IsEmpty(x+1,y,z)){
bmd = bmd_ori.clone();
fieldPlane = new Plane(bmd.width, bmd.height, 1, 1, IsTwoSided);
fieldPlane.rotationY = Math.PI/2;
fieldPlane.x = PANEL_SIZE * x + PANEL_SIZE;
fieldPlane.y = PANEL_SIZE * y + PANEL_SIZE/2;
fieldPlane.z = PANEL_SIZE * -z;
//暗くする
const filter_left:ColorMatrixFilter = CreateDarkFilter(0.4);
bmd.applyFilter(bmd, bmd.rect, POS_ZERO, filter_left);
tex = new Texture(bmd);
mat = new TextureMaterial(tex);
fieldPlane.cloneMaterialToAllSurfaces(mat);
m_World.scene.root.addChild(fieldPlane);
}
//右面
if(IsEmpty(x-1,y,z)){
bmd = bmd_ori.clone();
fieldPlane = new Plane(bmd.width, bmd.height, 1, 1, IsTwoSided);
fieldPlane.rotationY = -Math.PI/2;
fieldPlane.x = PANEL_SIZE * x;
fieldPlane.y = PANEL_SIZE * y + PANEL_SIZE/2;
fieldPlane.z = PANEL_SIZE * -z;
//暗くする
const filter_right:ColorMatrixFilter = CreateDarkFilter(0.8);
bmd.applyFilter(bmd, bmd.rect, POS_ZERO, filter_right);
tex = new Texture(bmd);
mat = new TextureMaterial(tex);
fieldPlane.cloneMaterialToAllSurfaces(mat);
m_World.scene.root.addChild(fieldPlane);
}
//裏は省略(カメラの回転があるようなら描く)
}
}
}
}
//地面画像設定
var tex_ground:Texture = new Texture(bmd_ground);
var mat_ground:TextureMaterial = new TextureMaterial(tex_ground);
ground.cloneMaterialToAllSurfaces(mat_ground);
//地面登録
m_World.scene.root.addChild(ground);
}
//Collision
{
if(m_Collision == null){
m_Collision = new Array(MAP_NUM_Z);
var rect:Rectangle = new Rectangle(-COLLISION_OFFSET,-COLLISION_OFFSET, COLLISION_SCALE+2*COLLISION_OFFSET,COLLISION_SCALE+2*COLLISION_OFFSET);
for(z = 0; z < MAP_NUM_Z; z++){
m_Collision[z] = new BitmapData(COLLISION_SCALE * MAP_NUM_X, COLLISION_SCALE * MAP_NUM_Y, false, COLLISION_COLOR_EMPTY);
for(y = 0; y < MAP_NUM_Y; y++){
rect.y = -COLLISION_OFFSET + y*COLLISION_SCALE;
for(x = 0; x < MAP_NUM_X; x++){
rect.x = -COLLISION_OFFSET + x*COLLISION_SCALE;
if(m_BitmapData_Field[MAP_DATA[z][y][x]]){//画像があればコリジョンもあるとみなす
m_Collision[z].fillRect(rect, COLLISION_COLOR_BLOCK);
}
}
}
}
}
}
//Update
{
//!!多重登録を防止したい
addEventListener(Event.ENTER_FRAME, Update);
}
}
//Update
public function Update(e:Event = null):void{
//Player
{
m_Player.Update();
}
//Camera
{
m_World.camera.x = m_Player.x;
m_World.camera.y = m_Player.y + PANEL_SIZE + 100;
//m_World.camera.z = m_Player.z - 50;
m_World.camera.z = MathUtils.Lerp(m_World.camera.z, m_Player.z - 50, 0.2);//補間処理を入れてみる
}
}
//#
//IsCollision
public function IsCollision(in_X:int, in_Y:int, in_Z:int):Boolean{
/*
//#MAP_DATAで判断するバージョン
//配列にアクセスするためのIndex化
var x:int = Math.floor( in_X / PANEL_SIZE);
var y:int = Math.floor( in_Y / PANEL_SIZE);
var z:int = Math.floor(-in_Z / PANEL_SIZE);
//範囲チェック
{
var Flag_for_RangeOut:Boolean = true;//範囲外はコリジョンとみなす(通行不能)
if(x < 0){return Flag_for_RangeOut;}
if(x >= MAP_NUM_X){return Flag_for_RangeOut;}
if(y < 0){return Flag_for_RangeOut;}
if(y >= MAP_NUM_Y){return Flag_for_RangeOut;}
if(z < 0){return Flag_for_RangeOut;}
if(z >= MAP_NUM_Z){return false;}//天井だけは突き抜けてOK
}
//要素が空でなければコリジョンとみなす
return (MAP_DATA[z][y][x] != O);
/*/
//#Bitmapで判断するバージョン
//BitmapにアクセスするためのIndex化
var x:int = Math.floor( in_X * COLLISION_SCALE / PANEL_SIZE);
var y:int = Math.floor( in_Y * COLLISION_SCALE / PANEL_SIZE);
var z:int = Math.floor(-in_Z / PANEL_SIZE);//こっちはBitmapじゃないのでそのまま
//範囲チェック
{
var Flag_for_RangeOut:Boolean = true;//範囲外はコリジョンとみなす(通行不能)
if(x < 0){return Flag_for_RangeOut;}
if(x >= MAP_NUM_X * COLLISION_SCALE){return Flag_for_RangeOut;}
if(y < 0){return Flag_for_RangeOut;}
if(y >= MAP_NUM_Y * COLLISION_SCALE){return Flag_for_RangeOut;}
if(z < 0){return Flag_for_RangeOut;}
if(z >= MAP_NUM_Z){return false;}//天井だけは突き抜けてOK
}
//
return (m_Collision[z].getPixel(x, y) == COLLISION_COLOR_BLOCK);
//*/
}
}
}
import flash.display.*;
import flash.errors.*;
import flash.events.*;
import flash.geom.*;
import flash.net.URLRequest;
import flash.ui.Keyboard;
import flash.system.LoaderContext;
import alternativ5.engine3d.controllers.*;
import alternativ5.engine3d.core.*;
import alternativ5.engine3d.display.*;
import alternativ5.engine3d.materials.*;
import alternativ5.engine3d.primitives.*;
//#プレイヤー
class Player extends Plane{
//==Const==
//移動速度
static public const MOVE_VEL:Number = 72.0;
//ジャンプ速度
static public const JUMP_VEL:Number = 130.0;
//重力
static public const GRAVITY:Number = 100.0;
//入力
static private var InputIter:int = 0;
static public const INPUT_U:int = InputIter++;
static public const INPUT_D:int = InputIter++;
static public const INPUT_L:int = InputIter++;
static public const INPUT_R:int = InputIter++;
static public const INPUT_JUMP:int = InputIter++;
static public const INPUT_NUM:int = InputIter;
//向き
static public const DIR_U:int = 0;
static public const DIR_D:int = 1;
static public const DIR_L:int = 2;
static public const DIR_R:int = 3;
//アニメーション時間(何秒で切り替えるか)
static public const ANIM_INTERVAL:Number = 0.5;
//==Var==
//2次元での表示画像
public var m_Graphic:MovieClip = new MovieClip();
public var m_GraphicList:Array;
//入力
public var m_Input:Array = new Array(INPUT_NUM);
//速度
public var m_Vel:Vector3D = new Vector3D(0,0,0);
//接地フラグ
public var m_GroundFlag:Boolean =false;
//向き
public var m_Dir:int = DIR_D;
//アニメーション用タイマー
public var m_AnimTimer:Number = 0;
//==Function==
//Init
public function Player(){
var i:int;
//Super
{
const DivideNum:int = 1;
super(GameMain.PANEL_SIZE, GameMain.PANEL_SIZE, DivideNum, DivideNum);
}
//Param
{
//垂直になるようにする
this.rotationX = Math.PI/2;
//m_Input
for(i = 0; i < INPUT_NUM; i++){
m_Input[i] = false;
}
}
//Graphic
{
var num:int = 8;
m_GraphicList = new Array(8);
for(i = 0; i < num; i++){
m_GraphicList[i] = new Bitmap(GameMain.Instance.m_BitmapData_Player[i]);
m_Graphic.addChild(m_GraphicList[i]);
}
}
//Attach Graphic
{
var ratio:Number = GameMain.PANEL_SIZE / GameMain.SCALE;
cloneMaterialToAllSurfaces(new MovieClipMaterial(m_Graphic, ratio, ratio));
}
/*
//Key
//→こいつではstageには触れないらしい
{
addEventListener(
Event.ADDED_TO_STAGE,//stageを扱うので、登録されたときに実行する
function(e:Event):void{
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
}
);
}
//*/
}
//Update
public function Update(e:Event=null):void{
var DeltaTime:Number = 1/24.0;
//Move
Update_Move(DeltaTime);
//Anim
Update_Anim(DeltaTime);
}
//Update : Move
public function Update_Move(in_DeltaTime:Number):void{
//移動元
var OldX:int;
var OldY:int;
var OldZ:int;
{
OldX = this.x;
OldY = this.y;
OldZ = this.z;
}
//移動先
var NewX:int = OldX;
var NewY:int = OldY;
var NewZ:int = OldZ;
{
//m_Vel.x & m_Vel.y
//XY方向の移動処理
{
//目標方向を入力から決定
var TrgVel:Vector3D = new Vector3D(0,0,0);
{//ついでに向きもここで変更
if(m_Input[INPUT_U]){TrgVel.y -= 1; m_Dir = DIR_U;}
if(m_Input[INPUT_D]){TrgVel.y += 1; m_Dir = DIR_D;}
if(m_Input[INPUT_L]){TrgVel.x -= 1; m_Dir = DIR_L;}
if(m_Input[INPUT_R]){TrgVel.x += 1; m_Dir = DIR_R;}
}
//補正
if(TrgVel.length > 0.1){
//入力あり
//→指定方向に加速
//長さがMOVE_VELのベクトルに変更
TrgVel.normalize();
TrgVel.scaleBy(MOVE_VEL);
}else{
//入力なし
//→減速
//そのまま使う
}
//適用
var ratio:Number = 0.8;//0に近いほど慣性が働く。1ならば慣性なし。
m_Vel.x = MathUtils.Lerp(m_Vel.x, TrgVel.x, ratio);
m_Vel.y = MathUtils.Lerp(m_Vel.y, TrgVel.y, ratio);
}
//m_Vel.z
{
//ジャンプ処理
{
if(m_Input[INPUT_JUMP] && m_GroundFlag){
m_Vel.z = -JUMP_VEL;
}
m_GroundFlag = false;
}
//重力処理
{
m_Vel.z += GRAVITY * in_DeltaTime;
}
}
//NewX, NewY, NewZ
//目標地点の計算
{
NewX += m_Vel.x * in_DeltaTime;
NewY += m_Vel.y * in_DeltaTime;
NewZ += m_Vel.z * in_DeltaTime;
}
}
//移動処理
{
var NextX:int = OldX;
var NextY:int = OldY;
var NextZ:int = OldZ;
//Z
while(NextZ != NewZ){
//次の座標に移る
if(NextZ < NewZ){
NextZ++;
}else{
NextZ--;
}
//コリジョンチェック
if(GameMain.Instance.IsCollision(NextX, NextY, NextZ)){
NextZ = this.z;//移動できなければ移動できたところまで戻して
m_Vel.z = 0;//速度を0にして
if(OldZ < NewZ){m_GroundFlag = true;}//(下方向への移動なら)接地したことにして
break;//終了
}
//コリジョンがなければ今の座標を採用
this.z = NextZ;
}
//Y
while(NextY != NewY){
//次の座標に移る
if(NextY < NewY){
NextY++;
}else{
NextY--;
}
//コリジョンチェック
if(GameMain.Instance.IsCollision(NextX, NextY, NextZ)){
NextY = this.y;//移動できなければ移動できたところまで戻して
m_Vel.y = 0;//速度を0にして
break;//終了
}
//コリジョンがなければ今の座標を採用
this.y = NextY;
}
//X
while(NextX != NewX){
//次の座標に移る
if(NextX < NewX){
NextX++;
}else{
NextX--;
}
//コリジョンチェック
if(GameMain.Instance.IsCollision(NextX, NextY, NextZ)){
NextX = this.x;//移動できなければ移動できたところまで戻して
m_Vel.x = 0;//速度を0にして
break;//終了
}
//コリジョンがなければ今の座標を採用
this.x = NextX;
}
}
}
//Update : Anim
public function Update_Anim(in_DeltaTime:Number):void{
//Timer
{
m_AnimTimer += in_DeltaTime;
if(ANIM_INTERVAL*2 <= m_AnimTimer){
m_AnimTimer -= ANIM_INTERVAL*2;
}
}
//Anim
{
//採用するIndex
var anim_index:int;
{
//方向で基準Indexを設定
switch(m_Dir){
case DIR_U:
anim_index = 2;//後向き
break;
case DIR_D:
anim_index = 0;//前向き
break;
case DIR_L:
anim_index = 4;//左向き
break;
case DIR_R:
anim_index = 6;//右向き
break;
}
//タイマーに応じてIndexにオフセットを適用
if(ANIM_INTERVAL <= m_AnimTimer){
anim_index += 1;
}
}
//採用するやつ以外は全て不可視にする
for(var i:int = 0; i < 8; i++){
m_GraphicList[i].visible = (i == anim_index);
}
}
}
//Input
private function SetInput(in_KeyCode:uint, in_Flag:Boolean):void{
switch (in_KeyCode){
case Keyboard.UP:
m_Input[INPUT_U] = in_Flag;
break;
case Keyboard.DOWN:
m_Input[INPUT_D] = in_Flag;
break;
case Keyboard.LEFT:
m_Input[INPUT_L] = in_Flag;
break;
case Keyboard.RIGHT:
m_Input[INPUT_R] = in_Flag;
break;
case Keyboard.SPACE://SPACE
case 90://Z
m_Input[INPUT_JUMP] = in_Flag;
break;
}
}
public function onKeyDown(event:KeyboardEvent):void{
SetInput(event.keyCode, true);
}
public function onKeyUp(event:KeyboardEvent):void{
SetInput(event.keyCode, false);
}
}
class BasicTemplate extends Sprite {
/**
* 新しい BasicTemplate インスタンスを作成します。
* @param viewWidth
* @param viewHeight
* @param scaleToStage
*/
public function BasicTemplate(viewWidth:int = 640, viewHeight:int = 480, scaleToStage:Boolean = true) {
_viewWidth = viewWidth;
_viewHeight = viewHeight;
_scaleToStage = scaleToStage;
// Creating scene
scene = new Scene3D();
scene.splitAnalysis = false; // not analysis for performance
scene.root = new Object3D();
// Adding camera
camera = new Camera3D();
//camera.z = -1000;
scene.root.addChild(camera);
// camera contoller
cameraContoller = new CameraController(this);
cameraContoller.camera = camera;
// set view
view = new View();
view.camera = camera;
addChild(view);
// stage
if (stage)
init();
else
addEventListener(Event.ADDED_TO_STAGE, init);
}
/**
* カメラインスタンスです。
*/
public var camera:Camera3D;
/**
* カメラコントローラーです。
*/
public var cameraContoller:CameraController;
/**
* シーンインスタンスです。
*/
public var scene:Scene3D;
/**
* ビューインスタンスです。
*/
public var view:View;
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング後に実行したい処理を記述します。
*/
protected var _onPostRender:Function = function():void {};
/**
* 初期化されたときに実行されるイベントです。
* 初期化時に実行したい処理を記述します。
*/
private var _onInit:Function = function():void {};
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング前に実行したい処理を記述します。
*/
private var _onPreRender:Function = function():void {};
private var _scaleToStage:Boolean;
private var _viewHeight:int;
private var _viewWidth:int;
public function get onInit():Function {
return _onInit;
}
public function set onInit(value:Function):void {
_onInit = value;
}
public function get onPostRender():Function {
return _onPostRender;
}
public function set onPostRender(value:Function):void {
_onPostRender = value;
}
public function get onPreRender():Function {
return _onPreRender;
}
public function set onPreRender(value:Function):void {
_onPreRender = value;
}
/**
* シングルレンダリング(レンダリングを一回だけ)を実行します。
*/
public function singleRender():void {
onRenderTick();
}
/**
* レンダリングを開始します。
*/
public function startRendering():void {
addEventListener(Event.ENTER_FRAME, onRenderTick);
}
/**
* レンダリングを停止します。
*/
public function stopRendering():void {
removeEventListener(Event.ENTER_FRAME, onRenderTick);
}
/**
* 初期化されたときに実行されるイベントです。
* 初期化時に実行したい処理をオーバーライドして記述します。
*/
protected function atInit():void {
}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング後に実行したい処理をオーバーライドして記述します。
*/
protected function atPostRender():void {
}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング前に実行したい処理をオーバーライドして記述します。
*/
protected function atPreRender():void {
}
/**
* @private
*/
private function init(e:Event = null):void {
// resize
stage.addEventListener(Event.RESIZE, onResize);
onResize(null);
// render
startRendering();
atInit();
_onInit();
}
/**
* @private
*/
private function onRenderTick(e:Event = null):void {
atPreRender();
_onPreRender();
scene.calculate();
atPostRender();
_onPostRender();
}
/**
* @private
*/
private function onResize(event:Event = null):void {
if (_scaleToStage) {
view.width = stage.stageWidth;
view.height = stage.stageHeight;
} else {
view.width = _viewWidth;
view.height = _viewHeight;
}
}
}
class MathUtils{
//Lerp
static public function Lerp(in_Src:Number, in_Dst:Number, in_Ratio:Number):Number{
return (in_Src * (1 - in_Ratio)) + (in_Dst * in_Ratio);
}
}