Ball & Maze (Template)
ベタなBall & Mazeのテンプレート
Androidの加速度センサーを試すためのコードだが、実機をまだ持っていないので未確認。
PCでも確認できるように、マウス位置で重力の制御が可能。
PC:Mouse
Android:Accelerometer
/**
* 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/jsKn
*/
/*
Ball & Maze (Template)
- for Android (and PC)
概要
- Androidで加速度センサーを使ってベタなBall&Mazeを作るためのテンプレート
- ただし、実機を持っていないのでまだ検証できていない
*/
package {
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.net.*;
import flash.system.*;
import flash.text.*;
//Box2D
import Box2D.Dynamics.*;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Common.*;
import Box2D.Common.Math.*;
import Box2D.Dynamics.Joints.*;
[SWF(width="465", height="465", frameRate="30", backgroundColor="0x004400")]
public class GameMain extends Sprite {
//==Const==
//画像ファイル名
//*
static public const URL_BLOCKS:String = "http://assets.wonderfl.net/images/related_images/c/cd/cdde/cdde14248108db9327a151f43ac41fa70b897c11";
// static public const URL_PLAYER:String = "http://assets.wonderfl.net/images/related_images/0/0f/0fb1/0fb141ba90fe1f9c9e8d82c83bb28ab27abc52b0";
/*/
static public const URL_BLOCKS:String = "Blocks.png";
// static public const URL_PLAYER:String = "Player.png";
//*/
//画面サイズ
static public const VIEW_W:int = 465;
static public const VIEW_H:int = 465;
//1マスの大きさ
static public const PANEL_LEN:int = 32;
//画像サイズ
static public const PANEL_W:int = 24;
static public const PANEL_H:int = 32;
static public const PANEL_NUM_X:int = 3;
static public const PANEL_NUM_Y:int = 4;
//マップ要素
static public var MapIndexIter:int = 0;
static public const O:int = MapIndexIter++;
static public const W:int = MapIndexIter++;
static public const X:int = MapIndexIter++;
static public const P:int = MapIndexIter++;
//マップ
static public const MAP:Array = [
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
[W,W,W,W,W,W,W,W,W,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,W,W,W,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,O,O,O,W,W,W,W],
[W,O,O,O,O,O,W,W,W,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,O,O,O,W,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,W,W,W,W],
[W,O,O,O,O,O,W,W,W,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,O,O,O,W,W,W,W],
[W,O,O,O,O,O,W,W,W,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,O,O,O,W,W,W,W],
[W,W,W,O,W,W,W,W,W,W,W,O,W,W,W,W,W,O,O,O,O,O,O,O,O,O,O,O,W,W,W,W],
[W,W,W,O,W,W,W,W,W,W,W,O,W,W,W,W,W,O,O,O,O,O,O,O,O,O,O,O,W,W,W,W],
[W,O,O,O,O,O,W,W,W,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,O,O,O,W,W,W,W],
[W,O,O,O,O,O,W,W,W,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,O,O,O,W,W,W,W],
[W,O,O,P,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,O,O,O,O,O,W,W,W,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,O,O,O,W,W,W,W],
[W,O,O,O,O,O,W,W,W,O,O,O,O,O,W,W,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,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
];
//マップのパネル数
static public const MAP_NUM_X:int = MAP[0].length;
static public const MAP_NUM_Y:int = MAP.length;
//マップの大きさ
static public const MAP_W:int = MAP_NUM_X * PANEL_LEN;
static public const MAP_H:int = MAP_NUM_Y * PANEL_LEN;
//Box2Dと実際の表示の比率(Box2Dに大きすぎる値を入れると上手く動かなかったりする)
static public const PHYS_SCALE:Number = 10;
static public function PHYS_to_IMAGE(in_Val:Number):Number{return in_Val * PHYS_SCALE;}
static public function IMAGE_to_PHYS(in_Val:Number):Number{return in_Val / PHYS_SCALE;}
//Box2Dの画面外の余白
static public const BOX2D_RANGE_OFFSET:int = 100;
//==Var==
//Pseudo Singleton
static public var Instance:GameMain;
//マップ(プレイヤーなどを地面に置き換えたりしたもの)
public var m_Map:Vector.<Vector.<int> >;
//プレイヤーの初期位置
public var m_PlayerX:int = 2.5*PANEL_LEN;//一応それっぽい位置に初期化
public var m_PlayerY:int = 2.5*PANEL_LEN;
//レイヤー
public var m_Layer_Root:Sprite = new Sprite();//Root
public var m_Layer_Ground:Sprite = new Sprite();//地面用レイヤー
public var m_Layer_Obj:Sprite = new Sprite();//通常表示用レイヤー
public var m_Layer_Debug:Sprite = new Sprite();//デバッグ描画用
public var m_Layer_HUD:Sprite = new Sprite();//情報表示用レイヤー
//地形画像
public var m_BitmapData_Floor:BitmapData = new BitmapData(MAP_W, MAP_H, true, 0x00000000);
//プレイヤー
public var m_Player:Player;
//Box2D
public var m_Box2D_World:b2World;
//==Function==
//Init
public function GameMain(){
var x:int;
var y:int;
//Pseudo Singleton
{
Instance = this;
}
//Common
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
}
//Static Init
{
ImageManager.Init();
Player.Initialize();
}
//MAP => m_Map
{
m_Map = new Vector.<Vector.<int> >(MAP_NUM_Y);
for(y = 0; y < MAP_NUM_Y; y++){
m_Map[y] = new Vector.<int>(MAP_NUM_X);
var PosY:int = (y+0.5) * PANEL_LEN;
for(x = 0; x < MAP_NUM_X; x++){
var PosX:int = (x+0.5) * PANEL_LEN;
var index:int = MAP[y][x];
switch(index){
case P:
index = O;//プレイヤーの居た位置は地面扱いする
m_PlayerX = PosX;
m_PlayerY = PosY;
break;
}
m_Map[y][x] = index;
}
}
}
//Box2D
{
//考慮する領域
var worldAABB:b2AABB = new b2AABB();
worldAABB.lowerBound.Set(IMAGE_to_PHYS(-BOX2D_RANGE_OFFSET), IMAGE_to_PHYS(-BOX2D_RANGE_OFFSET));
worldAABB.upperBound.Set(IMAGE_to_PHYS(MAP_W+BOX2D_RANGE_OFFSET), IMAGE_to_PHYS(MAP_H+BOX2D_RANGE_OFFSET));
//重力ベクトル
var gravity:b2Vec2 = new b2Vec2(0, 0);
//Sleep
var useSleep:Boolean = true;
//物理world
m_Box2D_World = new b2World(worldAABB, gravity, useSleep);
}
//地形コリジョン
{
Init_Terrain_Collision();
}
//Layer
{
addChild(m_Layer_Root);
{
m_Layer_Root.addChild(m_Layer_Ground);
m_Layer_Root.addChild(m_Layer_Obj);
m_Layer_Root.addChild(m_Layer_Debug);
}
addChild(m_Layer_HUD);
}
//地形
{
ImageManager.Map_to_Bitmap(
m_Map,
m_BitmapData_Floor
);
var bmp:Bitmap;
//Floor
{
bmp = new Bitmap(m_BitmapData_Floor);
m_Layer_Ground.addChild(bmp);
}
}
//プレイヤー
{
m_Player = new Player();
m_Layer_Obj.addChild(m_Player);
}
//Update
{
addEventListener(Event.ENTER_FRAME, Update);
}
//画像ロード開始
{
const LoadFunc:Function = function(in_URL:String, in_OnLoad:Function):void{
var loader:Loader = new Loader();
loader.load(new URLRequest(in_URL), new LoaderContext(true));//画像のロードを開始して
loader.contentLoaderInfo.addEventListener(
Event.COMPLETE,//ロードが完了したら
function(e:Event):void{
in_OnLoad(loader.content);//初期化に入る
}
);
}
LoadFunc(URL_BLOCKS, OnLoadEnd_Blocks);
// LoadFunc(URL_PLAYER, OnLoadEnd_Player);
}
//残りはResetと同じ処理
{
Reset();
}
/*
//Debug
{
var debugDraw:b2DebugDraw = new b2DebugDraw();
debugDraw.m_sprite = m_Layer_Debug;//this;
debugDraw.m_drawScale = PHYS_SCALE;
debugDraw.m_fillAlpha = 0.6;
debugDraw.m_lineThickness = 1;
debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit;
m_Box2D_World.SetDebugDraw(debugDraw);
}
//*/
}
//Reset
public function Reset():void{
//プレイヤー
{
m_Player.SetPos(m_PlayerX, m_PlayerY);
}
}
//Init : Terrain Collision
public function Init_Terrain_Collision():void{
var x:int;
var y:int;
var r:Rectangle;
//コリジョンリスト
var RectList:Vector.<Rectangle> = new Vector.<Rectangle>();
{
//現在の行のコリジョン
var RectList_Now:Vector.<Rectangle> = new Vector.<Rectangle>(MAP_NUM_X);
//結合するため、一時的に溜めておく
var RectList_Pre:Vector.<Rectangle> = new Vector.<Rectangle>(MAP_NUM_X);
for(y = 0; y < MAP_NUM_Y; y++){
r = null;
//まずはこの行のまとめられるところをまとめる
for(x = 0; x < MAP_NUM_X; x++){
var index:int = m_Map[y][x];
switch(index){
case X:
index = W;//壁として一体化する
break;
}
if(index == W){
if(r == null){
r = new Rectangle(x*PANEL_LEN, y*PANEL_LEN, PANEL_LEN, PANEL_LEN);
RectList_Now[x] = r;
}else{
r.width += PANEL_LEN;
}
}else{
r = null;
}
}
//前回の結果と統合できるなら統合する
for(x = 0; x < MAP_NUM_X; x++){
if(RectList_Pre[x] != null){//前回の結果と
if(RectList_Now[x] != null){//今回の結果で同じ始点のものがあり
if(RectList_Pre[x].width == RectList_Now[x].width){//幅が同じなら
//統合する
RectList_Pre[x].height += PANEL_LEN;
RectList_Now[x] = null;
continue;
}
}
//前回の結果が統合できない場合、もう統合することもないのでResultに入れてしまう
RectList.push(RectList_Pre[x]);
}
//今回の結果を前回の結果の方に移す
RectList_Pre[x] = RectList_Now[x];
RectList_Now[x] = null;
}
}
//残っているやつをResultに移す
for(x = 0; x < MAP_NUM_X; x++){
if(RectList_Pre[x] != null){
RectList.push(RectList_Pre[x]);
}
}
}
//実際に作成
{
//まずは地形用のBodyを一つだけ作成
var body:b2Body;
{
body = m_Box2D_World.CreateBody(new b2BodyDef());
}
//作成するShapeのベースを作成
var shapeDef:b2PolygonDef;
{
shapeDef = new b2PolygonDef();
shapeDef.density = 0;//Fix
}
//あとはリストの形状を追加していく
var w:Number;
var h:Number;
var center:b2Vec2 = new b2Vec2();
var ColNum:int = RectList.length;
for(var i:int = 0; i < ColNum; i++){
r = RectList[i];
w = IMAGE_to_PHYS(r.width/2);
h = IMAGE_to_PHYS(r.height/2);
center.x = IMAGE_to_PHYS(r.x) + w;
center.y = IMAGE_to_PHYS(r.y) + h;
shapeDef.SetAsOrientedBox(w, h, center);
body.CreateShape(shapeDef);
}
//一応、追加したShapeに合わせてMassを計算(Fixなので不要かもしれない)
body.SetMassFromShapes();
}
/*
//Debug
var sprite:Sprite = new Sprite();
m_Layer_Debug.addChild(sprite);
var g:Graphics = sprite.graphics;
g.lineStyle(3,0x00FFFF,1.0);
for(i = 0; i < ColNum; i++){
r = RectList[i];
g.drawRect(r.x, r.y, r.width, r.height);
}
//*/
}
//OnLoad : Blocks
public function OnLoadEnd_Blocks(in_Graphic:DisplayObject):void{
//Init ImageManager
{
ImageManager.SetImage(in_Graphic);//それを保持した後
}
//今の表示のスクリーンショットを撮っておいて、α減衰させつつ画像表示に移行させてみる
{
var bmd:BitmapData = new BitmapData(VIEW_W, VIEW_H, false, 0x000000);
bmd.draw(m_Layer_Root, new Matrix(1,0,0,1, m_Layer_Root.x,m_Layer_Root.y));
var bmp:Bitmap = new Bitmap(bmd);
addChild(bmp);
addEventListener(Event.ENTER_FRAME, function f(e:Event):void{
var DeltaAlpha:Number = 5 * 1.0/30.0;
bmp.alpha -= DeltaAlpha;
if(bmp.alpha <= 0){
removeChild(bmp);
removeEventListener(Event.ENTER_FRAME, f);
}
});
}
//ブロック描画
{
ImageManager.Map_to_Bitmap(
m_Map,
m_BitmapData_Floor
);
}
}
//OnLoad : Player
public function OnLoadEnd_Player(in_Graphic:DisplayObject):void{
var index_x:int;
var index_y:int;
var bmd:BitmapData;
var mtx:Matrix = new Matrix(1,0,0,1, 0,0);
var rect:Rectangle = new Rectangle(0,0, PANEL_W,PANEL_H);
//プレイヤー画像
{
for(index_x = 0; index_x < PANEL_NUM_X; index_x++){
for(index_y = 0; index_y < PANEL_NUM_Y; index_y++){
bmd = Player.m_BitmapDataList[index_y][index_x];
//Clear
bmd.fillRect(rect, 0x00000000);
//Draw
mtx.tx = -index_x*PANEL_W;
mtx.ty = -index_y*PANEL_H;
bmd.draw(in_Graphic, mtx);
}
}
}
}
//Update
public function Update(e:Event=null):void{
//今回進める時間
var DeltaTime:Number = 1.0/30.0;
//物理まわりの更新
Update_Phys(DeltaTime);
//Player
m_Player.Update(DeltaTime);
//Camera
Update_Camera();
}
//物理まわりの更新
public function Update_Phys(in_DeltaTime:Number):void{
//マウスのところに移動
//m_MouseJoint.SetTarget(new b2Vec2(IMAGE_to_PHYS(mouseX), IMAGE_to_PHYS(mouseY)));
//物理エンジンをDeltaTimeだけ進める
m_Box2D_World.Step(in_DeltaTime, 10);
//
for(var b:b2Body = m_Box2D_World.m_bodyList; b; b = b.m_next){
//画像との同期
if(b.m_userData != null){
var sprite:Sprite = b.m_userData as Sprite;
sprite.x = PHYS_to_IMAGE(b.GetPosition().x);
sprite.y = PHYS_to_IMAGE(b.GetPosition().y);
//b.m_userData.m_VX = PHYS_to_IMAGE(b.m_linearVelocity.x);
//b.m_userData.m_VY = PHYS_to_IMAGE(b.m_linearVelocity.y);
sprite.rotation = b.GetAngle() * 180/Math.PI;
}
//擬似摩擦
{
const Ratio:Number = 0.99;//本当はDeltaTime依存の値にした方が良い
b.GetLinearVelocity().x *= Ratio;
b.GetLinearVelocity().y *= Ratio;
b.SetAngularVelocity(b.GetAngularVelocity() * Ratio);
}
}
}
//Update : Camera
public function Update_Camera():void{
var PlayerX:int = m_Player.x;
var PlayerY:int = m_Player.y;
//移動量
var CameraMoveX:int = 0;
var CameraMoveY:int = 0;
{
//現在のカメラでのプレイヤー相対位置
var RelPlayerX:Number = PlayerX + m_Layer_Root.x;
var RelPlayerY:Number = PlayerY + m_Layer_Root.y;
//中央からの差がそのまま移動量
CameraMoveX = VIEW_W/2 - RelPlayerX;
CameraMoveY = VIEW_H/2 - RelPlayerY;
}
//目標値
var RootX:int = m_Layer_Root.x + CameraMoveX;
var RootY:int = m_Layer_Root.y + CameraMoveY;
{
//端制限
if(RootX < -MAP_W + VIEW_W){
RootX = -MAP_W + VIEW_W;
}
if(RootX > 0){
RootX = 0;
}
if(RootY < -MAP_H + VIEW_H + PANEL_LEN){//天井を1パネル上にズラしているので、その分カメラの範囲も狭める
RootY = -MAP_H + VIEW_H + PANEL_LEN;
}
if(RootY > 0){
RootY = 0;
}
}
m_Layer_Root.x = RootX;
m_Layer_Root.y = RootY;
}
//#IsGameOver
public function IsEnd():Boolean{
//return (m_Mode != MODE_MAIN);
return false;
}
}
}
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.net.*;
import flash.system.*;
import flash.text.*;
import flash.sensors.*;
//Box2D
import Box2D.Dynamics.*;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Common.*;
import Box2D.Common.Math.*;
import Box2D.Dynamics.Joints.*;
class ImageManager
{
//==Const==
//#Graphic
static public var m_GraphicIndexIter:int = 0;
static public const GRAPHIC_INDEX_BG:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_WALL:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_WALL_X:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_WALL_Y:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_WALL_XorY:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_WALL_XandY:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_NEEDLE:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_NEEDLE_X:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_NEEDLE_Y:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_NEEDLE_XY:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_NUM:int = m_GraphicIndexIter;
//#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_View:BitmapData;
//#Mapping
static public var GRAPHIC_INDEX_TO_POS:Array;
//#Palette
static public var m_Palette_ForView:Array;
//#Utility
static public const POS_ZERO:Point = new Point(0,0);
//==Function==
//#Init
static public function Init():void{
var x:int, y:int, i:int;
//m_BitmapData_View
{
m_BitmapData_View = new BitmapData(256, 256, false, 0x000000);
}
//GRAPHIC_INDEX_TO_POS
{//GRAPHIC_INDEX_~から画像の位置へのマッピング(さらにどの隅での処理かも含む)(そして左から何マス目、上から何マス目、という指定)
GRAPHIC_INDEX_TO_POS = new Array(GRAPHIC_INDEX_NUM);
//[LU][RU][LD][RD]
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_BG] = [[3,2], [3,2], [3,2], [3,2]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_WALL] = [[1,1], [1,1], [1,1], [1,1]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_WALL_X] = [[0,1], [2,1], [0,1], [2,1]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_WALL_Y] = [[1,0], [1,0], [1,2], [1,2]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_WALL_XorY] = [[0,0], [2,0], [0,2], [2,2]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_WALL_XandY] = [[3,0], [4,0], [3,1], [4,1]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_NEEDLE] = [[3,3], [4,3], [3,4], [4,4]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_NEEDLE_X] = [[0,4], [2,4], [0,4], [2,4]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_NEEDLE_Y] = [[1,3], [1,3], [1,5], [1,5]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_NEEDLE_XY] = [[0,3], [2,3], [0,5], [2,5]];
}
//m_Palette_ForView
{
m_Palette_ForView = new Array(256);
var index_graphic:int = GRAPHIC_INDEX_BG;
for(i = 0; i < 256; i++){
//区切りごとにindexを変更。次の区切りまではその値をセット
switch(i){
case 0:
case 6:
case 18:
case 24:
index_graphic = GRAPHIC_INDEX_BG; break;
case 3:
case 21:
index_graphic = GRAPHIC_INDEX_NEEDLE_Y; break;
case 9:
case 15:
index_graphic = GRAPHIC_INDEX_NEEDLE_X; break;
case 12:
index_graphic = GRAPHIC_INDEX_NEEDLE_XY; break;
case 27:
index_graphic = GRAPHIC_INDEX_NEEDLE; break;
case 54:
case 63:
index_graphic = GRAPHIC_INDEX_WALL_XorY; break;
case 60:
case 69:
index_graphic = GRAPHIC_INDEX_WALL_X; break;
case 72:
index_graphic = GRAPHIC_INDEX_WALL_Y; break;
case 78:
index_graphic = GRAPHIC_INDEX_WALL_XandY; break;
case 80:
index_graphic = GRAPHIC_INDEX_WALL; break;
}
m_Palette_ForView[i] = index_graphic;
}
}
}
//画像設定
static public function SetImage(in_Graphic:DisplayObject):void
{
m_BitmapData_View.draw(in_Graphic);
}
//#Draw : BG
static public function Map_to_Bitmap(in_Map:Vector.<Vector.<int> >, out_BitmapData_View:BitmapData):void
{
var x:int, y:int, i:int;
var mtx:Matrix = new Matrix();
var NumX:int = in_Map[0].length;
var NumY:int = in_Map.length;
//Map => Bitmap_Base
//Mapの要素を元に、「0:空白」「1:トゲ」「2:壁」というBitmapを生成
var BitmapData_Base:BitmapData;
{
BitmapData_Base = new BitmapData(NumX, NumY, false, 0x000000);
for(y = 0; y < NumY; y++){
for(x = 0; x < NumX; x++){
var index:int = 0;//default(O, P, G)
{
switch(in_Map[y][x]){
case GameMain.W:
index = 2;
break;
case GameMain.X:
index = 1;
break;
}
}
BitmapData_Base.setPixel(x, y, index);
}
}
}
//Bitmap_Base => Bitmap_LU,Bitmap_RU,Bitmap_LD,Bitmap_RD
//Bitmap_Baseを元に、四隅の隣接状況をそれぞれ求める(Uniqueな値になるようにする)
var BitmapData_Quater:Array = new Array(4);
{
//Create Filter
const filter:Array = [
new ConvolutionFilter(3,3,
[//LU
1, 3, 0,
9, 27, 0,
0, 0, 0,
]
),
new ConvolutionFilter(3,3,
[//RU
0, 3, 1,
0, 27, 9,
0, 0, 0,
]
),
new ConvolutionFilter(3,3,
[//LD
0, 0, 0,
9, 27, 0,
1, 3, 0,
]
),
new ConvolutionFilter(3,3,
[//RD
0, 0, 0,
0, 27, 9,
0, 3, 1,
]
),
];
for(i = 0; i < 4; i++){
//Init
BitmapData_Quater[i] = new BitmapData(NumX, NumY, false, 0x000000);
//Apply Filter
BitmapData_Quater[i].applyFilter(BitmapData_Base, BitmapData_Base.rect, POS_ZERO, filter[i]);
}
}
//Bitmap_LU,Bitmap_RU,Bitmap_LD,Bitmap_RD => ForView
//Uniqueな値から、対応するIndexへと変換する
var BitmapData_ForView:Array = new Array(4);
{
for(i = 0; i < 4; i++){
//Init
BitmapData_ForView[i] = new BitmapData(NumX, NumY, false, 0x000000);
//Apply Palette
BitmapData_ForView[i].paletteMap(BitmapData_Quater[i], BitmapData_Quater[i].rect, POS_ZERO, null, null, m_Palette_ForView);
}
}
//Draw
//上で求めたIndexに基づき描画
{
var rect:Rectangle = new Rectangle(0,0, 16,16);
for(y = 0; y < NumY; y++){
for(x = 0; x < NumX; x++){
for(i = 0; i < 4; i++){
rect.x = x * 32 + 16 * ((i&1)>>0);
rect.y = y * 32 + 16 * ((i&2)>>1);
//#view
mtx.tx = rect.x - 16 * GRAPHIC_INDEX_TO_POS[BitmapData_ForView[i].getPixel(x, y)][i][POS_X];
mtx.ty = rect.y - 16 * GRAPHIC_INDEX_TO_POS[BitmapData_ForView[i].getPixel(x, y)][i][POS_Y];
out_BitmapData_View.draw(m_BitmapData_View, mtx, null, null, rect);
}
}
}
}
}
}
//#Player
class Player extends Sprite
{
//==Const==
//重力
//static public const GRAVITY:Number = 20;
static public const MOVE_POW:Number = 2000.0;//擬似空気摩擦を考慮して大きめにする
//アニメーション用定数
static public const ANIM_DIR_U:int = 0;
static public const ANIM_DIR_R:int = 1;
static public const ANIM_DIR_D:int = 2;
static public const ANIM_DIR_L:int = 3;
//アニメーション用パラメータ
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==
//画像
static public var m_BitmapDataList:Array;
//Init
static public function Initialize():void{
//m_BitmapDataList
{
var shape:Shape = new Shape();
{
var g:Graphics = shape.graphics;
g.clear();
g.lineStyle(2, 0x888888, 1.0);
g.beginFill(0xFFFFFF, 1.0);
g.drawCircle(GameMain.PANEL_W/2, GameMain.PANEL_H/2, GameMain.PANEL_W/2);
g.endFill();
g.lineStyle(2, 0x888888, 1.0);
g.moveTo(GameMain.PANEL_W/2, GameMain.PANEL_H/2 - GameMain.PANEL_W/2);
g.lineTo(GameMain.PANEL_W/2, GameMain.PANEL_H/2 + GameMain.PANEL_W/2);
g.moveTo(GameMain.PANEL_W/2 - GameMain.PANEL_H/2, GameMain.PANEL_H/2);
g.lineTo(GameMain.PANEL_W/2 + GameMain.PANEL_H/2, GameMain.PANEL_H/2);
}
m_BitmapDataList = new Array(GameMain.PANEL_NUM_Y);
for(var y:int = 0; y < GameMain.PANEL_NUM_Y; y++){
m_BitmapDataList[y] = new Array(GameMain.PANEL_NUM_X);
for(var x:int = 0; x < GameMain.PANEL_NUM_X; x++){
m_BitmapDataList[y][x] = new BitmapData(GameMain.PANEL_W, GameMain.PANEL_H, true, 0x00000000);
m_BitmapDataList[y][x].draw(shape);
}
}
}
}
//==Var==
//グラフィック
public var m_Bitmap:Bitmap = new Bitmap();
//アニメーションの方向
public var m_AnimDir:int = ANIM_DIR_R;
//アニメーション用タイマー
public var m_AnimTimer:Number = 0.0;
//死亡フラグ
public var m_IsDead:Boolean = false;
//コリジョン
public var m_Body:b2Body;
//重力の取り扱い
public var m_Accel:Accelerometer;
//重力方向
public var m_Gravity:Vector3D = new Vector3D(0,0);
//重力方向の可視化
public var m_GravityShape:Shape = new Shape();
//==Function==
//Init
public function Player(){
//プレイヤーグラフィック
{
m_Bitmap.x = -GameMain.PANEL_W/2;
m_Bitmap.y = -GameMain.PANEL_H*9/16;
addChild(m_Bitmap);
}
//コリジョン
{
//Shape Def
var shapeDef:b2CircleDef;
{
shapeDef = new b2CircleDef();
shapeDef.radius = GameMain.IMAGE_to_PHYS(GameMain.PANEL_LEN/2 * 0.9);
shapeDef.density = 1;//tekitou
}
//Body Def
var bodyDef:b2BodyDef;
{
bodyDef = new b2BodyDef();
bodyDef.position.Set(GameMain.IMAGE_to_PHYS(this.x), GameMain.IMAGE_to_PHYS(this.y));
//bodyDef.fixedRotation = true;
}
//Body
var body:b2Body;
{
body = GameMain.Instance.m_Box2D_World.CreateBody(bodyDef);
body.CreateShape(shapeDef);
body.SetMassFromShapes();
body.m_userData = this;
}
m_Body = body;
}
//加速度センサー
{
if(Accelerometer.isSupported){
m_Accel = new Accelerometer();
m_Accel.setRequestedUpdateInterval(100);
m_Accel.addEventListener(AccelerometerEvent.UPDATE, SetGravity_Listener);
}
}
//重力可視化
{
GameMain.Instance.m_Layer_HUD.addChild(m_GravityShape);
}
}
//Init : Pos
public function SetPos(in_X:int, in_Y:int):void{
/*
this.x = in_X;
this.y = in_Y;
//*/
m_Body.SetXForm(new b2Vec2(GameMain.IMAGE_to_PHYS(in_X), GameMain.IMAGE_to_PHYS(in_Y)), 0);
}
//Update
public function Update(in_DeltaTime:Number):void{
//死亡・ゴール時は何もしない
if(GameMain.Instance.IsEnd()){
return;
}
//移動
Update_Move(in_DeltaTime);
//グラフィック
Update_Graphic(in_DeltaTime);
//死亡チェック
Check_Dead();
}
static public const GRAV_LINE_W:int = 4;
static public const GRAV_LINE_COLOR:uint = 0xFF0000;
static public const GRAV_LINE_ALPHA:Number = 0.1;
static public const GRAV_FILL_COLOR:uint = 0x220000;
static public const GRAV_FILL_ALPHA:Number = 0.1;
//Update : Graphic
public function Update_Graphic(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[m_AnimDir][iter];
}
//重力の可視化
{
var g:Graphics = m_GravityShape.graphics;
g.clear();
g.lineStyle(GRAV_LINE_W, GRAV_LINE_COLOR, GRAV_LINE_ALPHA);
g.beginFill(GRAV_FILL_COLOR, GRAV_FILL_ALPHA);
//矢印の描画
{
const ARROW_LEN:Number = GameMain.VIEW_W/2;//直線の長さっぽいもの
const ARROW_W:Number = ARROW_LEN/4;//直線の幅っぽいもの
const DELTA_RATIO:Number = 1.7;//三角形の幅は直線の何倍にするか
//中央
var CenterX:int = GameMain.VIEW_W/2;
var CenterY:int = GameMain.VIEW_H/2;
//矢印の先端
var DstX:int = CenterX + m_Gravity.x * ARROW_LEN/MOVE_POW;
var DstY:int = CenterY + m_Gravity.y * ARROW_LEN/MOVE_POW;
//接続点の位置
const DeltaRatio:Number = 0.6;
var DeltaX:int = Lerp(CenterX, DstX, DeltaRatio);
var DeltaY:int = Lerp(CenterY, DstY, DeltaRatio);
//幅用のオフセット
var OffsetX:int = (DstY - CenterY) * ARROW_W/ARROW_LEN;
var OffsetY:int = (CenterX - DstX) * ARROW_W/ARROW_LEN;
//先端から開始
g.moveTo(DstX, DstY);
//三角形の片方
g.lineTo(DeltaX + DELTA_RATIO*OffsetX, DeltaY + DELTA_RATIO*OffsetY);
//三角形と直線の接続点
g.lineTo(DeltaX + OffsetX, DeltaY + OffsetY);
//直線の角
g.lineTo(CenterX + OffsetX, CenterY + OffsetY);
//直線の角(もう片方)
g.lineTo(CenterX - OffsetX, CenterY - OffsetY);
//再び接続点
g.lineTo(DeltaX - OffsetX, DeltaY - OffsetY);
//三角形のもう片方
g.lineTo(DeltaX - DELTA_RATIO*OffsetX, DeltaY - DELTA_RATIO*OffsetY);
//先端に戻る
g.lineTo(DstX, DstY);
}
g.endFill();
}
}
//Check : Dead
public function Check_Dead():void{
//Check
{
if(m_IsDead){
return;
}
}
/*
//マップより下に行っていたら落下死する
if(this.y > GameMain.MAP_H+GameMain.PANEL_LEN){
//ゲームオーバー処理
{
GameMain.Instance.OnDead_Fall();
}
//フラグ
{
m_IsDead = true;
}
}
//*/
}
//Update : Move
public function Update_Move(in_DeltaTime:Number):void{
var Gravity:Vector3D = GetGravity();
var PowX:Number = GameMain.IMAGE_to_PHYS(Gravity.x);
var PowY:Number = GameMain.IMAGE_to_PHYS(Gravity.y);
m_Body.WakeUp();
m_Body.m_force.x += PowX;
m_Body.m_force.y += PowY;
/*//向き固定
//ついでに向きもここで更新
{
var AbsGapX:Number = Math.abs(Gravity.x);
var AbsGapY:Number = Math.abs(Gravity.y);
if(AbsGapY < AbsGapX){
if(Gravity.x > 0){
m_AnimDir = ANIM_DIR_R;
}else{
m_AnimDir = ANIM_DIR_L;
}
}else{
if(Gravity.y > 0){
m_AnimDir = ANIM_DIR_D;
}else{
m_AnimDir = ANIM_DIR_U;
}
}
}
//*/
}
//
public function GetGravity():Vector3D{
if(m_Accel){
//加速度センサーを使う
//→ハンドラで更新されてるはず
}else{
//マウスを使う
const GAP_MIN:Number = GameMain.PANEL_W/2;
const GAP_MAX:Number = GameMain.VIEW_W/3;//GameMain.PANEL_LEN*1.5;
/*
//まずはプレイヤーとマウス位置の差を求める
m_Gravity.x = GameMain.Instance.mouseX - (this.x + GameMain.Instance.m_Layer_Root.x);
m_Gravity.y = GameMain.Instance.mouseY - (this.y + GameMain.Instance.m_Layer_Root.y);
/*/
//マウスの画面中央からの差を求める
m_Gravity.x = GameMain.Instance.mouseX - GameMain.VIEW_W/2;
m_Gravity.y = GameMain.Instance.mouseY - GameMain.VIEW_H/2;
//*/
//長さを制御して、0~1に収める
var GapLen:Number = m_Gravity.length;
if(GapLen < GAP_MIN){
m_Gravity.x = m_Gravity.y = 0;
}else{
m_Gravity.x /= GapLen;
m_Gravity.y /= GapLen;
if(GapLen < GAP_MAX){
m_Gravity.x *= (GapLen - GAP_MIN) / (GAP_MAX - GAP_MIN);
m_Gravity.y *= (GapLen - GAP_MIN) / (GAP_MAX - GAP_MIN);
}
}
//最大値がMOVE_POWになるようにする
m_Gravity.x *= MOVE_POW;
m_Gravity.y *= MOVE_POW;
}
return m_Gravity;
}
//
public function SetGravity_Listener(e:AccelerometerEvent):void{
m_Gravity.x = MOVE_POW * -e.accelerationX;
m_Gravity.y = MOVE_POW * e.accelerationY;
}
//Utility
public function Lerp(in_Src:Number, in_Dst:Number, in_Ratio:Number):Number{
return (in_Src * (1 - in_Ratio)) + (in_Dst * in_Ratio);
}
}