ピタゴラ・アクト(Pitagola Act)
ダッシュパネルを配置して、ボールをゴールまで運ぶピタゴラ装置風ゲーム
操作方法(How To Play)
・ドラッグ&ドロップ(Drag & Drop)
・ダッシュパネルの配置(Set dash-panel)
比較用
・Android版(Air)
・https://play.google.com/store/apps/details?id=air.showohealer.game.airprototype
/**
* 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/bPZ0
*/
/*
ピタゴラ・アクト(Pitagola Act)
・ダッシュパネルを配置して、ボールをゴールまで運ぶピタゴラ装置風ゲーム
操作方法(How To Play)
・ドラッグ&ドロップ(Drag & Drop)
・ダッシュパネルの配置(Set dash-panel)
比較用
・Android版(Air)
・https://play.google.com/store/apps/details?id=air.showohealer.game.airprototype
*/
/*
ToDo
*/
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 DragAndDropAct extends Sprite {
//==File==
//*
static public const BITMAP_URL:String = "http://assets.wonderfl.net/images/related_images/7/7e/7ef9/7ef964ba40e4df1db26038f5dd8023c843ff0fef";
/*/
[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;
//リストの高さ
static public const FOOTER_H:int = 49;//465 - 32*14
//アイコンの大きさ
static public const ITEM_W:int = 48;
//アイテムの種類
public const ITEM_VAL:Vector.<int> = new <int>[
ActGameEngine.DL,
ActGameEngine.DU,
ActGameEngine.DR,
];
//Map
static public var MAP:Array;
//==Var==
//Pseudo Singleton
static public var Instance:DragAndDropAct;
//Engine
public var m_ActGameEngine:ActGameEngine = new ActGameEngine();
//Layer
public var m_Layer_GameRoot:Sprite = new Sprite();
public var m_Layer_InterfaceRoot:Sprite = new Sprite();
//Footer
public var m_Item:Vector.<Sprite>;
//Dragまわり
public var m_DragIndex:int = -1;
public var m_DragSrcX:int = 0;
public var m_DragSrcY:int = 0;
public var m_DragBitmap:Bitmap = new Bitmap();
public var m_DropCrossGraphic:Sprite = new Sprite();
public var m_DragHelpView:Bitmap;
//==Function==
//Init
public function DragAndDropAct() {
//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
{
var i:int;
var bmp:Bitmap;
var bmd:BitmapData;
const HideColor:uint = 0x88000000;
const AppearColor:uint = 0x00000000;
//Pseudo Singleton
{
Instance = this;
}
//BG
{
addChild(new Bitmap(new BitmapData(VIEW_W, VIEW_H, false, 0x808080)));
}
//Layer
{
addChild(m_Layer_GameRoot);
addChild(m_Layer_InterfaceRoot);
}
//Clippnig
{
m_Layer_GameRoot.scrollRect = new Rectangle(0,0, VIEW_W, VIEW_H-FOOTER_H);
}
//m_DragHelpView
{
bmd = new BitmapData(VIEW_W, VIEW_H, true, HideColor);
var text:TextField = new TextField();
text.selectable = false;
text.autoSize = TextFieldAutoSize.LEFT;
text.defaultTextFormat = new TextFormat('Verdana', 64, 0xFFFFFF, true);
text.text = "Drag & Drop\n ↑ ↑ ↑";
var mtx:Matrix = new Matrix(1,0,0,1, VIEW_W/2 - text.textWidth/2, VIEW_H/2);
bmd.draw(text, mtx);
m_DragHelpView = new Bitmap(bmd);
m_Layer_InterfaceRoot.addChild(m_DragHelpView);
//m_DragHelpView.visible = false;
}
//Footer
{
var footer:Sprite = new Sprite();
footer.y = VIEW_H - FOOTER_H;
m_Layer_InterfaceRoot.addChild(footer);
//Window
footer.addChild(new Bitmap(new BitmapData(VIEW_W, FOOTER_H, false, 0xFFFFFF)));
//Item
var item:Sprite;
var ItemNum:int = ITEM_VAL.length;
m_Item = new Vector.<Sprite>(ItemNum);
for(i = 0; i < ItemNum; ++i){
bmp = new Bitmap(ImageManager.GetDashPanelGraphic(ITEM_VAL[i]));
bmp.x = -ActGameEngine.PANEL_W/2;
bmp.y = -ActGameEngine.PANEL_W/2;
item = new Sprite();
item.addChild(bmp);
item.x = VIEW_W/2 + (i - 1) * VIEW_W/4;
item.y = FOOTER_H/2;
item.scaleX = item.scaleY = 1.0 * ITEM_W / ActGameEngine.PANEL_W;
footer.addChild(item);
m_Item[i] = item;
}
}
//m_DragBitmap
{
m_Layer_InterfaceRoot.addChild(m_DragBitmap);
m_DragBitmap.visible = false;
}
//Touch
{
stage.addEventListener(MouseEvent.MOUSE_DOWN, OnMouseDown);
stage.addEventListener(MouseEvent.MOUSE_MOVE, OnMouseMove);
stage.addEventListener(MouseEvent.MOUSE_UP, OnMouseUp);
}
//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 C:int = ActGameEngine.L;//連結ブロック
const B:int = ActGameEngine.B;//壊せる箱
const U:int = ActGameEngine.DU;//ダッシュブロック
const D:int = ActGameEngine.DD;//ダッシュブロック
const L:int = ActGameEngine.DL;//ダッシュブロック
const R:int = ActGameEngine.DR;//ダッシュブロック
MAP = [
[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,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,W,X,X,X,X,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
[W,O,O,O,O,O,O,O,O,O,C,O,C,O,C,W,W,W,W,W,W,W,W,W,W,W,W,W,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,O,W,W,W,W,W,W,R,R,R,R,R,R,O,W,W,W,W,W,W,W,W,C,W,W,C,W,W,W,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
[W,O,W,W,W,W,W,W,W,W,W,W,W,W,C,W,W,W,W,W,W,W,W,C,W,W,C,W,W,W,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
[W,O,W,W,W,W,W,W,W,W,W,W,W,W,O,W,W,W,W,W,W,W,W,C,W,W,C,W,W,W,O,O,O,O,W,O,O,O,O,O,O,O,W,O,O,O,O,O,O,O,C,O,O,O,O,W],
[W,B,W,W,W,W,W,W,W,O,O,O,O,O,C,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,O,W,W,O,W,L,L,L,W,W,W,W,L,O,W],
[W,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,O,O,O,O,C,C,C,C,C,W,W,O,W,W,O,W,W,W,W,W,W,W,W,W,O,W],
[W,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,O,O,O,O,W,W,W,W,W,W,W,O,W,W,O,W,W,W,W,W,W,W,W,W,O,U],
[W,B,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,X,X,X,X,W,W,W,W,W,W,W,C,C,C,O,W,W,W,W,W,W,W,W,W,O,U],
[W,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,O,W,W,O,W,W,W,W,W,W,W,W,W,O,U],
[W,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,O,W,W,O,W,W,W,W,W,W,W,W,W,O,U],
[W,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,O,O,O,O,W,W,W,W,W,W,W,W,W,O,U],
[W,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,O,O,O,O,W,W,W,W,W,W,W,W,W,O,U],
[W,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,O,U],
[W,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,O,U],
[W,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,O,U],
[W,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,O,U],
[W,O,W,W,W,W,W,W,O,O,W,W,W,W,W,W,O,O,O,B,O,O,O,W,W,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,O,W,W,W,W,W,W,O,O,W,W,W,W,W,W,O,O,O,B,O,O,O,W,W,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,B,O,O,B,B,B,B,O,O,W,W,W,W,W,W,O,O,O,B,O,O,O,W,W,O,O,O,O,G,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,W,W,W,W,W,W,W,B,W,W,W,W,W,W,W,O,O,O,B,O,O,O,W,W,O,O,O,O,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,O,U],
[W,W,W,W,W,W,W,W,O,W,W,W,W,W,W,W,O,O,O,B,O,O,O,W,W,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,W,W,W,W,W,W,W,O,O,O,O,O,O,O,O,O,O,O,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,W,W,W,W,W,W,O,U],
[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,O,U],
[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,O,U],
[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,O,U],
[W,W,W,W,R,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,O,U],
[W,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,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,O,U],
[W,O,O,O,O,O,O,O,O,O,O,O,W,O,O,O,O,O,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,O,U],
[W,O,P,O,O,W,W,W,W,W,O,O,W,O,O,O,O,O,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,O,U],
[W,W,W,W,W,W,W,O,O,O,O,O,W,O,O,O,O,O,O,O,O,O,W,W,W,W,W,U,U,U,U,U,U,W,W,W,W,W,W,U,U,U,U,U,U,W,W,W,W,W,W,W,W,W,O,U],
[W,W,W,W,W,W,W,O,O,W,W,W,W,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,W],
[W,W,W,W,W,W,W,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,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,W],
[W,W,W,W,W,W,W,O,O,O,O,O,O,O,O,O,X,W,W,W,W,W,W,W,W,W,W,U,O,O,O,O,W,W,W,W,W,W,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,X,X,X,X,W,W,W,W,W,W,W,W,X,X,X,X,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 - FOOTER_H);
}
//Graphic : Drop Cross
{
var TileNumX:int = VIEW_W / ActGameEngine.PANEL_W + 1;
var TileNumY:int = VIEW_H / ActGameEngine.PANEL_W + 1;
var BmdW:int = TileNumX + 1 + TileNumX;
var BmdH:int = TileNumY + 1 + TileNumY;
bmd = new BitmapData(BmdW, BmdH, true, HideColor);
bmd.fillRect(new Rectangle(TileNumX, 0, 1, BmdH), AppearColor);
bmd.fillRect(new Rectangle(0, TileNumY, BmdW, 1), AppearColor);
bmp = new Bitmap(bmd);
bmp.x -= TileNumX;
bmp.y -= TileNumY;
m_DropCrossGraphic.addChild(bmp);
m_ActGameEngine.m_Root_Game.addChild(m_DropCrossGraphic);
m_DropCrossGraphic.scaleX = m_DropCrossGraphic.scaleY = ActGameEngine.PANEL_W;
m_DropCrossGraphic.visible = false;
}
//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;
//何かをドラッグ中ならゲーム画面は停止する
if(0 <= m_DragIndex){
return;
}
m_ActGameEngine.Update(DeltaTime);
}
//Touch
private function OnMouseDown(e:MouseEvent):void{
//Alias
const PANEL_W:int = ActGameEngine.PANEL_W;
//すでに何かドラッグしていたらムシ
if(0 <= m_DragIndex){
return;
}
//どのパネルかをタッチしているのならドラッグ開始
var num:int = m_Item.length;
for(var i:int = 0; i < num; ++i){
var item:Sprite = m_Item[i];
//タッチの範囲チェック
var rel_x:int = item.mouseX;
var rel_y:int = item.mouseY;
if(rel_x < -ITEM_W/2 || ITEM_W/2 < rel_x || rel_y < -ITEM_W/2 || ITEM_W/2 < rel_y){
continue;//範囲外
}
//タッチされたのでドラッグ開始
m_DragIndex = i;
m_DragSrcX = mouseX;
m_DragSrcY = mouseY;
m_DragBitmap.bitmapData = ImageManager.GetDashPanelGraphic(ITEM_VAL[m_DragIndex]);
//!!画面を白黒化して時間停止
//→ドラッグ先の強調と合わせて「ラインの幅だけ透明で、他が黒半透明のBitmap」をかぶせる(ラインが範囲外になるようにしつつ)
// ・さらにサイズなどの削減のため、ラインは1ドットにしておいてPANEL_Wだけ拡大
m_DragHelpView.visible = true;
m_ActGameEngine.m_Root_Game.removeChild(m_DropCrossGraphic);
m_ActGameEngine.m_Root_Game.addChild(m_DropCrossGraphic);//再登録して他のやつより上に表示
break;
}
}
private function OnMouseMove(e:MouseEvent):void{
//ドラッグしているものがなければムシ
if(m_DragIndex < 0){
return;
}
//まだフッタ上にあるなら何もしない
if(VIEW_H - FOOTER_H < mouseY){
return;
}
//ドラッグ先のラインを光らせて強調
var IndexX:int = m_ActGameEngine.m_Root_Game.mouseX / ActGameEngine.PANEL_W;//Round
var IndexY:int = m_ActGameEngine.m_Root_Game.mouseY / ActGameEngine.PANEL_W;
m_DropCrossGraphic.x = IndexX * ActGameEngine.PANEL_W;
m_DropCrossGraphic.y = IndexY * ActGameEngine.PANEL_W;
m_DragBitmap.x = m_Layer_InterfaceRoot.mouseX - ActGameEngine.PANEL_W/2;
m_DragBitmap.y = m_Layer_InterfaceRoot.mouseY - ActGameEngine.PANEL_W/2;
m_DragBitmap.visible = true;
m_DropCrossGraphic.visible = true;
m_DragHelpView.visible = false;
}
private function OnMouseUp(e:MouseEvent):void{
//ドラッグしているものがなければムシ
if(m_DragIndex < 0){
return;
}
//Clear
var MapVal:int = ITEM_VAL[m_DragIndex];
m_DropCrossGraphic.visible = false;
m_DragHelpView.visible = false;
m_DragBitmap.visible = false;
m_DragIndex = -1;
//フッタ上にあるならキャンセル扱い
if(VIEW_H - FOOTER_H < mouseY){
return;
}
//ドラッグ先に配置
var IndexX:int = m_ActGameEngine.m_Root_Game.mouseX / ActGameEngine.PANEL_W;//Round
var IndexY:int = m_ActGameEngine.m_Root_Game.mouseY / ActGameEngine.PANEL_W;
//範囲制限
var NumX:int = MAP[0].length;
var NumY:int = MAP.length;
if(IndexX < 0){IndexX = 0;}
if(NumX <= IndexX){IndexX = NumX-1;}
if(IndexY < 0){IndexY = 0;}
if(NumY <= IndexY){IndexY = NumY-1;}
//壁かすでにパネルのある箇所のみ設置可能
switch(MAP[IndexY][IndexX]){
case ActGameEngine.W:
case ActGameEngine.DU:
case ActGameEngine.DD:
case ActGameEngine.DL:
case ActGameEngine.DR:
break;
default:
return;
}
var obj:DashPanel = DashPanel.CreateOrChange(IndexX, IndexY, MapVal, m_ActGameEngine.m_PhysWorld);
if(obj != null){
m_ActGameEngine.m_GameObject.push(obj);
m_ActGameEngine.m_Root_Game.addChild(obj);
}
}
}
}
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 B:int = s_BlockIndexIter++;//壊せる箱
static public const DU:int = s_BlockIndexIter++;//ダッシュブロック
static public const DD:int = s_BlockIndexIter++;//ダッシュブロック
static public const DL:int = s_BlockIndexIter++;//ダッシュブロック
static public const DR: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);
//グラフィックがないので描画登録はなし
}
//Breakable Box
{
var box_arr:Vector.<BreakableBox> = BreakableBox.Create(in_Map, m_PhysWorld);
num = box_arr.length;
for(i = 0; i < num; ++i){
m_GameObject.push(box_arr[i]);
m_Root_Game.addChild(box_arr[i]);
}
}
//Dash Panel
{
var dash_arr:Vector.<DashPanel> = DashPanel.Create(in_Map, m_PhysWorld);
num = dash_arr.length;
for(i = 0; i < num; ++i){
m_GameObject.push(dash_arr[i]);
m_Root_Game.addChild(dash_arr[i]);
}
}
//Block
{
var block_arr:Vector.<Block> = Block.Create(in_Map, m_PhysWorld);
num = block_arr.length;
for(i = 0; i < num; ++i){
m_GameObject.push(block_arr[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);
m_GameObject[i].Update_Post();
}
}
//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;//0.05;
//
public var m_GamePosX_Prev:Number = 0;
public var m_GamePosY_Prev:Number = 0;
public var m_GameVelX_Prev:Number = 0;
public var m_GameVelY_Prev:Number = 0;
//HP
public var m_HP:int = 1;
//Flag
public var m_UseSleep:Boolean = true;
public var m_GroundFlag:Boolean = false;
//==Function==
//#Common
//Update
public function Update(in_DeltaTime:Number):void{
}
public function Update_Post():void{
if(m_PhysBody != null)
{
//Vel
{
//PhysPos
var PhysPos:b2Vec2;
{
PhysPos = m_PhysBody.GetPosition();
}
//PhysPos => GamePos
{
m_GamePosX_Prev = PhysPos.x * ActGameEngine.PHYS_SCALE;
m_GamePosY_Prev = PhysPos.y * ActGameEngine.PHYS_SCALE;
}
}
//Vel
{
//PhysVel
var PhysVel:b2Vec2;
{
PhysVel = m_PhysBody.GetLinearVelocity();
}
//PhysVel => GameVel
{
m_GameVelX_Prev = PhysVel.x * ActGameEngine.PHYS_SCALE;
m_GameVelY_Prev = PhysVel.y * ActGameEngine.PHYS_SCALE;
}
}
}
}
//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_Box(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 = 0.3;//0.5;
// 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_Box(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 : Dynamic : Circle
public function CreateCollision_Dynamic_Circle(rad:Number):void{
//Bodyの用意
ReadyBody();
var shapeDef:b2CircleDef = new b2CircleDef();
shapeDef.radius = rad / 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_Box(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:
case ActGameEngine.DU:
case ActGameEngine.DD:
case ActGameEngine.DL:
case ActGameEngine.DR:
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_Box(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_Box(-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==
//==Var==
//==Function==
//Init
public function Init():void{
//Alias
const PANEL_W:int = ActGameEngine.PANEL_W;
//グラフィック
{
var bmp:Bitmap = new Bitmap(ImageManager.GetPlayerGraphic());
bmp.x = -PANEL_W/2;
bmp.y = -PANEL_W/2;
addChild(bmp);
}
//コリジョン
{
CreateCollision_Dynamic_Circle((PANEL_W-1) * 0.5);
}
}
//Update
override public function Update(in_DeltaTime:Number):void{
}
//Damage
override public function OnDamage(in_Val:int):void{
if(m_HP <= 0){
return;
}
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_Box(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;
}
}
//DashPanel
class DashPanel extends GameObject
{
//==Static==
static public var s_GameObjMap:Vector.<Vector.<DashPanel> >;
static public function Create(in_Map:Array, in_PhysWorld:b2World):Vector.<DashPanel>{
//
var result:Vector.<DashPanel> = new Vector.<DashPanel>();
var obj:DashPanel;
var xx:int, yy:int;
//Create
{
var NumX:int = in_Map[0].length;
var NumY:int = in_Map.length;
s_GameObjMap = new Vector.<Vector.<DashPanel> >(NumY);
for(yy = 0; yy < NumY; ++yy){
s_GameObjMap[yy] = new Vector.<DashPanel>(NumX);
for(xx = 0; xx < NumX; ++xx){
s_GameObjMap[yy][xx] = null;
var map:int = in_Map[yy][xx];
switch(map){
case ActGameEngine.DU:
case ActGameEngine.DD:
case ActGameEngine.DL:
case ActGameEngine.DR:
obj = CreateOrChange(xx, yy, map, in_PhysWorld);
result.push(obj);
break;
}
}
}
}
return result;
}
static public function CreateOrChange(in_X:int, in_Y:int, in_MapVal:int, in_PhysWorld:b2World):DashPanel{
//新規追加の場合のみインスタンスを返し、すでにあるやつの変更になるならNullを返す
var obj:DashPanel = s_GameObjMap[in_Y][in_X];
if(obj == null){
//新規
obj = new DashPanel();
obj.m_PhysWorld = in_PhysWorld;
obj.x = in_X * ActGameEngine.PANEL_W;
obj.y = in_Y * ActGameEngine.PANEL_W;
obj.Init(in_MapVal)
s_GameObjMap[in_Y][in_X] = obj;
return obj;
}else{
//変更
obj.ChangeDir(in_MapVal);
return null;
}
}
//==Const==
static public const MOVE_POW_X:Number = 1100.0;
// static public const MOVE_POW_Y:Number = 5100.0;
static public const MOVE_VEL_Y:Number = 420.0;
static public const DEC_RATIO:Number = 0.7;
//==Var==
public var m_MapVal:int = ActGameEngine.DU;
public var m_Bitmap:Bitmap = new Bitmap();
//==Function==
//Init
public function Init(in_MapVal:int):void{
//Alias
const PANEL_W:int = ActGameEngine.PANEL_W;
//Phys
{
CreateSensor_Box(-PANEL_W/16, -PANEL_W/16, PANEL_W*18/16, PANEL_W*18/16);
}
//Graphic
{
addChild(m_Bitmap);
}
//Dir
{
ChangeDir(in_MapVal);
}
}
//Change : Dir
public function ChangeDir(in_MapVal:int):void{
//Param
{
m_MapVal = in_MapVal;
}
//Graphic
{
m_Bitmap.bitmapData = ImageManager.GetDashPanelGraphic(m_MapVal);
}
}
//OnContact
override public function OnContact(in_Obj:GameObject, in_Nrm:Vector3D):void{
//対象の速度の変更
var body:b2Body = in_Obj.m_PhysBody;
if(body == null){return;}
var DeltaTime:Number = 1.0 / stage.frameRate;
//PhysVel
var PhysVel:b2Vec2;
{
PhysVel = body.GetLinearVelocity();
}
//PhysVel => GameVel
var GameVX:Number;
var GameVY:Number;
{
GameVX = PhysVel.x * ActGameEngine.PHYS_SCALE;
GameVY = PhysVel.y * ActGameEngine.PHYS_SCALE;
}
//GameVelの補正
{
var GameAX:Number;
var GameAY:Number;
switch(m_MapVal){
case ActGameEngine.DU:
case ActGameEngine.DD:
// GameAY = (m_MapVal != ActGameEngine.DU)? MOVE_POW_Y: -MOVE_POW_Y;
// GameVY += GameAY * DeltaTime;
// GameVY *= Math.pow(DEC_RATIO, 10.0*DeltaTime);
GameVY = (m_MapVal != ActGameEngine.DU)? MOVE_VEL_Y: -MOVE_VEL_Y;
break;
case ActGameEngine.DL:
case ActGameEngine.DR:
GameAX = (m_MapVal != ActGameEngine.DL)? MOVE_POW_X: -MOVE_POW_X;
GameVX += GameAX * DeltaTime;
GameVX *= Math.pow(DEC_RATIO, 10.0*DeltaTime);
break;
}
}
//上矢印の吸着だけ特殊処理(バウンドを抑える)
{
if(m_MapVal == ActGameEngine.DU && in_Obj is Player)
{
if(this.y + ActGameEngine.PANEL_W < in_Obj.y)
{
if(this.x <= in_Obj.x && in_Obj.x < this.x + ActGameEngine.PANEL_W)
{//真下
GameVY = -200;
in_Obj.y = this.y + ActGameEngine.PANEL_W * 1.5;
var PhysPos:b2Vec2 = body.GetPosition();
PhysPos.y = in_Obj.y / ActGameEngine.PHYS_SCALE;
body.GetXForm().position.SetV(PhysPos);
}
else
{//斜め下
//GameVY = -200;
GameVY = PhysVel.y * ActGameEngine.PHYS_SCALE;
}
}
}
}
//GameVel => PhysVel
{
PhysVel.x = GameVX / ActGameEngine.PHYS_SCALE;
PhysVel.y = GameVY / ActGameEngine.PHYS_SCALE;
}
//Apply
{
body.SetLinearVelocity(PhysVel);
}
//相手のスリープを解除
{
body.WakeUp();
}
}
}
class BreakableBox extends GameObject
{
//==Const==
static public const BREAK_VEL_THRESHOLD:Number = 50;
static public const GAP_VEL_RATIO_MIN:Number = 10.0;
static public const GAP_VEL_RATIO_MAX:Number = 10.0;
static public const ROT_VEL_MAX:Number = 3.0 * 360;
static public const PIECE_RECT:Vector.<Rectangle> = new <Rectangle>[
new Rectangle( 0, 0, 32, 4),//U
new Rectangle( 0,28, 32, 4),//D
new Rectangle( 0, 0, 4,32),//L
new Rectangle(28, 0, 4,32),//R
new Rectangle( 4, 4, 24, 4),//Inner
new Rectangle( 4, 8, 12, 4),
new Rectangle(16, 8, 12, 4),
new Rectangle( 4,12, 24, 4),//
new Rectangle( 4,16, 12, 4),
new Rectangle(16,16, 12, 4),
new Rectangle( 4,20, 24, 4),//
new Rectangle( 4,24, 12, 4),
new Rectangle(16,24, 12, 4),
];
static public const POS_ZERO:Point = new Point(0,0);
//==Static==
static public function Create(in_Map:Array, in_PhysWorld:b2World):Vector.<BreakableBox>{
var result:Vector.<BreakableBox> = new Vector.<BreakableBox>();
//
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.B){
var obj:BreakableBox = new BreakableBox(xx, yy, in_PhysWorld);
result.push(obj);
}
}
}
return result;
}
//==Var==
public var m_Bitmap_Box:Bitmap;
public var m_Piece:Vector.<BoxPiece> = null;
//==Function==
//Init
public function BreakableBox(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
{
CreateCollision_Fix_Box(0, 0, PANEL_W, PANEL_W);
}
//Graphic
{
m_Bitmap_Box = new Bitmap(ImageManager.GetBreakableBoxGraphic());
addChild(m_Bitmap_Box);
}
}
//Update
override public function Update(in_DeltaTime:Number):void{
if(m_Piece != null){
var num:int = PIECE_RECT.length;
for(var i:int = 0; i < num; ++i){
m_Piece[i].Update(in_DeltaTime);
}
}
}
//Contact :
override public function OnContact(in_Obj:GameObject, in_Nrm:Vector3D):void{
//Check
if(! (in_Obj is Player)){
return;
}
//Check Vel
{
//Check
{
var Dot:Number = in_Obj.m_GameVelX_Prev * in_Nrm.x + in_Obj.m_GameVelY_Prev * in_Nrm.y;
if(Math.abs(Dot) < BREAK_VEL_THRESHOLD){
return;
}
}
}
//自滅
const DamageVal:int = 1;
OnDamage(DamageVal);
if(m_HP <= 0){
CreatePieces(in_Obj.m_GameVelX_Prev, in_Obj.m_GameVelY_Prev);
}
}
//Damage
override public function OnDamage(in_Val:int):void{
if(m_HP <= 0){
return;
}
m_HP -= in_Val;
}
//Create : Pieces
public function CreatePieces(in_HitVX:Number, in_HitVY:Number):void{
//Alias
const PANEL_W:int = ActGameEngine.PANEL_W;
//Graphic : Box : Hide
{
removeChild(m_Bitmap_Box);
}
//Create Pieces
{
var num:int = PIECE_RECT.length;
m_Piece = new Vector.<BoxPiece>(num);
for(var i:int = 0; i < num; ++i)
{
var rect:Rectangle = PIECE_RECT[i];
var bmd:BitmapData = new BitmapData(rect.width, rect.height, false, 0x000000);
bmd.copyPixels(m_Bitmap_Box.bitmapData, rect, POS_ZERO);
var CenterX:Number = rect.x + rect.width/2;
var CenterY:Number = rect.y + rect.height/2;
var GapX:Number = CenterX - PANEL_W/2;
var GapY:Number = CenterY - PANEL_W/2;
var piece:BoxPiece = new BoxPiece(bmd);
piece.x = CenterX;
piece.y = CenterY;
piece.vx = in_HitVX + GapX * Lerp(GAP_VEL_RATIO_MIN, GAP_VEL_RATIO_MIN, Math.random());
piece.vy = in_HitVY + GapY * Lerp(GAP_VEL_RATIO_MIN, GAP_VEL_RATIO_MIN, Math.random());
piece.rotv = Lerp(-ROT_VEL_MAX, ROT_VEL_MAX, Math.random());
addChild(piece);
m_Piece[i] = piece;
}
}
//Collision
{
m_PhysWorld.DestroyBody(m_PhysBody);
m_PhysBody = null;
}
}
//Util : Lerp
public function Lerp(in_Src:Number, in_Dst:Number, in_Ratio:Number):Number{
return (in_Src * (1 - in_Ratio)) + (in_Dst * in_Ratio);
}
}
//BoxPiece
class BoxPiece extends Sprite
{
//==Const==
static public const GRAVITY:Number = 1000;
//==Var==
public var vx:Number = 0;
public var vy:Number = 0;
public var rotv:Number = 0;
//==Function==
//Init
public function BoxPiece(in_BMD:BitmapData){
var bmp:Bitmap = new Bitmap(in_BMD);
bmp.x = -in_BMD.width/2;
bmp.y = -in_BMD.height/2;
addChild(bmp);
}
//Update
public function Update(in_DeltaTime:Number):void{
this.x += vx * in_DeltaTime;
this.y += vy * in_DeltaTime + 0.5*GRAVITY*in_DeltaTime*in_DeltaTime;
vy += GRAVITY*in_DeltaTime;
this.rotation = rotv * in_DeltaTime;
}
}
//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;
static public var m_BitmapData_DashPanel:Vector.<BitmapData> = new Vector.<BitmapData>(4);
static public var m_BitmapData_BreakableBox:BitmapData;
static public var m_BitmapData_Player:BitmapData;
static public var m_BitmapData_Goal: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, SrcRect:Rectangle;
//m_BitmapData_Ori
{
m_BitmapData_Ori = new BitmapData(256, 256, true, 0x00000000);
m_BitmapData_Ori.draw(in_Graphic);
}
//DashPanel
{
for(i = 0; i < 4; ++i){
SrcRect = new Rectangle(16*10, 0, 32, 32);
if((i & 1) != 0){SrcRect.x += 32;}
if((i & 2) != 0){SrcRect.y += 32;}
m_BitmapData_DashPanel[i] = new BitmapData(32, 32, true, 0x00000000);
m_BitmapData_DashPanel[i].copyPixels(m_BitmapData_Ori, SrcRect, POS_ZERO);
}
}
//Breakable Box
{
SrcRect = new Rectangle(16*14, 0, 32, 32);
m_BitmapData_BreakableBox = new BitmapData(32, 32, true, 0x00000000);
m_BitmapData_BreakableBox.copyPixels(m_BitmapData_Ori, SrcRect, POS_ZERO);
}
//Player
{
SrcRect = new Rectangle(0, 16*6, 32, 32);
m_BitmapData_Player = new BitmapData(32, 32, true, 0x00000000);
m_BitmapData_Player.copyPixels(m_BitmapData_Ori, SrcRect, POS_ZERO);
}
//Goal
{
SrcRect = new Rectangle(16*14, 32, 32, 32);
m_BitmapData_Goal = new BitmapData(32, 32, true, 0x00000000);
m_BitmapData_Goal.copyPixels(m_BitmapData_Ori, SrcRect, POS_ZERO);
}
//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:
case ActGameEngine.DU:
case ActGameEngine.DD:
case ActGameEngine.DL:
case ActGameEngine.DR:
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 GetPlayerGraphic():BitmapData{
return m_BitmapData_Player;
}
//==Goal==
static public function CreateGoalGraphic():Bitmap{
return new Bitmap(m_BitmapData_Goal);
}
//==Dash Panel==
static public function GetDashPanelGraphic(in_MapVal:int):BitmapData{
switch(in_MapVal){
case ActGameEngine.DU:
return m_BitmapData_DashPanel[0];
case ActGameEngine.DD:
return m_BitmapData_DashPanel[1];
case ActGameEngine.DL:
return m_BitmapData_DashPanel[2];
case ActGameEngine.DR:
return m_BitmapData_DashPanel[3];
}
return null;
}
//==Breakable Box==
static public function GetBreakableBoxGraphic():BitmapData{
return m_BitmapData_BreakableBox;
}
}