Box2D Act Template
Box2Dを使ったアクションゲームのテンプレート
主に自分用。
/**
* 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/bjOv
*/
/*
Box2D Act Template
・Box2Dを使ったアクションゲームのテンプレート
Box2D 2.0.2 only
・2.1とかだとエラー
*/
package {
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.net.*;
import flash.system.*;
import flash.text.*;
[SWF(width="465", height="465", frameRate="30", backgroundColor="0x000000")]
public class Box2DAct extends Sprite {
//==File==
//*
static public const BITMAP_URL:String = "http://assets.wonderfl.net/images/related_images/9/9e/9ea7/9ea7a1dba862955d298634ebcb8c87c4804c4d44";
/*/
[Embed(source='Image.png')]
private static var Bitmap_Graphic: Class;
//*/
//==Const==
//画面の大きさ
static public const VIEW_W:int = 465;
static public const VIEW_H:int = 465;
//==Var==
//Pseudo Singleton
static public var Instance:Box2DAct;
//Layer
public var m_Layer_GameRoot:Sprite = new Sprite();
//Engine
public var m_ActGameEngine:ActGameEngine = new ActGameEngine();
//==Function==
//Init
public function Box2DAct() {
//Load
//*
//wonderfl用:Bitmapを外部からロードする場合
//Load
var loader:Loader = new Loader();
loader.load(new URLRequest(BITMAP_URL), new LoaderContext(true));//画像のロードを開始して
loader.contentLoaderInfo.addEventListener(
Event.COMPLETE,//ロードが完了したら
function(e:Event):void{
OnLoad(loader.content);//それを保持した後
}
);
/*/
//ローカル用:Bitmapを事前ロードできる場合
//ブロック画像のセット(&その他初期化)
OnLoad(new Bitmap_Graphic());
//*/
}
public function OnLoad(in_Graphic:DisplayObject):void
{
//Static Init
{
ImageManager.Init(in_Graphic);
}
//Init
{
if(stage != null){
Init(null);
}else{
addEventListener(
Event.ADDED_TO_STAGE,//ステージに追加されたら
Init
);
}
}
}
public function Init(e:Event):void
{
//Pseudo Singleton
{
Instance = this;
}
//BG
{
addChild(new Bitmap(new BitmapData(VIEW_W, VIEW_H, false, 0x808080)));
}
//Layer
{
addChild(m_Layer_GameRoot);
}
//Engine
{
const O:int = ActGameEngine.O;//空白
const W:int = ActGameEngine.W;//地形
const P:int = ActGameEngine.P;//プレイヤー位置(生成後は空白として扱われる)
const G:int = ActGameEngine.G;//ゴール位置(基本的には空白として扱われる)
const X:int = ActGameEngine.X;//トゲブロック
const L:int = ActGameEngine.L;//連結ブロック
const A:int = ActGameEngine.A;//ダッシュブロック
const MAP:Array = [
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
[W,O,O,O,O,O,O,O,W,W,X,W,X,X,X,W],
[W,O,O,O,O,O,O,O,W,X,X,X,W,X,W,W],
[W,O,O,O,O,O,O,G,W,W,W,W,W,W,W,W],
[W,O,O,O,O,O,O,W,O,O,O,O,O,O,O,W],
[W,O,O,O,O,O,O,W,W,O,O,O,O,O,O,W],
[W,O,O,O,O,O,O,L,L,O,O,O,O,O,O,W],
[W,O,O,O,O,O,O,W,W,W,O,O,O,O,O,W],
[W,O,O,O,O,O,O,L,L,L,O,O,O,O,O,W],
[W,O,O,O,O,O,O,W,W,W,W,O,O,O,O,W],
[W,O,O,O,O,O,O,L,L,L,L,O,O,O,O,W],
[W,O,W,W,W,W,W,W,W,W,W,W,O,O,O,W],
[W,O,O,O,O,O,O,O,O,O,O,O,O,O,O,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,W],
[W,O,O,O,O,O,O,O,O,O,O,O,O,O,O,W],
[W,O,O,O,O,O,O,O,O,O,O,O,O,O,W,W],
[W,O,O,O,O,O,O,L,O,O,O,O,O,O,W,W],
[W,O,O,O,O,O,O,L,O,O,O,O,O,W,W,W],
[W,O,O,O,O,O,L,L,O,O,O,O,O,W,W,W],
[W,O,O,O,W,X,X,X,X,X,X,X,X,X,X,W],
[W,O,O,O,O,O,O,O,O,O,O,O,O,O,O,W],
[W,W,O,O,O,O,O,O,O,O,O,O,O,O,O,W],
[W,O,O,O,O,O,O,O,O,O,O,O,O,O,O,W],
[W,O,O,O,O,L,L,O,O,O,O,O,O,O,O,W],
[W,X,X,X,X,W,W,W,O,O,W,O,W,O,O,W],
[W,O,O,O,O,O,O,O,O,O,O,O,O,O,O,W],
[W,O,O,O,O,O,O,X,X,X,X,X,O,O,W,W],
[W,O,O,O,O,O,O,O,O,O,O,O,O,O,W,W],
[W,O,O,O,O,O,O,O,L,O,O,O,O,W,W,W],
[W,O,O,O,O,O,O,W,W,O,O,O,O,W,W,W],
[W,O,P,O,W,O,O,W,W,O,O,O,O,W,W,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
];
m_ActGameEngine = new ActGameEngine();
m_Layer_GameRoot.addChild(m_ActGameEngine);
m_ActGameEngine.Init(MAP, VIEW_W, VIEW_H);
}
//Update
{
addEventListener(Event.ENTER_FRAME, Update);
}
//OnEnd
{
addEventListener(Event.REMOVED_FROM_STAGE, Finish);
}
}
//Finish
public function Finish(e:Event):void{
removeEventListener(Event.ADDED_TO_STAGE, Init);
removeEventListener(Event.ENTER_FRAME, Update);
removeEventListener(Event.REMOVED_FROM_STAGE, Finish);
}
//Update
public function Update(e:Event=null):void{
var DeltaTime:Number = 1.0 / stage.frameRate;
m_ActGameEngine.Update(DeltaTime);
}
}
}
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.net.*;
import flash.system.*;
import flash.text.*;
import flash.ui.*;
//Box2D
import Box2D.Dynamics.*;
import Box2D.Dynamics.Contacts.*;
import Box2D.Dynamics.Joints.*;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Common.Math.*;
//import General.*;
//Engine
class ActGameEngine extends Sprite
{
//==Const==
//パネルの大きさ
static public const PANEL_W:int = 32;
//重力
static public const GRAVITY:Number = 10.0;
//マップの要素
static public var s_BlockIndexIter:int = 0;
static public const O:int = s_BlockIndexIter++;//空白
static public const W:int = s_BlockIndexIter++;//地形
static public const P:int = s_BlockIndexIter++;//プレイヤー位置(生成後は空白として扱われる)
static public const G:int = s_BlockIndexIter++;//ゴール位置(基本的には空白として扱われる)
static public const X:int = s_BlockIndexIter++;//トゲブロック
static public const L:int = s_BlockIndexIter++;//連結ブロック
static public const A:int = s_BlockIndexIter++;//ダッシュブロック
//Box2Dとのスケーリング変換
static public const PHYS_SCALE:Number = 100.0;
//表示サイズ(外部から指定)
static public var VIEW_W:int = 0;
static public var VIEW_H:int = 0;
//マップ(外部から指定)
static public var MAP:Array;
static public var MAP_W:int = 0;
static public var MAP_H:int = 0;
//==Var==
//Phys World
public var m_PhysWorld:b2World;
//All GameObject List
public var m_GameObject:Vector.<GameObject> = new Vector.<GameObject>();
//Layer
public var m_Root :Sprite = new Sprite();
public var m_Root_Game :Sprite = new Sprite();
public var m_Root_UI :Sprite = new Sprite();
//BG
public var m_BG:BackGround;
//Player
public var m_Player:Player;
//Goal
public var m_Goal:Goal;
//Text
public var m_Text:TextField;
//Flag
public var m_IsGameOver:Boolean = false;
//==Function==
//Init
public function Init(in_Map:Array, in_ViewW:int, in_ViewH:int):void{
var i:int;
var num:int;
//Const
{
VIEW_W = in_ViewW;
VIEW_H = in_ViewH;
MAP = in_Map;
MAP_W = in_Map[0].length * PANEL_W;
MAP_H = in_Map.length * PANEL_W;
}
//Physics
{
//AABB
const RANGE_LX:Number = -10 * PANEL_W;
const RANGE_UY:Number = -10 * PANEL_W;
const RANGE_RX:Number = 110 * PANEL_W;
const RANGE_DY:Number = 110 * PANEL_W;
var worldAABB:b2AABB = new b2AABB();
worldAABB.lowerBound.Set(RANGE_LX/PHYS_SCALE, RANGE_UY/PHYS_SCALE);
worldAABB.upperBound.Set(RANGE_RX/PHYS_SCALE, RANGE_DY/PHYS_SCALE);
//Gravity
var g:b2Vec2 = new b2Vec2(0.0, GRAVITY);
//Sleep
var useSleep:Boolean = true;
//World
m_PhysWorld = new b2World(worldAABB, g, useSleep);
}
//Layer
{
addChild(m_Root);
m_Root.addChild(m_Root_Game);
m_Root.addChild(m_Root_UI);
}
//BG
{
m_BG = BackGround.Create(in_Map, m_PhysWorld);
m_GameObject.push(m_BG);
m_Root_Game.addChild(m_BG);
}
//Goal
{
m_Goal = Goal.Create(in_Map, m_PhysWorld);
m_GameObject.push(m_Goal);
m_Root_Game.addChild(m_Goal);
}
//Needle
{
var needle_arr:Vector.<Needle> = Needle.Create(in_Map, m_PhysWorld);
//グラフィックがないので描画登録はなし
}
//Block
{
var block_arr:Vector.<Block> = Block.Create(in_Map, m_PhysWorld);
num = block_arr.length;
for(i = 0; i < num; ++i){
m_Root_Game.addChild(block_arr[i]);
}
}
//Player
{
m_Player = Player.Create(in_Map, m_PhysWorld);
m_GameObject.push(m_Player);
m_Root_Game.addChild(m_Player);
}
//Text
{
m_Text = new TextField();
m_Text.selectable = false;
m_Text.autoSize = TextFieldAutoSize.CENTER;
m_Text.defaultTextFormat = new TextFormat('Verdana', 64, 0xFFFFFF, true);
m_Text.text = "";
// m_Text.filters = [new GlowFilter(0x00FFFF,1.0, 8,8)];
m_Text.x = in_ViewW/2;
m_Text.y = in_ViewH/2;
m_Root_UI.addChild(m_Text);
}
//Camera
{
Update_Camera(0.0);
}
/*
//Debug
{
var m_DebugLayer:Sprite = new Sprite();
addChild(m_DebugLayer);
// デバッグオブジェクト
var debug:b2DebugDraw = new b2DebugDraw();
debug.m_sprite = m_DebugLayer;
debug.m_drawScale = PHYS_SCALE;
debug.m_fillAlpha = 0.3;
debug.m_lineThickness = 1.0;
debug.m_drawFlags = b2DebugDraw.e_shapeBit;
// デバッグ描画
m_PhysWorld.SetDebugDraw(debug);
}
//*/
}
//Update
public function Update(in_DeltaTime:Number):void{
//Check
{
if(m_IsGameOver){
return;
}
}
//Phys
Update_Phys(in_DeltaTime);
//GameObj
Update_GameObj(in_DeltaTime);
//Camera
Update_Camera(in_DeltaTime);
//End Check
Check_GameOver();
}
//Update : Phys
public function Update_Phys(in_DeltaTime:Number):void{
{
//あまり「動くコリジョン」は使わないので、贅沢にたくさん処理して良いことにする(ちゃんとしたコリジョン排斥のため)
var iterations:int = 50;
m_PhysWorld.Step(in_DeltaTime, iterations);
}
//Phys => GameObj
{
for(var iter:b2Contact = m_PhysWorld.m_contactList; iter != null; iter = iter.GetNext()){
if(iter.GetManifoldCount() == 0){
continue;
}
var Obj1:GameObject = iter.GetShape1().m_body.m_userData as GameObject;
var Obj2:GameObject = iter.GetShape2().m_body.m_userData as GameObject;
var Nrm_Phys:b2Vec2 = iter.GetManifolds()[0].normal;
var Nrm:Vector3D = new Vector3D(Nrm_Phys.x, Nrm_Phys.y);
var Nrm_Neg:Vector3D = new Vector3D(-Nrm_Phys.x, -Nrm_Phys.y);
Nrm.normalize();
Nrm_Neg.normalize();
Obj1.OnContact_Common(Obj2, Nrm);
Obj2.OnContact_Common(Obj1, Nrm_Neg);
Obj1.OnContact(Obj2, Nrm);
Obj2.OnContact(Obj1, Nrm_Neg);
}
//Physics→GameObjectへの位置の反映
{
for(var bb:b2Body = m_PhysWorld.m_bodyList; bb; bb = bb.m_next) {
var Obj:GameObject = bb.m_userData as GameObject;
if(Obj != null){
Obj.Phys2Obj();
}
}
}
}
}
//Update : GameObj
public function Update_GameObj(in_DeltaTime:Number):void{
var num:int = m_GameObject.length;
for(var i:int = 0; i < num; ++i){
m_GameObject[i].Update(in_DeltaTime);
}
}
//Update : Camera
public function Update_Camera(in_DeltaTime:Number):void{
//プレイヤー位置
var PlayerX:int;
var PlayerY:int;
{
PlayerX = m_Player.x;
PlayerY = m_Player.y;
}
//プレイヤーを中心にした時の画面の左上の座標
var TrgX:int;
var TrgY:int;
{
TrgX = PlayerX - VIEW_W/2;
TrgY = PlayerY - VIEW_H/2;
}
//カメラの左上の位置
var CameraX:int;
var CameraY:int;
{
CameraX = TrgX;
CameraY = TrgY;
//画面外を移さないようにする
if(CameraX + VIEW_W > MAP_W){CameraX = MAP_W - VIEW_W;}
if(CameraX < 0){CameraX = 0;}
if(CameraY + VIEW_H > MAP_H){CameraY = MAP_H - VIEW_H;}
if(CameraY < 0){CameraY = 0;}
}
//カメラ位置に合わせて、ステージの位置を変更する
{
m_Root_Game.x = -CameraX;
m_Root_Game.y = -CameraY;
}
}
//Check : GameOver
public function Check_GameOver():void{
//Goal
if(m_Goal.m_GoalFlag){
OnGoal();
return;
}
//Dead End
if(m_Player.m_HP <= 0){
OnDead();
return;
}
}
//GameOver : Dead
public function OnDead():void{
m_IsGameOver = true;
m_Text.text = "Game Over";
}
//GameOver : Goal
public function OnGoal():void{
m_IsGameOver = true;
m_Text.text = "GOAL";
}
}
//GameObject : Interface
class GameObject extends Sprite
{
//==Const==
static public const PHYS_SCALE:Number = ActGameEngine.PHYS_SCALE;
//==Var==
//Pyhsics
//!!
//Phys World
public var m_PhysWorld:b2World;
//Phys
public var m_PhysBody:b2Body;
public var m_Friction:Number = 0.05;
//Flag
public var m_UseSleep:Boolean = true;
public var m_GroundFlag:Boolean = false;
//==Function==
//#Common
//Update
public function Update(in_DeltaTime:Number):void{
}
//Damage
public function OnDamage(in_Val:int):void{
}
//#Physics
//Ready : Body
public function ReadyBody():void{
//Check
if(m_PhysBody != null){
return;
}
//Definition
var physBodyDef:b2BodyDef = new b2BodyDef();
physBodyDef.position.Set(this.x / PHYS_SCALE, this.y / PHYS_SCALE);
physBodyDef.fixedRotation = true;
physBodyDef.allowSleep = m_UseSleep;
physBodyDef.userData = this;
//Create
m_PhysBody = m_PhysWorld.CreateBody(physBodyDef);
}
//Create : Fix : Box
public function CreateCollision_Fix(lx:int, uy:int, w:int, h:int):void{
//Bodyの用意
ReadyBody();
var shapeDef:b2PolygonDef = new b2PolygonDef();
shapeDef.SetAsOrientedBox(w/2/PHYS_SCALE, h/2/PHYS_SCALE, new b2Vec2((lx+w/2)/PHYS_SCALE, (uy+h/2)/PHYS_SCALE));
shapeDef.density = 0;//Fix
shapeDef.friction = m_Friction;
// shapeDef.restitution = i_Param.restitution;
// shapeDef.filter.categoryBits = i_Param.category_bits;
// shapeDef.filter.maskBits = i_Param.mask_bits;
m_PhysBody.CreateShape(shapeDef);
}
//Create : Dynamic : Box
public function CreateCollision_Dynamic(lx:int, uy:int, w:int, h:int):void{
//Bodyの用意
ReadyBody();
var shapeDef:b2PolygonDef = new b2PolygonDef();
shapeDef.SetAsOrientedBox(w/2/PHYS_SCALE, h/2/PHYS_SCALE, new b2Vec2((lx+w/2)/PHYS_SCALE, (uy+h/2)/PHYS_SCALE));
shapeDef.density = 0.1;
shapeDef.friction = m_Friction;
// shapeDef.restitution = i_Param.restitution;
// shapeDef.filter.categoryBits = i_Param.category_bits;
// shapeDef.filter.maskBits = i_Param.mask_bits;
m_PhysBody.CreateShape(shapeDef);
m_PhysBody.SetMassFromShapes();
}
//Create : Sensor : Box
public function CreateSensor(lx:int, uy:int, w:int, h:int):void{
//Bodyの用意
ReadyBody();
var shapeDef:b2PolygonDef = new b2PolygonDef();
shapeDef.SetAsOrientedBox(w/2/PHYS_SCALE, h/2/PHYS_SCALE, new b2Vec2((lx+w/2)/PHYS_SCALE, (uy+h/2)/PHYS_SCALE));
shapeDef.density = 0;//Fix
shapeDef.friction = m_Friction;
// shapeDef.restitution = i_Param.restitution;
// shapeDef.filter.categoryBits = i_Param.category_bits;
// shapeDef.filter.maskBits = i_Param.mask_bits;
shapeDef.isSensor = true;
m_PhysBody.CreateShape(shapeDef);
}
//Contact : Common
public function OnContact_Common(in_Obj:GameObject, in_Nrm:Vector3D):void{
//コリジョンに接触したら必ず呼ばれる
//コリジョンの接地判定
{//将来的に「横方向にぶつかってる」などの判定が必要になるかもしれないので、Ground以外にも用意しておく
var Vel:b2Vec2 = m_PhysBody.GetLinearVelocity();
//L
{
if(in_Nrm.x < -0.7){
if(Vel.x <= 0){
}
}
}
//R
{
if(in_Nrm.x > 0.7){
if(Vel.x >= 0){
}
}
}
//U
{
if(in_Nrm.y < -0.7){
if(Vel.y <= 0){
}
}
}
//D
{
if(in_Nrm.y > 0.7){
// if(Vel.y >= 0)//これだけだと、「一緒に落下しているとき」や「めりこんで上昇してるとき」が入らないので、もっと良い判定が望まれる
{
//接地フラグを立てる
m_GroundFlag = true;
}
}
}
}
}
//Contact :
public function OnContact(in_Obj:GameObject, in_Nrm:Vector3D):void{
//こっちはオーバーライドして各自で使う
}
//Sync : Physics=>Obj
public function Phys2Obj():void{
//コリジョンの位置を実際の位置として採用する
//Check
{
if(m_PhysBody == null){
return;
}
}
//Pos
{
this.x = m_PhysBody.GetPosition().x * PHYS_SCALE;
this.y = m_PhysBody.GetPosition().y * PHYS_SCALE;
}
//Rot
{
this.rotation = m_PhysBody.GetAngle() * 360/(2*Math.PI);
}
}
}
//GameObject : BG
class BackGround extends GameObject
{
//==Static==
//Create
static public function Create(in_Map:Array, in_PhysWorld:b2World):BackGround{
var bg:BackGround = new BackGround();
//Set Param
{
bg.m_PhysWorld = in_PhysWorld;
}
//Graphic
{
bg.addChild(ImageManager.CreateBackGroundGraphic(in_Map));
}
//Physics
{
CreateTerrainCollision(in_Map, bg);
}
return bg;
}
//Create : Collision
static public function CreateTerrainCollision(in_Map:Array, bg:BackGround):void{
var x:int;
var y:int;
var iter_x:int;
var iter_y:int;
var NumX:int = in_Map[0].length;
var NumY:int = in_Map.length;
//Alias
const W:int = ActGameEngine.W;
const O:int = ActGameEngine.O;
const X:int = ActGameEngine.X;
const PANEL_W:int = ActGameEngine.PANEL_W;
var CopyMap:Array;
{
CopyMap = new Array(NumY);
for(y = 0; y < NumY; y += 1){
CopyMap[y] = new Array(NumX);
for(x = 0; x < NumX; x += 1){
var m:int = in_Map[y][x];
switch(m){
case ActGameEngine.X:
m = W;
break;
}
CopyMap[y][x] = m;
}
}
}
//左右に一列になってるブロックを探して連結
//さらに、それらの下もブロックだったら連結
for(y = 0; y < NumY; y += 1){
var lx:int = -1;
var rx:int = -1;
for(x = -1; x < NumX+1; x += 1){
//範囲外は空白とみなす
var map:int;
{
if(x < 0){map = O;}
else
if(x >= NumX){map = O;}
else
{map = CopyMap[y][x];}
}
//必要な処理をしつつ、ブロックの生成が必要になったらフラグを立てて伝達
var CreateBlockFlag:Boolean = true;
{
switch(map){
case ActGameEngine.W:
{
if(lx < 0){lx = x;}
rx = x;
}
//このブロックの上も元々ブロックであれば、横に長くせず、縦に長くする
{
//上がブロックじゃない時だけフラグを戻す。そうでなければ、下のブロック生成に移行する
if(y == 0){CreateBlockFlag = false;}//マップの上辺なら上がブロックなわけはない
else
if(in_Map[y-1][x] != W && in_Map[y-1][x] != X){CreateBlockFlag = false;}//一つ上がブロックでなければすぐには生成しない
}
break;
}
}
//必要ならブロックを生成
{
if(CreateBlockFlag)
{
//左右に連結してるのがあれば、下方向を連結した後、採用
if(lx >= 0)
{//yの段のlx~rxが連結されている
//lx~rx, uy~dyを一つのブロックとみなす
//uyとdyを求める
var uy:int;
{
uy = y;//今の行が上辺
}
var dy:int;
{
var break_flag:Boolean = false;
for(dy = uy+1; dy < NumY; dy += 1){
for(iter_x = lx; iter_x <= rx; iter_x += 1){
if(CopyMap[dy][iter_x] != W){
break_flag = true;
}
if(break_flag){break;}
}
if(break_flag){break;}
}
dy -= 1;
}
//ブロックを実際に生成
{
bg.CreateCollision_Fix(lx * PANEL_W, uy * PANEL_W, (rx-lx+1) * PANEL_W, (dy-uy+1) * PANEL_W);
// var block:Block_Fix = new Block_Fix();
// block.Init(lx, rx, uy, dy);
}
//CopyMap上から、該当ブロックを消す
{
for(iter_y = uy; iter_y <= dy; iter_y += 1){
for(iter_x = lx; iter_x <= rx; iter_x += 1){
CopyMap[iter_y][iter_x] = O;
}
}
}
//reset
{
lx = rx = -1;
}
}//lx >= 0
}//CreateBlockFlag
}//Scope : Create Block
}//loop x
}//loop y
}
}
//GameObject : Block
class Block extends GameObject
{
//==Static==
//Create
static public function Create(in_Map:Array, in_PhysWorld:b2World):Vector.<Block>{
var result:Vector.<Block> = new Vector.<Block>();
//Alias
var NumX:int = in_Map[0].length;
var NumY:int = in_Map.length;
//Temp
var xx:int;
var yy:int;
//m_Mapの内容をコピーして、連結したものは消せるようにしておく
var CopyMap:Vector.<Vector.<int> >;
{
CopyMap = new Vector.<Vector.<int> >(NumY);
for(yy = 0; yy < NumY; yy += 1){
CopyMap[yy] = new Vector.<int>(NumX);
for(xx = 0; xx < NumX; xx += 1){
CopyMap[yy][xx] = in_Map[yy][xx];
}
}
}
//連結ブロック
{
var link_info:Vector.<Point> = new Vector.<Point>();
const MAP_W_MAX:int = 100;
const MAP_H_MAX:int = 100;
var link_lx:int = MAP_W_MAX;
var link_rx:int = 0;
var link_uy:int = MAP_H_MAX;
var link_dy:int = 0;
const gather_link_block:Function = function(in_X:int, in_Y:int):void{
//Check
{//L以外は飛ばす
if(CopyMap[in_Y][in_X] != ActGameEngine.L){
return;
}
}
//Lがあったので、これと連結しているLを全て集めて連結ブロックを生成
//まずは自分を追加
{
link_info.push(new Point(in_X, in_Y));
}
//ここは確認したので消す
{
CopyMap[in_Y][in_X] = ActGameEngine.O;
}
//Lのある範囲を求める
{
if(in_X < link_lx){link_lx = in_X;}
if(link_rx < in_X){link_rx = in_X;}
if(in_Y < link_uy){link_uy = in_Y;}
if(link_dy < in_Y){link_dy = in_Y;}
}
//上下左右について確認
{
if(in_Y > 0){gather_link_block(in_X, in_Y-1);}
if(in_Y < NumY-1){gather_link_block(in_X, in_Y+1);}
if(in_X > 0){gather_link_block(in_X-1, in_Y);}
if(in_X < NumX-1){gather_link_block(in_X+1, in_Y);}
}
};
for(yy = 0; yy < NumY; ++yy){
for(xx = 0; xx < NumX; ++xx){
//
gather_link_block(xx, yy);
//
if(link_info.length > 0){
//Create
{
var block:Block = Create_One(link_info, link_lx, link_rx, link_uy, link_dy, in_PhysWorld);
result.push(block);
}
//Reset
{
link_info = new Vector.<Point>();
link_lx = MAP_W_MAX;
link_rx = 0;
link_uy = MAP_H_MAX;
link_dy = 0;
}
}
}
}
}
return result;
}
//Create : Solo
static public function Create_One(in_PointList:Vector.<Point>, in_LX:int, in_RX:int, in_UY:int, in_DY:int, in_PhysWorld:b2World):Block{
var Num:int = in_PointList.length;
var NumX:int = in_RX - in_LX + 1;
var NumY:int = in_DY - in_UY + 1;
var i:int;
var xx:int;
var yy:int;
var OffsetX:int = -in_LX * ActGameEngine.PANEL_W;
var OffsetY:int = -in_UY * ActGameEngine.PANEL_W;
//CopyMap
var CopyMap:Array;
{
//Init
{
CopyMap = new Array(NumY);
for(yy = 0; yy < NumY; yy++){
CopyMap[yy] = new Array(NumX);
for(xx = 0; xx < NumX; xx++){
CopyMap[yy][xx] = ActGameEngine.O;
}
}
}
//Set
{
for(i = 0; i < Num; i++){
var point:Point = in_PointList[i];
xx = point.x - in_LX;
yy = point.y - in_UY;
CopyMap[yy][xx] = ActGameEngine.L;
}
}
}
//まずはコリジョンのRectangleのリストを求める
var col_rect_list:Vector.<Rectangle> = new Vector.<Rectangle>();
{//横方向に並んでるものはまとめて、さらに縦も同じ位置・同じ幅であればまとめる
//まとめるための関数
const clustering:Function = function(in_LX:int, in_RX:int, in_Y:int):void{
//今回の分の範囲
var rect:Rectangle = new Rectangle(in_LX, in_Y, in_RX-in_LX+1, 1);
//すでに求めた範囲のやつと一体化できるなら一体化する
var col_num:int = col_rect_list.length;
for(i = 0; i < col_num; i++){
//検証対象
var trg_rect:Rectangle = col_rect_list[i];
//一体化できるか
var union_flag:Boolean = true;
{
//幅が違えば一体化しない
if(trg_rect.x != rect.x || trg_rect.width != rect.width){
union_flag = false;
}
//自分の一つ上でなければ一体化しない
{
var trg_next_y:int = trg_rect.y + trg_rect.height;
if(trg_next_y != in_Y){
union_flag = false;
}
}
}
//一体化
if(union_flag){
trg_rect.height += 1;//下にくっつけたことにすればOKのはず
return;//一体化したので新規登録はせずに終了
}
}
//一体化できるものがなければ、新規登録
col_rect_list.push(rect);
}
//まとめ中かそうでないかのフラグ
var NowClustering:Boolean = false;
//イテレーション開始
var lx:int, rx:int;
for(yy = 0; yy < NumY; yy++){
for(xx = 0; xx < NumX; xx++){
var IsBlock:Boolean = (CopyMap[yy][xx] == ActGameEngine.L);
if(! NowClustering){//Lをまだ見つけていない
if(! IsBlock){//今回のもLじゃない
//何もせず次へ進む
}else{//Lを見つけた
//クラスタリング開始
NowClustering = true;
//左端はここ
lx = xx;
//右端もここ
rx = xx;
}
}else{//Lをすでに見つけていて、それを連結中
if(IsBlock){//今回のもLだった
//右端を伸ばす
rx = xx;
}else{//Lが途切れた
//前回位置までをクラスタリング
clustering(lx, rx, yy);
//クラスタリング終了
NowClustering = false;
}
}
}
if(NowClustering){//右端までLだった
//まとめる
rx = xx-1;
clustering(lx, rx, yy);
//クラスタリング終了
NowClustering = false;
}
}
}
//原点の調整をしつつ実際にコリジョンを生成
var block:Block = new Block();
{
//Create
{
block.x = -OffsetX;
block.y = -OffsetY;
block.m_PhysWorld = in_PhysWorld;
block.ReadyBody();
}
//Add Shape
{
var shapeDef:b2PolygonDef = new b2PolygonDef();
shapeDef.density = 0.1;
shapeDef.friction = 0.1;//0.3;
// shapeDef.restitution = ColParam.restitution;
// shapeDef.filter.categoryBits = ColParam.category_bits;
// shapeDef.filter.maskBits = ColParam.mask_bits;
var center:b2Vec2 = new b2Vec2();
var col_num:int = col_rect_list.length;
for(i = 0; i < col_num; i++){
var rect:Rectangle = col_rect_list[i];
//W
var w:Number = (rect.width/2 * ActGameEngine.PANEL_W - 0.01) / ActGameEngine.PHYS_SCALE;
var h:Number = (rect.height/2 * ActGameEngine.PANEL_W - 0.01) / ActGameEngine.PHYS_SCALE;
//center
center.x = (ActGameEngine.PANEL_W * (in_LX + (rect.left + rect.right)/2) + OffsetX) / ActGameEngine.PHYS_SCALE;
center.y = (ActGameEngine.PANEL_W * (in_UY + (rect.top + rect.bottom)/2) + OffsetY) / ActGameEngine.PHYS_SCALE;
/*
shapeDef.SetAsOrientedBox(w, h, center);
/*/
{//八角形
var d:Number = 4.0 / ActGameEngine.PHYS_SCALE;//削り取る角の辺の長さ
shapeDef.vertexCount = 8;
//時計回りに頂点を設定
shapeDef.vertices[0].Set(center.x + w-d, center.y - h);//北北東
shapeDef.vertices[1].Set(center.x + w, center.y - h+d);//東北東
shapeDef.vertices[2].Set(center.x + w, center.y + h-d);//東南東
shapeDef.vertices[3].Set(center.x + w-d, center.y + h);//南南東
shapeDef.vertices[4].Set(center.x - w+d, center.y + h);//南南西
shapeDef.vertices[5].Set(center.x - w, center.y + h-d);//西南西
shapeDef.vertices[6].Set(center.x - w, center.y - h+d);//西北西
shapeDef.vertices[7].Set(center.x - w+d, center.y - h );//北北西
}
//*/
block.m_PhysBody.CreateShape(shapeDef);
}
block.m_PhysBody.SetMassFromShapes();
}
}
//画像
{
var bmp:Bitmap = ImageManager.CreateBlockGraphic(CopyMap);
block.addChild(bmp);
}
return block;
}
}
//GameObject : Needle
class Needle extends GameObject
{
//==Static==
//Create
static public function Create(in_Map:Array, in_PhysWorld:b2World):Vector.<Needle>{
var result:Vector.<Needle> = new Vector.<Needle>();
//
var num_x:int = in_Map[0].length;
var num_y:int = in_Map.length;
for(var yy:int = 0; yy < num_y; ++yy){
for(var xx:int = 0; xx < num_x; ++xx){
if(in_Map[yy][xx] == ActGameEngine.X){
var obj:Needle = new Needle(xx, yy, in_PhysWorld);
result.push(obj);
}
}
}
return result;
}
//==Function==
//Init
public function Needle(in_IndexX:int, in_IndexY:int, in_PhysWorld:b2World){
//Alias
const PANEL_W:int = ActGameEngine.PANEL_W;
//Param
{
m_PhysWorld = in_PhysWorld;
this.x = in_IndexX * PANEL_W;
this.y = in_IndexY * PANEL_W;
}
//Collision
{
CreateSensor(-PANEL_W/16, -PANEL_W/16, PANEL_W*18/16, PANEL_W*18/16);
}
//No Graphic
}
//Contact :
override public function OnContact(in_Obj:GameObject, in_Nrm:Vector3D):void{
//Check
if(! (in_Obj is Player)){
return;
}
//
const DamageVal:int = 1;
in_Obj.OnDamage(DamageVal);
}
}
//GameObject : Player
class Player extends GameObject
{
//==Static==
//Create
static public function Create(in_Map:Array, in_PhysWorld:b2World):Player{
var player:Player = new Player();
//Set Param
{
player.m_PhysWorld = in_PhysWorld;
player.m_UseSleep = false;
var num_x:int = in_Map[0].length;
var num_y:int = in_Map.length;
for(var yy:int = 0; yy < num_y; ++yy){
for(var xx:int = 0; xx < num_x; ++xx){
if(in_Map[yy][xx] == ActGameEngine.P){
player.x = (xx + 0.5) * ActGameEngine.PANEL_W;
player.y = (yy + 0.5) * ActGameEngine.PANEL_W;
}
}
}
}
//Init
{
player.Init();
}
return player;
}
//==Const==
/*
#X方向の慣性制御
VX = 110に収束するように、POWとRATIOを決定する
・地上は完全に110、空中はそれより少し小さい値に収束
例えばDeltaTime=0.1(秒)とすると、
VX += POW * 0.1
VX *= RATIO
という式になり、POW=100、RATIO=0.5ならVX=5に収束する、という感じ
*/
//#Pos
static public const MOVE_POW_AIR:Number = 470.0;//空中での制御はやややりにくくする
static public const MOVE_POW_GROUND:Number = 1100.0;
static public const JUMP_VEL:Number = 420.0;
// static public const GRAVITY:Number = 600.0;
//#空気抵抗、地面との摩擦
static public const DRAG_RATIO_O:Number = 0.7;//空中での摩擦は少なくする(あまり減らさないようにする)
static public const DRAG_RATIO_W:Number = 0.5;//地面の摩擦も物理エンジンには任せない(壁に触れたままジャンプして摩擦が起こっても困るため)
//アニメーション用パラメータ
static public const ANIM_CYCLE:Number = 1.0;
static public const ANIM_ITER:Array = [0,1,2,1];
static public const ANIM_NUM:int = ANIM_ITER.length;
//用意されたグラフィックの数
static public const GRAPHIC_NUM:int = 3;
//==Var==
//入力
public var m_InputL:Boolean = false;
public var m_InputR:Boolean = false;
public var m_InputU:Boolean = false;
//表示画像
public var m_Bitmap:Bitmap = new Bitmap();//これの中身を差し替えることでアニメーションさせる
//アニメーション用タイマー
public var m_AnimTimer:Number = 0.0;
//アニメーション用画像リスト
public var m_BitmapDataList:Vector.<BitmapData> = new Vector.<BitmapData>(GRAPHIC_NUM);
//HP
public var m_HP:int = 1;
//==Function==
//Init
public function Init():void{
//Input
{
addEventListener(
Event.ADDED_TO_STAGE,//ステージに追加されたら
function(e:Event):void{
//キー入力を見る
stage.addEventListener(KeyboardEvent.KEY_DOWN, OnKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, OnKeyUp);
}
);
}
//グラフィック
{
//ロード
{
m_BitmapDataList = ImageManager.CreatePlayerGraphic();
}
//表示画像の登録
{
m_Bitmap.x = -24/2;
m_Bitmap.y = -32/2;
addChild(m_Bitmap);
}
}
//コリジョン
{
CreateCollision_Dynamic(-24/2, -32/2, 24, 32-1);
}
}
//Update : Input
private function OnKeyDown(event:KeyboardEvent):void{
if(event.keyCode == Keyboard.LEFT){ m_InputL = true;}
if(event.keyCode == Keyboard.RIGHT){m_InputR = true;}
if(event.keyCode == Keyboard.UP){ m_InputU = true;}
}
private function OnKeyUp(event:KeyboardEvent):void{
if(event.keyCode == Keyboard.LEFT){ m_InputL = false;}
if(event.keyCode == Keyboard.RIGHT){m_InputR = false;}
if(event.keyCode == Keyboard.UP){ m_InputU = false;}
}
//Update
override public function Update(in_DeltaTime:Number):void{
//移動
Update_Move(in_DeltaTime);
//アニメーション
Update_Anim(in_DeltaTime);
}
//Update : Anim
public function Update_Anim(in_DeltaTime:Number):void{
//m_AnimTimer
{
m_AnimTimer += in_DeltaTime;
if(m_AnimTimer > ANIM_CYCLE){m_AnimTimer -= ANIM_CYCLE;}
}
//m_AnimTimer => iter
var iter:int;
{
iter = ANIM_ITER[int(ANIM_NUM * m_AnimTimer/ANIM_CYCLE)];
}
m_Bitmap.bitmapData = m_BitmapDataList[iter];
if(m_InputL){this.scaleX = -1;}
if(m_InputR){this.scaleX = 1;}
}
//Update : Move
public function Update_Move(in_DeltaTime:Number):void{
//速度補正のみ行い、実際の移動は物理エンジン任せ
//Check
{
if(m_PhysBody == null){
return;
}
}
//PhysVel
var PhysVel:b2Vec2;
{
PhysVel = m_PhysBody.GetLinearVelocity();
}
//PhysVel => GameVel
var GameVX:Number;
var GameVY:Number;
{
GameVX = PhysVel.x * ActGameEngine.PHYS_SCALE;
GameVY = PhysVel.y * ActGameEngine.PHYS_SCALE;
}
//GameVelの補正
{
//GameAX
var GameAX:Number;
{
var PowX:Number;
{
if(! m_GroundFlag){
PowX = MOVE_POW_AIR;
}else{
PowX = MOVE_POW_GROUND;
}
}
GameAX = 0;
if(m_InputR){
GameAX = PowX
}
if(m_InputL){
GameAX = -PowX
}
}
//GameVX
{
//Powによる加算
GameVX += GameAX * in_DeltaTime;
//空気抵抗率
var Ratio:Number;
{
if(! m_GroundFlag){
Ratio = DRAG_RATIO_O;
}else{
Ratio = DRAG_RATIO_W;
}
}
//空気抵抗などによる減速(擬似抵抗)
GameVX *= Math.pow(Ratio, 10.0*in_DeltaTime);
}
//GameVY
{
// GameVY += GameAY * i_DeltaTime;//重力計算は物理エンジン任せ
//下降速度に制限を設けてみる
if(GameVY > JUMP_VEL){
GameVY = JUMP_VEL;//ジャンプ速度と同じにしてみる
}
if(m_GroundFlag && 0 <= GameVY){//接地中はジャンプ可能
if(m_InputU){
GameVY = -JUMP_VEL;
}
}
}
}
//GameVel => PhysVel
{
PhysVel.x = GameVX / ActGameEngine.PHYS_SCALE;
PhysVel.y = GameVY / ActGameEngine.PHYS_SCALE;
}
//Apply
{
m_PhysBody.SetLinearVelocity(PhysVel);
}
//Param Reset
{
m_GroundFlag = false;
}
}
//Damage
override public function OnDamage(in_Val:int):void{
m_HP -= in_Val;
}
}
//GameObject : Goal
class Goal extends GameObject
{
//==Static==
//Create
static public function Create(in_Map:Array, in_PhysWorld:b2World):Goal{
var goal:Goal = new Goal();
//Set Param
{
goal.m_PhysWorld = in_PhysWorld;
goal.m_UseSleep = false;
var num_x:int = in_Map[0].length;
var num_y:int = in_Map.length;
for(var yy:int = 0; yy < num_y; ++yy){
for(var xx:int = 0; xx < num_x; ++xx){
if(in_Map[yy][xx] == ActGameEngine.G){
goal.x = xx * ActGameEngine.PANEL_W;
goal.y = yy * ActGameEngine.PANEL_W;
}
}
}
}
//Init
{
goal.Init();
}
return goal;
}
//==Var==
public var m_GoalFlag:Boolean = false;
//==Function==
//Init
public function Init():void{
//Alias
const PANEL_W:int = ActGameEngine.PANEL_W;
//Collision
{
CreateSensor(PANEL_W*2/16, PANEL_W*2/16, PANEL_W*12/16, PANEL_W*12/16);
}
//Graphic
{
//this.blendMode = BlendMode.ADD;
addChild(ImageManager.CreateGoalGraphic());
}
}
//Contact :
override public function OnContact(in_Obj:GameObject, in_Nrm:Vector3D):void{
//Check
if(! (in_Obj is Player)){
return;
}
//
m_GoalFlag = true;
}
}
//ImageManager
class ImageManager
{
//==Const==
//Alias
static public const PANEL_W:int = ActGameEngine.PANEL_W;
static public const TILE_W:int = PANEL_W / 2;
//#enum:Quater
static public const LU:int = 0;
static public const RU:int = 1;
static public const LD:int = 2;
static public const RD:int = 3;
//#enum:Pos
static public const POS_X:int = 0;
static public const POS_Y:int = 1;
//#Graphic
static public var m_BitmapData_Ori:BitmapData;
//#Mapping
static public var m_Rect_Ground :Vector.<Vector.<Rectangle> >;
static public var m_Rect_Block :Vector.<Vector.<Rectangle> >;
static public var m_Rect_Needle :Vector.<Vector.<Rectangle> >;
//Filter
static public const divisor:Number = 1.0;
static public const bias:Number = 0.0;
static public const preserveAlpha:Boolean = true;
static public const clamp:Boolean = false;
static public const m_ConvFilter:Vector.<ConvolutionFilter> = new <ConvolutionFilter>[
new ConvolutionFilter(3,3,
[//LU
1, 2, 0,
4, 8, 0,
0, 0, 0,
],divisor,bias,preserveAlpha,clamp
),
new ConvolutionFilter(3,3,
[//RU
0, 2, 1,
0, 8, 4,
0, 0, 0,
],divisor,bias,preserveAlpha,clamp
),
new ConvolutionFilter(3,3,
[//LD
0, 0, 0,
4, 8, 0,
1, 2, 0,
],divisor,bias,preserveAlpha,clamp
),
new ConvolutionFilter(3,3,
[//RD
0, 0, 0,
0, 8, 4,
0, 2, 1,
],divisor,bias,preserveAlpha,clamp
),
];
//Rect
//- Empty
static public const RECT_EMPTY :Rectangle = new Rectangle( 4 * TILE_W, 2 * TILE_W, TILE_W, TILE_W);
//- BG
static public const RECT_BG :Rectangle = new Rectangle( 3 * TILE_W, 2 * TILE_W, TILE_W, TILE_W);
//- Goal
static public const RECT_GOAL :Rectangle = new Rectangle( 8 * TILE_W, 3 * TILE_W, PANEL_W, PANEL_W);
//- Wall
static public const RECT_WALL :Rectangle = new Rectangle( 1 * TILE_W, 1 * TILE_W, TILE_W, TILE_W);
static public const RECT_WALL_L :Rectangle = new Rectangle( 0 * TILE_W, 1 * TILE_W, TILE_W, TILE_W);
static public const RECT_WALL_R :Rectangle = new Rectangle( 2 * TILE_W, 1 * TILE_W, TILE_W, TILE_W);
static public const RECT_WALL_U :Rectangle = new Rectangle( 1 * TILE_W, 0 * TILE_W, TILE_W, TILE_W);
static public const RECT_WALL_D :Rectangle = new Rectangle( 1 * TILE_W, 2 * TILE_W, TILE_W, TILE_W);
static public const RECT_WALL_LorU :Rectangle = new Rectangle( 0 * TILE_W, 0 * TILE_W, TILE_W, TILE_W);
static public const RECT_WALL_RorU :Rectangle = new Rectangle( 2 * TILE_W, 0 * TILE_W, TILE_W, TILE_W);
static public const RECT_WALL_LorD :Rectangle = new Rectangle( 0 * TILE_W, 2 * TILE_W, TILE_W, TILE_W);
static public const RECT_WALL_RorD :Rectangle = new Rectangle( 2 * TILE_W, 2 * TILE_W, TILE_W, TILE_W);
static public const RECT_WALL_LandU :Rectangle = new Rectangle( 3 * TILE_W, 0 * TILE_W, TILE_W, TILE_W);
static public const RECT_WALL_RandU :Rectangle = new Rectangle( 4 * TILE_W, 0 * TILE_W, TILE_W, TILE_W);
static public const RECT_WALL_LandD :Rectangle = new Rectangle( 3 * TILE_W, 1 * TILE_W, TILE_W, TILE_W);
static public const RECT_WALL_RandD :Rectangle = new Rectangle( 4 * TILE_W, 1 * TILE_W, TILE_W, TILE_W);
//- Block
static public const RECT_BLOCK :Rectangle = new Rectangle( 1 * TILE_W, 4 * TILE_W, TILE_W, TILE_W);
static public const RECT_BLOCK_L :Rectangle = new Rectangle( 0 * TILE_W, 4 * TILE_W, TILE_W, TILE_W);
static public const RECT_BLOCK_R :Rectangle = new Rectangle( 2 * TILE_W, 4 * TILE_W, TILE_W, TILE_W);
static public const RECT_BLOCK_U :Rectangle = new Rectangle( 1 * TILE_W, 3 * TILE_W, TILE_W, TILE_W);
static public const RECT_BLOCK_D :Rectangle = new Rectangle( 1 * TILE_W, 5 * TILE_W, TILE_W, TILE_W);
static public const RECT_BLOCK_LorU :Rectangle = new Rectangle( 0 * TILE_W, 3 * TILE_W, TILE_W, TILE_W);
static public const RECT_BLOCK_RorU :Rectangle = new Rectangle( 2 * TILE_W, 3 * TILE_W, TILE_W, TILE_W);
static public const RECT_BLOCK_LorD :Rectangle = new Rectangle( 0 * TILE_W, 5 * TILE_W, TILE_W, TILE_W);
static public const RECT_BLOCK_RorD :Rectangle = new Rectangle( 2 * TILE_W, 5 * TILE_W, TILE_W, TILE_W);
static public const RECT_BLOCK_LandU :Rectangle = new Rectangle( 3 * TILE_W, 3 * TILE_W, TILE_W, TILE_W);
static public const RECT_BLOCK_RandU :Rectangle = new Rectangle( 4 * TILE_W, 3 * TILE_W, TILE_W, TILE_W);
static public const RECT_BLOCK_LandD :Rectangle = new Rectangle( 3 * TILE_W, 4 * TILE_W, TILE_W, TILE_W);
static public const RECT_BLOCK_RandD :Rectangle = new Rectangle( 4 * TILE_W, 4 * TILE_W, TILE_W, TILE_W);
//- Needle
static public const RECT_STEEL :Rectangle = new Rectangle( 6 * TILE_W, 1 * TILE_W, TILE_W, TILE_W);
static public const RECT_STEEL_L :Rectangle = new Rectangle( 5 * TILE_W, 1 * TILE_W, TILE_W, TILE_W);
static public const RECT_STEEL_R :Rectangle = new Rectangle( 7 * TILE_W, 1 * TILE_W, TILE_W, TILE_W);
static public const RECT_STEEL_U :Rectangle = new Rectangle( 6 * TILE_W, 0 * TILE_W, TILE_W, TILE_W);
static public const RECT_STEEL_D :Rectangle = new Rectangle( 6 * TILE_W, 2 * TILE_W, TILE_W, TILE_W);
static public const RECT_STEEL_LorU :Rectangle = new Rectangle( 5 * TILE_W, 0 * TILE_W, TILE_W, TILE_W);
static public const RECT_STEEL_RorU :Rectangle = new Rectangle( 7 * TILE_W, 0 * TILE_W, TILE_W, TILE_W);
static public const RECT_STEEL_LorD :Rectangle = new Rectangle( 5 * TILE_W, 2 * TILE_W, TILE_W, TILE_W);
static public const RECT_STEEL_RorD :Rectangle = new Rectangle( 7 * TILE_W, 2 * TILE_W, TILE_W, TILE_W);
static public const RECT_STEEL_LandU :Rectangle = new Rectangle( 8 * TILE_W, 0 * TILE_W, TILE_W, TILE_W);
static public const RECT_STEEL_RandU :Rectangle = new Rectangle( 9 * TILE_W, 0 * TILE_W, TILE_W, TILE_W);
static public const RECT_STEEL_LandD :Rectangle = new Rectangle( 8 * TILE_W, 1 * TILE_W, TILE_W, TILE_W);
static public const RECT_STEEL_RandD :Rectangle = new Rectangle( 9 * TILE_W, 1 * TILE_W, TILE_W, TILE_W);
static public const RECT_NEEDLE_L :Rectangle = new Rectangle( 5 * TILE_W, 4 * TILE_W, TILE_W, TILE_W);
static public const RECT_NEEDLE_R :Rectangle = new Rectangle( 7 * TILE_W, 4 * TILE_W, TILE_W, TILE_W);
static public const RECT_NEEDLE_U :Rectangle = new Rectangle( 6 * TILE_W, 3 * TILE_W, TILE_W, TILE_W);
static public const RECT_NEEDLE_D :Rectangle = new Rectangle( 6 * TILE_W, 5 * TILE_W, TILE_W, TILE_W);
static public const RECT_NEEDLE_LorU :Rectangle = new Rectangle( 5 * TILE_W, 3 * TILE_W, TILE_W, TILE_W);
static public const RECT_NEEDLE_RorU :Rectangle = new Rectangle( 7 * TILE_W, 3 * TILE_W, TILE_W, TILE_W);
static public const RECT_NEEDLE_LorD :Rectangle = new Rectangle( 5 * TILE_W, 5 * TILE_W, TILE_W, TILE_W);
static public const RECT_NEEDLE_RorD :Rectangle = new Rectangle( 7 * TILE_W, 5 * TILE_W, TILE_W, TILE_W);
//#Utility
static public const POS_ZERO:Point = new Point(0,0);
//Static Init
static public function Init(in_Graphic:DisplayObject):void
{
var x:int, y:int, i:int, j:int, index:int;
//m_BitmapData_Ori
{
m_BitmapData_Ori = new BitmapData(256, 256, true, 0x00000000);
m_BitmapData_Ori.draw(in_Graphic);
}
//m_Rect_Ground
{
m_Rect_Ground = new Vector.<Vector.<Rectangle> >(16);
for(i = 0; i < 16; ++i){
m_Rect_Ground[i] = new Vector.<Rectangle>(4);
switch(i){
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
//Empty
for(j = 0; j < 4; ++j){
m_Rect_Ground[i][j] = RECT_EMPTY;
}
break;
case 8:
case 9:
//XorY
m_Rect_Ground[i][0] = RECT_WALL_LorU;
m_Rect_Ground[i][1] = RECT_WALL_RorU;
m_Rect_Ground[i][2] = RECT_WALL_LorD;
m_Rect_Ground[i][3] = RECT_WALL_RorD;
break;
case 10:
case 11:
//X
m_Rect_Ground[i][0] = RECT_WALL_L;
m_Rect_Ground[i][1] = RECT_WALL_R;
m_Rect_Ground[i][2] = RECT_WALL_L;
m_Rect_Ground[i][3] = RECT_WALL_R;
break;
case 12:
case 13:
//U
m_Rect_Ground[i][0] = RECT_WALL_U;
m_Rect_Ground[i][1] = RECT_WALL_U;
m_Rect_Ground[i][2] = RECT_WALL_D;
m_Rect_Ground[i][3] = RECT_WALL_D;
break;
case 14:
//XandY
m_Rect_Ground[i][0] = RECT_WALL_LandU;
m_Rect_Ground[i][1] = RECT_WALL_RandU;
m_Rect_Ground[i][2] = RECT_WALL_LandD;
m_Rect_Ground[i][3] = RECT_WALL_RandD;
break;
case 15:
//Default
for(j = 0; j < 4; ++j){
m_Rect_Ground[i][j] = RECT_WALL;
}
break;
}
}
}
//m_Rect_Block
{
m_Rect_Block = new Vector.<Vector.<Rectangle> >(16);
for(i = 0; i < 16; ++i){
m_Rect_Block[i] = new Vector.<Rectangle>(4);
switch(i){
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
//Empty
for(j = 0; j < 4; ++j){
m_Rect_Block[i][j] = RECT_EMPTY;
}
break;
case 8:
case 9:
//XorY
m_Rect_Block[i][0] = RECT_BLOCK_LorU;
m_Rect_Block[i][1] = RECT_BLOCK_RorU;
m_Rect_Block[i][2] = RECT_BLOCK_LorD;
m_Rect_Block[i][3] = RECT_BLOCK_RorD;
break;
case 10:
case 11:
//X
m_Rect_Block[i][0] = RECT_BLOCK_L;
m_Rect_Block[i][1] = RECT_BLOCK_R;
m_Rect_Block[i][2] = RECT_BLOCK_L;
m_Rect_Block[i][3] = RECT_BLOCK_R;
break;
case 12:
case 13:
//U
m_Rect_Block[i][0] = RECT_BLOCK_U;
m_Rect_Block[i][1] = RECT_BLOCK_U;
m_Rect_Block[i][2] = RECT_BLOCK_D;
m_Rect_Block[i][3] = RECT_BLOCK_D;
break;
case 14:
//XandY
m_Rect_Block[i][0] = RECT_BLOCK_LandU;
m_Rect_Block[i][1] = RECT_BLOCK_RandU;
m_Rect_Block[i][2] = RECT_BLOCK_LandD;
m_Rect_Block[i][3] = RECT_BLOCK_RandD;
break;
case 15:
//Default
for(j = 0; j < 4; ++j){
m_Rect_Block[i][j] = RECT_BLOCK;
}
break;
}
}
}
//m_Rect_Needle
{
m_Rect_Needle = new Vector.<Vector.<Rectangle> >(16);
for(i = 0; i < 16; ++i){
m_Rect_Needle[i] = new Vector.<Rectangle>(4);
switch(i){
case 0:
case 1:
//Empty
for(j = 0; j < 4; ++j){
m_Rect_Needle[i][j] = RECT_EMPTY;
}
break;
case 2:
case 3:
//NeedleY
m_Rect_Needle[i][0] = RECT_NEEDLE_U;
m_Rect_Needle[i][1] = RECT_NEEDLE_U;
m_Rect_Needle[i][2] = RECT_NEEDLE_D;
m_Rect_Needle[i][3] = RECT_NEEDLE_D;
break;
case 4:
case 5:
//NeedleX
m_Rect_Needle[i][0] = RECT_NEEDLE_L;
m_Rect_Needle[i][1] = RECT_NEEDLE_R;
m_Rect_Needle[i][2] = RECT_NEEDLE_L;
m_Rect_Needle[i][3] = RECT_NEEDLE_R;
break;
case 6:
case 7:
//NeedleXorY
m_Rect_Needle[i][0] = RECT_NEEDLE_LorU;
m_Rect_Needle[i][1] = RECT_NEEDLE_RorU;
m_Rect_Needle[i][2] = RECT_NEEDLE_LorD;
m_Rect_Needle[i][3] = RECT_NEEDLE_RorD;
break;
case 8:
case 9:
//XorY
m_Rect_Needle[i][0] = RECT_STEEL_LorU;
m_Rect_Needle[i][1] = RECT_STEEL_RorU;
m_Rect_Needle[i][2] = RECT_STEEL_LorD;
m_Rect_Needle[i][3] = RECT_STEEL_RorD;
break;
case 10:
case 11:
//X
m_Rect_Needle[i][0] = RECT_STEEL_L;
m_Rect_Needle[i][1] = RECT_STEEL_R;
m_Rect_Needle[i][2] = RECT_STEEL_L;
m_Rect_Needle[i][3] = RECT_STEEL_R;
break;
case 12:
case 13:
//U
m_Rect_Needle[i][0] = RECT_STEEL_U;
m_Rect_Needle[i][1] = RECT_STEEL_U;
m_Rect_Needle[i][2] = RECT_STEEL_D;
m_Rect_Needle[i][3] = RECT_STEEL_D;
break;
case 14:
//XandY
m_Rect_Needle[i][0] = RECT_STEEL_LandU;
m_Rect_Needle[i][1] = RECT_STEEL_RandU;
m_Rect_Needle[i][2] = RECT_STEEL_LandD;
m_Rect_Needle[i][3] = RECT_STEEL_RandD;
break;
case 15:
//Default
for(j = 0; j < 4; ++j){
m_Rect_Needle[i][j] = RECT_STEEL;
}
break;
}
}
}
}
//==BG==
static public function CreateBackGroundGraphic(in_Map:Array):Bitmap
{
//Alias
var NumX:int = in_Map[0].length;
var NumY:int = in_Map.length;
//最終的な画像
var bmd:BitmapData = new BitmapData(NumX * PANEL_W, NumY * PANEL_W, true, 0x00000000);
bmd.lock();
//まずは遠景でクリア
FillBG(bmd);
//トゲ描画
DrawNeedle(bmd, in_Map);
//地形描画
DrawGround(bmd, in_Map);
bmd.unlock();
return new Bitmap(bmd);
}
//遠景によるクリア
static public function FillBG(io_BMD:BitmapData):void
{
var W:int = io_BMD.width;
var H:int = io_BMD.height;
var SrcRect:Rectangle = RECT_BG;
var DstPoint:Point = new Point();
for(var yy:int = 0; yy < H; yy += TILE_W){
DstPoint.y = yy;
for(var xx:int = 0; xx < W; xx += TILE_W){
DstPoint.x = xx;
io_BMD.copyPixels(m_BitmapData_Ori, SrcRect, DstPoint, null, null, true);
}
}
}
//トゲ描画
static public function DrawNeedle(io_BMD:BitmapData, in_Map:Array):void
{
//Alias
var NumX:int = in_Map[0].length;
var NumY:int = in_Map.length;
var xx:int, yy:int, i:int;
//Map => Bitmap_Base
//Mapの要素を元に、「0:空白」「1:地形」というBitmapを生成
var BitmapData_Base:BitmapData;
{
BitmapData_Base = new BitmapData(NumX, NumY, false, 0x0);
BitmapData_Base.lock();
for(yy = 0; yy < NumY; yy++){
for(xx = 0; xx < NumX; xx++){
switch(in_Map[yy][xx]){
case ActGameEngine.X:
BitmapData_Base.setPixel(xx, yy, 1);
break;
}
}
}
}
//Bitmap_Base => Bitmap_LU,Bitmap_RU,Bitmap_LD,Bitmap_RD
//Bitmap_Baseを元に、四隅の隣接状況をそれぞれ求める(Uniqueな値になるようにする)
//Uniqueな値から、対応するIndexへと変換する
var BitmapData_Quater:Vector.<BitmapData> = new Vector.<BitmapData>(4);
{
var rect:Rectangle = BitmapData_Base.rect;
//
for(i = 0; i < 4; i++){
//Init
var bmd:BitmapData = new BitmapData(NumX, NumY, false, 0x000000);
bmd.lock();
bmd.applyFilter(BitmapData_Base, rect, POS_ZERO, m_ConvFilter[i]);
BitmapData_Quater[i] = bmd;
}
}
//Draw
//上で求めたIndexに基づき描画
{
var DstPoint:Point = new Point(0,0);
var SrcRect:Rectangle = new Rectangle(0,0,TILE_W,TILE_W);
for(yy = 0; yy < NumY; yy++){
for(xx = 0; xx < NumX; xx++){
for(i = 0; i < 4; i++){
DstPoint.x = xx * PANEL_W + ((i&1)>>0) * TILE_W;
DstPoint.y = yy * PANEL_W + ((i&2)>>1) * TILE_W;
SrcRect = m_Rect_Needle[BitmapData_Quater[i].getPixel(xx, yy)][i];
io_BMD.copyPixels(m_BitmapData_Ori, SrcRect, DstPoint, null, null, true);
}
}
}
}
}
//地形描画
static public function DrawGround(io_BMD:BitmapData, in_Map:Array):void
{
//Alias
var NumX:int = in_Map[0].length;
var NumY:int = in_Map.length;
var xx:int, yy:int, i:int;
//Map => Bitmap_Base
//Mapの要素を元に、「0:空白」「1:地形」というBitmapを生成
var BitmapData_Base:BitmapData;
{
BitmapData_Base = new BitmapData(NumX, NumY, false, 0x0);
BitmapData_Base.lock();
for(yy = 0; yy < NumY; yy++){
for(xx = 0; xx < NumX; xx++){
switch(in_Map[yy][xx]){
case ActGameEngine.W:
BitmapData_Base.setPixel(xx, yy, 1);
break;
}
}
}
}
//Bitmap_Base => Bitmap_LU,Bitmap_RU,Bitmap_LD,Bitmap_RD
//Bitmap_Baseを元に、四隅の隣接状況をそれぞれ求める(Uniqueな値になるようにする)
//Uniqueな値から、対応するIndexへと変換する
var BitmapData_Quater:Vector.<BitmapData> = new Vector.<BitmapData>(4);
{
var rect:Rectangle = BitmapData_Base.rect;
//
for(i = 0; i < 4; i++){
//Init
var bmd:BitmapData = new BitmapData(NumX, NumY, false, 0x000000);
bmd.lock();
bmd.applyFilter(BitmapData_Base, rect, POS_ZERO, m_ConvFilter[i]);
BitmapData_Quater[i] = bmd;
}
}
//Draw
//上で求めたIndexに基づき描画
{
var DstPoint:Point = new Point(0,0);
var SrcRect:Rectangle = new Rectangle(0,0,TILE_W,TILE_W);
for(yy = 0; yy < NumY; yy++){
for(xx = 0; xx < NumX; xx++){
for(i = 0; i < 4; i++){
DstPoint.x = xx * PANEL_W + ((i&1)>>0) * TILE_W;
DstPoint.y = yy * PANEL_W + ((i&2)>>1) * TILE_W;
SrcRect = m_Rect_Ground[BitmapData_Quater[i].getPixel(xx, yy)][i];
io_BMD.copyPixels(m_BitmapData_Ori, SrcRect, DstPoint, null, null, true);
}
}
}
}
}
//==Block==
static public function CreateBlockGraphic(in_Map:Array):Bitmap
{
//Alias
var NumX:int = in_Map[0].length;
var NumY:int = in_Map.length;
//最終的な画像
var bmd:BitmapData = new BitmapData(NumX * PANEL_W, NumY * PANEL_W, true, 0x00000000);
bmd.lock();
//ブロック描画
DrawBlock(bmd, in_Map);
bmd.unlock();
return new Bitmap(bmd);
}
//ブロック描画
static public function DrawBlock(io_BMD:BitmapData, in_Map:Array):void
{
//Alias
var NumX:int = in_Map[0].length;
var NumY:int = in_Map.length;
var xx:int, yy:int, i:int;
//Map => Bitmap_Base
//Mapの要素を元に、「0:空白」「1:地形」というBitmapを生成
var BitmapData_Base:BitmapData;
{
BitmapData_Base = new BitmapData(NumX, NumY, false, 0x0);
BitmapData_Base.lock();
for(yy = 0; yy < NumY; yy++){
for(xx = 0; xx < NumX; xx++){
switch(in_Map[yy][xx]){
case ActGameEngine.L:
BitmapData_Base.setPixel(xx, yy, 1);
break;
}
}
}
}
//Bitmap_Base => Bitmap_LU,Bitmap_RU,Bitmap_LD,Bitmap_RD
//Bitmap_Baseを元に、四隅の隣接状況をそれぞれ求める(Uniqueな値になるようにする)
//Uniqueな値から、対応するIndexへと変換する
var BitmapData_Quater:Vector.<BitmapData> = new Vector.<BitmapData>(4);
{
var rect:Rectangle = BitmapData_Base.rect;
//
for(i = 0; i < 4; i++){
//Init
var bmd:BitmapData = new BitmapData(NumX, NumY, false, 0x000000);
bmd.lock();
bmd.applyFilter(BitmapData_Base, rect, POS_ZERO, m_ConvFilter[i]);
BitmapData_Quater[i] = bmd;
}
}
//Draw
//上で求めたIndexに基づき描画
{
var DstPoint:Point = new Point(0,0);
var SrcRect:Rectangle = new Rectangle(0,0,TILE_W,TILE_W);
for(yy = 0; yy < NumY; yy++){
for(xx = 0; xx < NumX; xx++){
for(i = 0; i < 4; i++){
DstPoint.x = xx * PANEL_W + ((i&1)>>0) * TILE_W;
DstPoint.y = yy * PANEL_W + ((i&2)>>1) * TILE_W;
SrcRect = m_Rect_Block[BitmapData_Quater[i].getPixel(xx, yy)][i];
io_BMD.copyPixels(m_BitmapData_Ori, SrcRect, DstPoint, null, null, true);
}
}
}
}
}
//==Player==
static public function CreatePlayerGraphic():Vector.<BitmapData>{
var result:Vector.<BitmapData> = new Vector.<BitmapData>(Player.GRAPHIC_NUM);
var mtx:Matrix = new Matrix(1,0,0,1, 0,0);
for(var i:int = 0; i < Player.GRAPHIC_NUM; i++){
var bmd:BitmapData = new BitmapData(24, 32, true, 0x00000000);
mtx.tx = -i*24;
mtx.ty = -96;
bmd.draw(m_BitmapData_Ori, mtx);
result[i] = bmd;
}
return result;
}
//==Goal==
static public function CreateGoalGraphic():Bitmap{
var bmd:BitmapData = new BitmapData(ActGameEngine.PANEL_W, ActGameEngine.PANEL_W, true, 0x88FFFFFF);
bmd.copyPixels(m_BitmapData_Ori, RECT_GOAL, POS_ZERO);
return new Bitmap(bmd);
}
}