swf
(ノートパソコンだと重いです)
Shot Them "ALL"(あるいは、敵の屍を越えていけ)
- 左右キー
- 移動
- 上キー
- ジャンプ
- Sキー
- ショット
- Rキー
- リセット
状況
今日もちょっと忙しくて、ステージを作成するのが精一杯だった。オブジェクトの新規作成は、来週かな。もしかしたら土日にやるかもしれないけど。
とりあえず、試しに色々なオブジェクトをステージに組み込んでみた。今の形式でだいたい良さそうだが、以下の問題が残ってる。
- 最初のオブジェクトとしてプレイヤーを登録すると、プレイヤーが死んでも消えない
- おそらく、オブジェクト管理まわりにバグがある
- ダメージ床を統合してない
- ブロックの各面に対してダメージ判定を実装することを考えると、結構面倒
- ダメージ床のコリジョンの大きさが、ブロックの大きさと微妙に異なる
- つなぎ目の部分でブロックがひっかかってしまうので、統合の際に一緒に解消したい
- プレイヤーやゴールもセットデータとして統合したい
- プレイヤーは保持しておきたいとか、ゴールはプレイヤーの位置がわからないといけないとかの問題があるので、設計の変更が必要になる
結局、コードはたいして短くならなかったけど、書きやすくはなったので良し。上のサイズぐらいまでなら手作業でなんとかいける。以下、コードは折りたたみ。
コード
//mxmlc Main.as //author Show=O=Healer package { import Box2D.Dynamics.*; import Box2D.Dynamics.Contacts.*; import Box2D.Collision.*; import Box2D.Collision.Shapes.*; import Box2D.Common.Math.*; import flash.events.Event; import flash.display.*; import flash.text.TextField; import flash.utils.*; //Input import flash.ui.Keyboard; import flash.events.KeyboardEvent; //AA import flash.geom.*; [SWF(backgroundColor="#ffffff", width="400", height="300")] public class Main extends Sprite { //Base Sprite private var m_SpriteGame:Sprite;//プレイヤーなどを表示するためのスプライト private var m_SpriteInterface:Sprite;//HPの残量などを表示するためのスプライト //Player private var m_Player:CPlayer; //Param //ステージの範囲 public static const RANGE_LX:Number = 0; public static const RANGE_RX:Number = 1500; public static const RANGE_UY:Number = 0; public static const RANGE_DY:Number = 300; //画面の大きさ public static const CAMERA_W:Number = 400; public static const CAMERA_H:Number = 300; public static const FLOOR_UY:Number = 200; public static const FLOOR_DY:Number = 370; //ステージの設定 public static const STAGE_PARAM:Array = [ //カンマのつけ方が面倒なので、必ず存在する「name」に「カンマなし」の役目を押し付ける {//Limit Wall Left lx:RANGE_LX-10, rx:RANGE_LX, uy:RANGE_UY, dy:RANGE_DY, density:0.0,//fixed category_bits:0x0004, name:"Block" }, {//Limit Wall Right lx:RANGE_RX, rx:RANGE_RX+10, uy:RANGE_UY, dy:RANGE_DY, density:0.0,//fixed category_bits:0x0004, name:"Block" }, {//Floor 1 lx:0, rx:100, uy:FLOOR_UY-50, dy:FLOOR_DY, density:0.0,//fixed category_bits:0x0004, name:"Block" }, {//Floor 2 lx:100, rx:350, uy:FLOOR_UY+2, dy:FLOOR_DY, density:0.0,//fixed category_bits:0x0004, name:"Block" }, {//Fall Block lx:280, rx:360, uy:FLOOR_UY-120, dy:FLOOR_UY-100, density:20.0, // category_bits:IObject.CATEGORY_TERRAIN, category_bits:0x0004, start_sleep:true, name:"Block" }, {//Floor Damage lx:350, rx:RANGE_RX, uy:FLOOR_UY+5, dy:FLOOR_DY, name:"DamageFloor" }, {//Floor Center lx:500, rx:650, uy:FLOOR_UY-50, dy:FLOOR_UY-20, density:0.0,//fixed category_bits:0x0004, name:"Block" }, {//Floor Center2 lx:550, rx:600, uy:FLOOR_UY-80, dy:FLOOR_UY-50, density:0.0,//fixed category_bits:0x0004, name:"Block" }, {//Enemy x:520, y:FLOOR_UY-70, name:"Enemy" }, {//Enemy x:560, y:FLOOR_UY-100, name:"Enemy" }, {//Enemy x:600, y:FLOOR_UY-100, name:"Enemy" }, {//Enemy x:640, y:FLOOR_UY-70, name:"Enemy" }, {//Breakable Block lx:900, rx:940, uy:FLOOR_UY-50, dy:FLOOR_UY, density:0.0, // category_bits:IObject.CATEGORY_TERRAIN, category_bits:0x0004, become_gro:true, name:"Block" }, {//Enemy x:920, y:FLOOR_UY-70, name:"Enemy" }, {//Breakable Block lx:940, rx:980, uy:FLOOR_UY-50, dy:FLOOR_UY, density:0.0, // category_bits:IObject.CATEGORY_TERRAIN, category_bits:0x0004, become_gro:true, name:"Block" }, {//Enemy x:960, y:FLOOR_UY-70, name:"Enemy" }, {//Breakable Block lx:980, rx:1020, uy:FLOOR_UY-50, dy:FLOOR_UY, density:0.0, // category_bits:IObject.CATEGORY_TERRAIN, category_bits:0x0004, become_gro:true, name:"Block" }, {//Enemy x:1000, y:FLOOR_UY-70, name:"Enemy" }, {//Breakable Block lx:1020, rx:1060, uy:FLOOR_UY-50, dy:FLOOR_UY, density:0.0, // category_bits:IObject.CATEGORY_TERRAIN, category_bits:0x0004, become_gro:true, name:"Block" }, {//Enemy x:1040, y:FLOOR_UY-70, name:"Enemy" }, /* {//Upper Floor name:"Block", lx:RANGE_LX + (RANGE_RX-RANGE_LX)*0/7, rx:RANGE_LX + (RANGE_RX-RANGE_LX)*4/7, uy:FLOOR_UY-140, dy:FLOOR_UY-120, density:0.0,//fixed category_bits:0x0004 }, {//Enemy x:RANGE_LX + (RANGE_RX-RANGE_LX)*2.2/7, y:FLOOR_UY-40, name:"Enemy" }, {//Enemy x:RANGE_LX + (RANGE_RX-RANGE_LX)*2.8/7, y:FLOOR_UY-40, name:"Enemy" }, {//Enemy x:RANGE_LX + (RANGE_RX-RANGE_LX)*4.2/7, y:FLOOR_UY-60, name:"Enemy" }, {//Enemy x:RANGE_LX + (RANGE_RX-RANGE_LX)*4.8/7, y:FLOOR_UY-60, name:"Enemy" }, {//Enemy x:RANGE_LX + (RANGE_RX-RANGE_LX)*6.2/7, y:FLOOR_UY-80, name:"Enemy" }, {//Enemy x:RANGE_LX + (RANGE_RX-RANGE_LX)*6.8/7, y:FLOOR_UY-80, name:"Enemy" }, {//Enemy x:RANGE_LX + (RANGE_RX-RANGE_LX)*0.5/7, y:FLOOR_UY-160, name:"Enemy" }, {//Enemy x:RANGE_LX + (RANGE_RX-RANGE_LX)*1.5/7, y:FLOOR_UY-160, name:"Enemy" }, {//Enemy x:RANGE_LX + (RANGE_RX-RANGE_LX)*2.5/7, y:FLOOR_UY-160, name:"Enemy" }, {//Enemy x:RANGE_LX + (RANGE_RX-RANGE_LX)*3.5/7, y:FLOOR_UY-160, name:"Enemy" }, //*/ ]; public static const PLAYER_X:Number = 50; public static const PLAYER_Y:Number = 180; public static const KEY_R:int = 82; public function Main() { stage.scaleMode = "noScale"; stage.align = "TL"; var text:TextField = new TextField(); text.text = "CLICK TO START!!!"; text.x = text.y = 100; addChild(text); stage.addEventListener("click", function(event:Event):void { if(text.visible){ Init(); } text.visible = false; }); } //とりあえず、ちゃんとフォーカスがもらえるように、クリックで開始することにする private function Init():void { m_SpriteGame = new Sprite(); addChild(m_SpriteGame); m_SpriteInterface = new Sprite(); addChild(m_SpriteInterface); Reset(); //毎フレームUpdateを呼ぶ addEventListener("enterFrame", function(event:Event):void { Update(); }); //リスタートなどのキーボード処理 stage.addEventListener(KeyboardEvent.KEY_DOWN, OnKeyDown); } //リスタートのために、初期化処理と共通部分を分離 private function Reset():void { {//Reset Manager ObjectManager.Reset(); PhysManager.Reset(); } //現在、一番最初に作ったオブジェクトの挙動がおかしくなるバグあり //Load Stage STAGE_PARAM.forEach( function(param:Object, index:int, arr:Array):void{ var obj:IObject; if(param.name == "Block"){ var blockParam:ObjectParam = new ObjectParam(); { blockParam.m_LX = param.lx; blockParam.m_RX = param.rx; blockParam.m_UY = param.uy; blockParam.m_DY = param.dy; ObjectParam.PARAM_NAME.forEach( function(block_param_name:String, block_index:int, block_arr:Array):void{ if(param.hasOwnProperty(block_param_name)){ blockParam[block_param_name] = param[block_param_name]; } } ); } obj = new CBlock(blockParam); } if(param.name == "DamageFloor"){ obj = new CFloor_Damage(param.lx, param.rx, param.uy, param.dy); } if(param.name == "Enemy"){ var enemy:CEnemy = new CEnemy(); enemy.SetPos(param.x, param.y); obj = enemy; } if(obj != null){ obj.OnRegist(m_SpriteGame); } } ); {//Player m_Player = new CPlayer(stage); m_Player.SetPos(PLAYER_X, PLAYER_Y); m_Player.OnRegist(m_SpriteGame); } {//Goal var goal:CGoal = new CGoal(m_Player); goal.SetPos(RANGE_RX-50, FLOOR_UY-70); goal.OnRegist(m_SpriteGame); } /* {//Block Sleeping blockParam4.m_PhysParam_Density = 20.0;//Movable blockParam4.m_PhysParam_StartSleep = true; } //*/ /* {//Block Breakable blockParam2.m_PhysParam_Density = 0.0;//Fixed blockParam2.m_BecomeGro = true; } {//Block AntiGravity blockParam3.m_PhysParam_Density = 20.0;//Movable blockParam3.m_AntiGravity = true; } //*/ //タイマーのリセット m_PreTime = getTimer(); } private function OnKeyDown(event:KeyboardEvent):void{ if(event.keyCode == KEY_R){ Reset(); } } //=Update= private var m_PreTime:Number = 0.0; static public const MAX_DELTA_TIME:Number = 1.0/15.0; public function Update():void { // var deltaTime:Number = 1.0 / 30.0; var nowTime:Number = getTimer(); var deltaTime:Number = (nowTime - m_PreTime) / 1000.0;//ミリ秒→秒 m_PreTime = nowTime; if(deltaTime > MAX_DELTA_TIME){ deltaTime = MAX_DELTA_TIME;//一応制限してみる(コリジョンのすりぬけ防止) } //=Object //プレイヤや弾などのUpdateを呼ぶ ObjectManager.Update(deltaTime); //=Physics //物理エンジンを進める PhysManager.Update(deltaTime); //=Camera UpdateCamera(); /* //=Render graphics.clear(); for (var bb:b2Body = PhysManager.Instance.m_World.m_bodyList; bb; bb = bb.m_next) { //primitive描画っぽいもの for (var s:b2Shape = bb.GetShapeList(); s != null; s = s.GetNext()) { DrawShape(s); } } //*/ } private function UpdateCamera():void{ var trgX:Number = m_Player.x - CAMERA_W/2.0; var trgY:Number = m_Player.y - CAMERA_H/2.0; if(trgX < RANGE_LX){ trgX = RANGE_LX; } if(trgY < RANGE_UY){ trgY = RANGE_UY; } if(trgX > RANGE_RX - CAMERA_W){ trgX = RANGE_RX - CAMERA_W; } if(trgY > RANGE_DY - CAMERA_H){ trgY = RANGE_DY - CAMERA_H; } m_SpriteGame.x = -trgX; m_SpriteGame.y = -trgY; } //=Render= /* //判定の可視化などで重宝するので、もうしばらく残しておく public function DrawShape(shape:b2Shape):void { //box if(shape.m_type == b2Shape.e_polyShape) { var drawBox:Function = function():void{ var poly:b2PolyShape = shape as b2PolyShape; var tV:b2Vec2 = b2Math.AddVV(poly.m_position, b2Math.b2MulMV(poly.m_R, poly.m_vertices[i])); graphics.beginFill(0x999999, 1); graphics.lineStyle(1,0xffffff,1); graphics.moveTo(tV.x * PhysManager.PHYS_SCALE, tV.y * PhysManager.PHYS_SCALE); for (var i:int = 0; i < poly.m_vertexCount; ++i) { var v:b2Vec2 = b2Math.AddVV(poly.m_position, b2Math.b2MulMV(poly.m_R, poly.m_vertices[i])); graphics.lineTo(v.x * PhysManager.PHYS_SCALE, v.y * PhysManager.PHYS_SCALE); } graphics.lineTo(tV.x * PhysManager.PHYS_SCALE, tV.y * PhysManager.PHYS_SCALE); graphics.endFill(); }; drawBox(); } } //*/ } } import Box2D.Dynamics.*; import Box2D.Dynamics.Contacts.*; import Box2D.Collision.*; import Box2D.Collision.Shapes.*; import Box2D.Common.Math.*; import flash.events.Event; import flash.display.*; import flash.text.TextField; import flash.utils.*; //Input import flash.ui.Keyboard; import flash.events.KeyboardEvent; //AA import flash.geom.*; //!物理エンジンのWrapper class PhysManager { //=Phys= // private var m_World:b2World; public var m_World:b2World; //=Param= static public const PHYS_SCALE:Number = 10; static public const GRAVITY:Number = 20.0; static public const RANGE_LX:Number = Main.RANGE_LX - 30.0; static public const RANGE_RX:Number = Main.RANGE_RX + 30.0; static public const RANGE_UY:Number = Main.RANGE_UY - 30.0; static public const RANGE_DY:Number = Main.RANGE_DY + 30.0; //=Singleton= private static var __Instance:PhysManager; public static function get Instance():PhysManager { if(__Instance == null){ __Instance = new PhysManager(); } return __Instance; } //=Init Physics= public function PhysManager(){ {//Common //AABB var worldAABB:b2AABB = new b2AABB(); worldAABB.minVertex.Set(RANGE_LX/PHYS_SCALE, RANGE_UY/PHYS_SCALE); worldAABB.maxVertex.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_World = new b2World(worldAABB, g, useSleep); } } //=Static Function= //コリジョンを実際に作成する public static function CreateBody(in_BodyDef:b2BodyDef):b2Body{ return Instance.m_World.CreateBody(in_BodyDef); } //コリジョンを削除する public static function DestroyBody(in_Body:b2Body):void{ Instance.m_World.DestroyBody(in_Body); } //毎フレーム呼んでもらう public static function Update(in_DeltaTime:Number):void{ //物理エンジンをin_DeltaTimeだけ進める Instance.m_World.Step(in_DeltaTime, 10); //ぶつかっているものを見つけて、対応関数を呼ぶ for(var iter:b2Contact = Instance.m_World.GetContactList(); iter != null; iter = iter.GetNext()){ if(iter.GetManifoldCount() == 0){ continue; } var Obj1:IObject = iter.GetShape1().m_body.m_userData as IObject; var Obj2:IObject = iter.GetShape2().m_body.m_userData as IObject; var Nrm:b2Vec2 = iter.GetManifolds()[0].normal; Obj1.OnContact(Obj2, Nrm.x, Nrm.y); Obj2.OnContact(Obj1, -Nrm.x, -Nrm.y); } //Spriteへの位置の反映 for (var bb:b2Body = Instance.m_World.m_bodyList; bb; bb = bb.m_next) { if(bb.m_userData != null){ bb.m_userData.x = bb.m_position.x * PHYS_SCALE; bb.m_userData.y = bb.m_position.y * PHYS_SCALE; bb.m_userData.m_VX = bb.m_linearVelocity.x * PHYS_SCALE; bb.m_userData.m_VY = bb.m_linearVelocity.y * PHYS_SCALE; bb.m_userData.rotation = bb.GetRotation() * 360/(2*3.14); } } } //全てのオブジェクトを消す public static function Reset():void{ Instance.m_World.CleanBodyList(); } } //!オブジェクトの全体的な管理 class ObjectManager { //=Singleton= private static var __Instance:ObjectManager; public static function get Instance():ObjectManager { if(__Instance == null){ __Instance = new ObjectManager(); } return __Instance; } // private var m_HeadObj:IObject; //Objectを登録し、Updateが呼ばれるようにする public static function Register(in_Obj:IObject):void{ if(Instance.m_HeadObj == null){ Instance.m_HeadObj = in_Obj; }else{ Instance.m_HeadObj.m_PrevObj = in_Obj; in_Obj.m_NextObj = Instance.m_HeadObj; Instance.m_HeadObj = in_Obj; } } //上ではこれを呼び、各ObjectのUpdateを呼び出す。ついでに消失管理もここで。 public static function Update(in_DeltaTime:Number):void{ //毎フレーム、関数オブジェクトを生成してるはずなのでいけてない(staticで持っておきたい) //Event var updateEvent:Function = function():void{ for(var iter:IObject = Instance.m_HeadObj; iter != null; iter = iter.m_NextObj){ Instance.m_EventArray.forEach( function(evt:IEvent, index:int, arr:Array):void{ var callback:Function = iter.m_EventFuncMap[evt.m_Type]; if(callback != null){ callback(evt); } } ); } //Reset Instance.m_EventArray = new Array(); }; updateEvent(); //Chack Range var checkRange:Function = function():void{ for(var iter:IObject = Instance.m_HeadObj; iter != null; iter = iter.m_NextObj){ if(iter.x <= PhysManager.RANGE_LX || iter.x >= PhysManager.RANGE_RX || iter.y <= PhysManager.RANGE_UY || iter.y >= PhysManager.RANGE_DY){ //レンジ外のものは削除 if(iter.m_PrevObj == null){ Instance.m_HeadObj = iter.m_NextObj; iter.m_NextObj.m_PrevObj = null; iter.m_NextObj = null; }else{ iter.m_PrevObj.m_NextObj = iter.m_NextObj; iter.m_NextObj.m_PrevObj = iter.m_PrevObj; iter.m_NextObj = null; } iter.Destroy(); } } }; checkRange(); //Update Object var updateObject:Function = function():void{ for(var iter:IObject = Instance.m_HeadObj; iter != null; iter = iter.m_NextObj){ //共通Update iter.CommonUpdate(in_DeltaTime); //独自Update iter.Update(in_DeltaTime); if(iter.IsKilled()){ if(iter.m_PrevObj == null){ Instance.m_HeadObj = iter.m_NextObj; iter.m_NextObj.m_PrevObj = null; iter.m_NextObj = null; }else{ iter.m_PrevObj.m_NextObj = iter.m_NextObj; iter.m_NextObj.m_PrevObj = iter.m_PrevObj; iter.m_NextObj = null; } iter.Destroy(); } } }; updateObject(); } //全てのオブジェクトを消す public static function Reset():void{ for(var iter:IObject = Instance.m_HeadObj; iter != null; iter = iter.m_NextObj){ iter.Destroy_Reset(); } Instance.m_HeadObj = null; Instance.m_EventArray = new Array(); } //=Event= private var m_EventArray:Array = new Array(); public static function PushEvent(in_Event:IEvent):void{ Instance.m_EventArray.push(in_Event); } } //!プレイヤー、敵、弾の共通インタフェース class IObject extends Sprite { //==Object== //=生成されたらマネージャに自分を登録し、Updateが呼ばれるようにしておく public function IObject(){ ObjectManager.Register(this); } //=消える処理まわり private var m_KillFlag:Boolean = false; private var m_ResetDestroyFlag:Boolean = false; public function Kill():void{//オブジェクト側は消えたい時にコレを呼ぶ m_KillFlag = true; } public function IsKilled():Boolean{ return m_KillFlag; } public function IsReset():Boolean{ return m_ResetDestroyFlag; } //Destroy時に呼び出して欲しい処理はこれをオーバライドする protected function OnDestruct():void{ } public function Destroy():void{//システム側が、消す時にこれを呼ぶ OnDestruct(); if(m_Body != null){ PhysManager.DestroyBody(m_Body); } parent.removeChild(this); } public function Destroy_Reset():void{//リセット用のDestroy m_ResetDestroyFlag = true; Destroy(); } //=消失管理&Updateの連鎖などで使うためのリスト用パラメータ //双方向である必要はない気もする public var m_NextObj:IObject; public var m_PrevObj:IObject; //=ゲーム内に出現する時の処理 public function OnRegist(in_Parent:DisplayObjectContainer):void{ m_Graphic = CreateAASprite(m_AA);//m_AAをもとに、実際に描画するものを作成 if(m_BodyDef != null){ m_BodyDef.userData = this;//m_Graphic;//物理エンジンに合わせて座標などを更新するために登録 //Create m_BodyDef.position.Set(this.x / PhysManager.PHYS_SCALE, this.y / PhysManager.PHYS_SCALE); m_Body = PhysManager.CreateBody(m_BodyDef);//コリジョンの実際の生成 } in_Parent.addChild(this); } //共通の毎回処理する処理 public function CommonUpdate(in_DeltaTime:Number):void{ CheckBaloon(in_DeltaTime); } //=HP= //自分のHP public var m_HP:int = 1; //相手に与えるダメージ public var m_Damage:int = 0; //自分のタイプ public var m_Type:int = 0; //タイプ一覧 public static const TYPE_PLAYER:int = 0x0001; public static const TYPE_PLAYER_BULLET:int = 0x0002; public static const TYPE_ENEMY:int = 0x0004; public static const TYPE_ENEMY_BULLET:int = 0x0008; public static const TYPE_TERRAIN:int = 0x0010; public static const TYPE_TERRAIN_DAMAGE:int = 0x0011; public static const TYPE_PIECE:int = 0x0012; //==Collision== //Collision Category public static const CATEGORY_PLAYER:int = 0x0001; public static const CATEGORY_PLAYER_BULLET:int = 0x0002; public static const CATEGORY_TERRAIN:int = 0x0004; public static const CATEGORY_BLOCK:int = 0x0008; public static const CATEGORY_ENEMY:int = 0x0010; //Collision Param protected var m_PhysParam_Density:Number = 1.0; protected var m_PhysParam_Friction:Number = 0.0; // protected var m_PhysParam_Restitution:Number = 0.0; protected var m_PhysParam_CategoryBits:int = 1;//test protected var m_PhysParam_MaskBits:int = ~0; protected var m_PhysParam_AllowSleep:Boolean = true; protected var m_PhysParam_StartSleep:Boolean = false; //Collision Body protected var m_BodyDef:b2BodyDef; protected var m_Body:b2Body; //Create Collision //円のコリジョンの作成(準備だけで、実際の生成はOnRegistで行う) protected function CreateCollision_Circle(in_R:Number):void{ //Shape var shapeSd:b2CircleDef = new b2CircleDef(); { shapeSd.radius = in_R / PhysManager.PHYS_SCALE; shapeSd.density = m_PhysParam_Density; shapeSd.friction = m_PhysParam_Friction; // shapeSd.restitution = m_PhysParam_Restitution; shapeSd.categoryBits = m_PhysParam_CategoryBits; shapeSd.maskBits = m_PhysParam_MaskBits; } //Body m_BodyDef = new b2BodyDef(); { m_BodyDef.AddShape(shapeSd); m_BodyDef.linearVelocity.Set(m_VX / PhysManager.PHYS_SCALE, m_VY / PhysManager.PHYS_SCALE); if(m_PhysParam_StartSleep){ m_BodyDef.isSleeping = true; }else{ m_BodyDef.allowSleep = m_PhysParam_AllowSleep; } } } //四角のコリジョンの作成(準備だけで、実際の生成はOnRegistで行う) protected function CreateCollision_Box(in_W:Number, in_H:Number):void{ //Shape var shapeSd:b2BoxDef = new b2BoxDef(); { shapeSd.extents.Set(in_W/2 / PhysManager.PHYS_SCALE, in_H/2 / PhysManager.PHYS_SCALE); shapeSd.density = m_PhysParam_Density; shapeSd.friction = m_PhysParam_Friction; // shapeSd.restitution = m_PhysParam_Restitution; shapeSd.categoryBits = m_PhysParam_CategoryBits; shapeSd.maskBits = m_PhysParam_MaskBits; } //Body m_BodyDef = new b2BodyDef(); { m_BodyDef.AddShape(shapeSd); m_BodyDef.linearVelocity.Set(m_VX / PhysManager.PHYS_SCALE, m_VY / PhysManager.PHYS_SCALE); if(m_PhysParam_StartSleep){ m_BodyDef.isSleeping = true; }else{ m_BodyDef.allowSleep = m_PhysParam_AllowSleep; } } } //==Graphic== //Graphic Param protected var m_AA:String = "X";//グロ・ラグドールのためにも、文字列は別で記憶しておく protected var m_Graphic:Sprite;//上のAAをもとに生成されたビットマップ protected var m_GraphicW:Number = -1.0;//とりこむ幅(マイナスなら、テキストの大きさに合わせる) protected var m_GraphicH:Number = -1.0; //Set AA protected function SetAA(in_AA:String):void{ m_AA = in_AA; } //in_Textを(Bitmapによって)表示するSpriteを作成する protected function CreateAASprite(in_Text:String):Sprite{ //まずは文字列を普通に表示するものを作成 var text_field:TextField = new TextField(); { text_field.text = in_Text; text_field.border = false; text_field.x = 0; text_field.y = 0; if(m_GraphicW > 0.0){ text_field.width = m_GraphicW; text_field.height = m_GraphicH; }else{ text_field.width = 999; text_field.height = 999; } } //その内容をビットマップデータとして取り込む var bmp_data : BitmapData; if(m_GraphicW > 0.0){ bmp_data = new BitmapData(m_GraphicW, m_GraphicH, true , 0x00000000); }else{ bmp_data = new BitmapData(text_field.textWidth+5, text_field.textHeight+5, true , 0x00000000); } { var matrix : Matrix = new Matrix(1,0,0,1,0,0); var color : ColorTransform = new ColorTransform(1,1,1,1,0,0,0,0); var rect : Rectangle = new Rectangle(0,0,bmp_data.width,bmp_data.height); bmp_data.draw(text_field, matrix, color, BlendMode.NORMAL, rect, true); } //取り込んだビットマップデータを表示 var bmp_obj:Bitmap = new Bitmap( bmp_data , PixelSnapping.AUTO , true); { if(m_GraphicW > 0.0){ bmp_obj.x = -m_GraphicW*0.5; bmp_obj.y = -m_GraphicH*0.5; }else{ bmp_obj.x = -text_field.textWidth*0.5; bmp_obj.y = -text_field.textHeight*0.5; } } //さらにそれを表示するスプライトを作成して返す var sprite:Sprite = new Sprite(); { addChild(sprite); sprite.addChild(bmp_obj); } return sprite; } // protected function CreateGroRagdoll(in_Text:String):void{//grotesque var i:int; //まず、in_Textの文字を一つ一つTextFieldにする var text_field_array:Array = new Array(); for(i = 0; i < in_Text.length; ++i){ var text_field:TextField = new TextField(); { text_field.text = in_Text.charAt(i); text_field.border = false; text_field.x = 0; text_field.y = 0; } text_field_array.push(text_field); } //TextFieldを元に、グラフィックを計算したり、幅を計算して位置を求めたりする // var bmp_x:Number = this.x + -this.width*0.5; // var bmp_y:Number = this.y + -this.height*0.5; //本体の中心位置に対する破片の相対位置 var offset_x:Number = -this.width*0.5; var offset_y:Number = -this.height*0.5; var max_h:Number = 0.0;//下方向へのオフセットを決定するため、一番大きい高さを毎回記録する for(i = 0; i < text_field_array.length; ++i){ if(text_field_array[i].text == "\r"){//"\n"じゃ識別できなかった //改行なので、次の行のためのリセット。改行は表示しないので、そこら辺の処理は飛ばす // bmp_x = this.x + -this.width*0.5; // bmp_y += max_h; offset_x = -this.width*0.5; offset_y += max_h; max_h = 0.0; continue; } //空白は表示しても仕方がないので生成しない(文字間の幅の計算には必要なので、その処理は行う) var create_bmp_flag:Boolean = true; if(text_field_array[i].text == " "){ create_bmp_flag = false; } if(text_field_array[i].text == " "){ create_bmp_flag = false; } //見た目の大きさ var w:Number = text_field_array[i].textWidth; var h:Number = text_field_array[i].textHeight; //実際の見た目よりコリジョンは小さくする var col_w:Number = 0.5*w; var col_h:Number = 0.5*h; //破片の作成 if(create_bmp_flag){ var piece:CRagdollPiece = new CRagdollPiece(text_field_array[i].text, col_w, col_h); // piece.SetPos(bmp_x+0.5*w, bmp_y+0.5*h); //破片を実際の画像の位置にあわせる piece.SetPos(this.x + offset_x+0.5*w, this.y + offset_y+0.5*h); //破片を以前の速度をベースにしつつ飛び散らせる piece.SetVel(m_VX + 1.0*offset_x, m_VY + 1.0 + 1.0*offset_y); piece.OnRegist(this.parent); //一定確率で、破片を別のものにする if(Math.random() < 0.5){ piece.GrowWorse(); } } //次の破片位置のオフセットのための各種処理 //横方向 // bmp_x += w; offset_x += w; //縦方向 if(max_h < h){ max_h = h; } } } //==Coordinate== //Set Position public function SetPos(in_X:Number, in_Y:Number):void{ this.x = in_X; this.y = in_Y; } public var m_VX:Number = 0.0; public var m_VY:Number = 0.0; //Set Velocity public function SetVel(in_VX:Number, in_VY:Number):void{ m_VX = in_VX; m_VY = in_VY; if(m_BodyDef != null){ m_BodyDef.linearVelocity.Set(in_VX / PhysManager.PHYS_SCALE, in_VY / PhysManager.PHYS_SCALE); } } //==Baloon== public var m_TopBaloon:CBaloon; //本体にくっつくセリフを生成。消すのは、返り値のフラグをオフニすればよい。 public function PushBaloonText(in_Text:String):CBaloon{ PushBaloonText_Timer(in_Text, -1.0); return m_TopBaloon; } //本体にくっつき、時間で消滅するセリフを生成 public function PushBaloonText_Timer(in_Text:String, in_Time:Number):void{ var newBaloon:CBaloon = new CBaloon(in_Text, in_Time); addChild(newBaloon); newBaloon.x = 0.5*this.width; newBaloon.y = -0.5*newBaloon.height; if(m_TopBaloon == null){ m_TopBaloon = newBaloon; }else{ removeChild(m_TopBaloon); newBaloon.m_NextBaloon = m_TopBaloon; m_TopBaloon.m_PrevBaloon = newBaloon; m_TopBaloon = newBaloon; } } //本体が死んでも残り、画面内に表示されようとするセリフオブジェクトを生成する public function CreateBaloonObj(in_Text:String, in_Time:Number):void{ if(IsReset()){ return; } var trgX:Number = this.x; var trgY:Number = this.y; if(trgX < Main.RANGE_LX){trgX = Main.RANGE_LX;} if(trgX > Main.RANGE_RX){trgX = Main.RANGE_RX;} if(trgY < Main.RANGE_UY){trgY = Main.RANGE_UY;} if(trgY > Main.RANGE_DY){trgY = Main.RANGE_DY;} var baloon:CBaloonObj = new CBaloonObj(trgX, trgY, in_Text, in_Time); baloon.OnRegist(this.parent); } private function CheckBaloon(in_DeltaTime:Number):void{ for(var iter:CBaloon = m_TopBaloon; iter != null; iter = iter.m_NextBaloon){ //時間制限式のやつのチェック if(iter.m_RestTime >= 0.0){ iter.m_RestTime -= in_DeltaTime; if(iter.m_RestTime <= 0.0){ iter.m_KillFlag = true; } } //時間や外部のイベントでフラグが立っていたら消す if(iter.m_KillFlag){ //トップを消すなら、次のトップに表示を差し替える if(iter == m_TopBaloon){ m_TopBaloon = iter.m_NextBaloon; removeChild(iter); if(m_TopBaloon != null){ addChild(m_TopBaloon); } }else{ iter.m_PrevBaloon.m_NextBaloon = iter.m_NextBaloon; } if(iter.m_NextBaloon != null){ iter.m_NextBaloon.m_PrevBaloon = iter.m_PrevBaloon; } } } } //=Event= public var m_EventFuncMap:Object = new Object(); //in_EventTypeのイベントが送られてきたら、in_Funcを実行するようにする public function RegisterEventFunc(in_EventType:String, in_Func:Function):void{ m_EventFuncMap[in_EventType] = in_Func; } //他のオブジェクトにメッセージを送る public function DispatchEvent(in_Event:IEvent):void{ ObjectManager.PushEvent(in_Event); } //=virtual function= //毎フレーム呼ばれる public function Update(in_DeltaTime:Number):void{ } //衝突した時に呼ばれる public function OnContact(in_Obj:IObject, in_NrmX:Number, in_NrmY:Number):void{ //in_NrmX > 0.0//自分の右に当たった //in_NrmX < 0.0//自分の右に当たった //in_NrmY > 0.0//自分の下に当たった //in_NrmY < 0.0//自分の上に当たった } } //!ラグドール時の破片 class CRagdollPiece extends IObject { public function CRagdollPiece(in_Text:String, in_W:Number, in_H:Number){ //Collision m_PhysParam_Density = 1.0; m_PhysParam_Friction = 1.0; // m_PhysParam_Restitution = 0.9; m_PhysParam_CategoryBits = CATEGORY_BLOCK; CreateCollision_Box(in_W, in_H); //Graphic SetAA(in_Text); //Type m_Type = TYPE_PIECE; } //破片のグラフィックをさらに細かくなるように変更 public function GrowWorse():void{ //グラフィックを変更 //Default var nextAA:String = "*"; //*からの連鎖 if(m_AA == "*"){ nextAA = ":"; } if(m_AA == ":"){ nextAA = "."; } //独自 if(m_AA == "o"){ nextAA = "A"; } if(m_AA == "^"){ nextAA = ";"; } if(m_AA == "^"){ nextAA = ";"; } //Reset if(m_Graphic){ removeChild(m_Graphic); } //Create m_Graphic = CreateAASprite(nextAA);//m_AAをもとに、実際に描画するものを作成 } //衝突した時に呼ばれる override public function OnContact(in_Obj:IObject, in_NrmX:Number, in_NrmY:Number):void{ if(in_Obj.m_Type == TYPE_PLAYER_BULLET){ GrowWorse(); } } } //!セリフ class CBaloon extends Sprite { public var m_RestTime:Number = -1.0;//マイナスなら、イベントでオフにされるまでずっと表示 public var m_KillFlag:Boolean = false; public var m_NextBaloon:CBaloon = null; public var m_PrevBaloon:CBaloon = null; public function CBaloon(in_Text:String, in_Time:Number){ {//in_Text //まずは文字列を普通に表示するものを作成 var text_field:TextField = new TextField(); { text_field.text = in_Text; text_field.border = false; // text_field.x = 0; // text_field.y = 0; } //その内容をビットマップデータとして取り込む var bmp_data:BitmapData = new BitmapData(text_field.textWidth+5, text_field.textHeight+5, true , 0x00000000); { var matrix : Matrix = new Matrix(1,0,0,1,0,0); var color : ColorTransform = new ColorTransform(1,1,1,1,0,0,0,0); var rect : Rectangle = new Rectangle(0,0,bmp_data.width,bmp_data.height); bmp_data.draw(text_field, matrix, color, BlendMode.NORMAL, rect, true); } //取り込んだビットマップデータを表示 var bmp_obj:Bitmap = new Bitmap( bmp_data , PixelSnapping.AUTO , true); //セリフをセット addChild(bmp_obj); } {//m_RestTime m_RestTime = in_Time; } } } //!セリフオブジェクト(本体が消えてもセリフを残したい場合に使用) class CBaloonObj extends IObject { //本来出現させるべき位置 protected var m_OriX:Number; protected var m_OriY:Number; //表示の残り時間 protected var m_RestTime:Number; public function CBaloonObj(in_X:Number, in_Y:Number, in_Text:String, in_Time:Number){ m_OriX = in_X; m_OriY = in_Y; SetPos(in_X, in_Y); //Graphic SetAA(in_Text); m_RestTime = in_Time; } override public function Update(in_DeltaTime:Number):void{ {//残り時間のチェック m_RestTime -= in_DeltaTime; if(m_RestTime <= 0.0){ Kill(); } } {//画面内に居ようとする処理 var absX:Number = this.parent.x + m_OriX; var absY:Number = this.parent.y + m_OriY; var trgX:Number = this.x; var trgY:Number = this.y; if(absX - 0.5*this.width < 0){ trgX = -this.parent.x + 0.5*this.width; } if(absX + 0.5*this.width > Main.CAMERA_W){ trgX = -this.parent.x - 0.5*this.width + Main.CAMERA_W; } if(absY - 0.5*this.height < 0){ trgY = -this.parent.y + 0.5*this.height; } if(absY + 0.5*this.height > Main.CAMERA_H){ trgY = -this.parent.y - 0.5*this.height + Main.CAMERA_H; } this.x = trgX; this.y = trgY; } } } //!プレイヤー class CPlayer extends IObject { //=Param= static public const COLLISION_R:Number = 15.0; static public const PLAYER_VX:Number = 100; static public const PLAYER_VY:Number = 150; static public const BULLET_V:Number = 200; //溜めショットの溜め時間 static public const SUPER_SHOT_TIME:Number = 2.0; //=Input= private var m_InputL:int = 0; private var m_InputR:int = 0; private var m_InputU:int = 0; private var m_InputD:int = 0; private var m_InputSpace:int = 0; static public const KEY_S:int = 83; //== protected var m_Dir:Number = 1.0;//右向きなら1、左向きなら-1 protected var m_GroundFlag:Boolean = false; protected var m_BaseVX:Number = 0.0; protected var m_BaseVY:Number = 0.0; protected var m_ShotTimer:Number = -1.0;//マイナスの時はボタンを押していない protected var m_Baloon_Charge:CBaloon; public function CPlayer(in_Stage:Stage) { //Collision m_PhysParam_Density = 2; m_PhysParam_Friction = 0.0; // m_PhysParam_Restitution = 0.0; m_PhysParam_CategoryBits = CATEGORY_PLAYER; m_PhysParam_MaskBits = CATEGORY_TERRAIN | CATEGORY_BLOCK | CATEGORY_ENEMY; m_PhysParam_AllowSleep = false; CreateCollision_Circle(COLLISION_R); //Graphic SetAA("┏(^o^)┛\n ┛┓"); //Type m_Type = TYPE_PLAYER; {//Init Input in_Stage.addEventListener(KeyboardEvent.KEY_DOWN, OnKeyDown); in_Stage.addEventListener(KeyboardEvent.KEY_UP, OnKeyUp); //プレイヤが消える時に、removeしたい } {//Init EventFunc RegisterEventFunc("EnemyDead", OnEnemyDead); } } override protected function OnDestruct():void{ stage.removeEventListener(KeyboardEvent.KEY_DOWN, OnKeyDown); stage.removeEventListener(KeyboardEvent.KEY_UP, OnKeyUp); } override public function Update(in_DeltaTime:Number):void{ {//player update //入力にしたがって動かす m_Body.m_linearVelocity.x = (m_BaseVX + PLAYER_VX * (m_InputR - m_InputL))/PhysManager.PHYS_SCALE; if(m_GroundFlag && m_InputU > 0){ m_Body.m_linearVelocity.y = (m_BaseVY - PLAYER_VY)/PhysManager.PHYS_SCALE; } m_GroundFlag = false; // m_BaseVX = 0.0; // m_BaseVY = 0.0; } {//Power Shot if(m_ShotTimer >= 0.0){ m_ShotTimer += in_DeltaTime; } if(m_ShotTimer >= SUPER_SHOT_TIME && m_Baloon_Charge == null){ m_Baloon_Charge = PushBaloonText("ウーイ"); } //チャージショットを発射したら、セリフを差し替える if(m_ShotTimer < 0.0 && m_Baloon_Charge != null){ m_Baloon_Charge.m_KillFlag = true; m_Baloon_Charge = null; PushBaloonText_Timer("シネ!", 1.0); } } //死亡判定 var deadFlag:Boolean = false; if(m_HP <= 0){ //ダメージ死 deadFlag = true; } if(this.y > Main.RANGE_DY){ //落下死 deadFlag = true; } if(deadFlag){ //ティウンティウンティウンを表示 for(var i:int = 0; i < 8; ++i){ var v:Number = 50.0; var vx:Number = v * Math.cos(2.0*Math.PI * i/8.0); var vy:Number = v * Math.sin(2.0*Math.PI * i/8.0); var playerDeadEffect:CPlayerDeadEffect = new CPlayerDeadEffect(vx, vy); playerDeadEffect.SetPos(this.x, this.y); // GameObjectManager.Regist(playerDeadEffect); playerDeadEffect.OnRegist(parent); } Kill(); } } public function OnGoal():void{ //ゴール判定に触れたら呼ばれる //昇天グラフィックを表示 var playerOnGoal:CPlayerOnGoal = new CPlayerOnGoal(); playerOnGoal.SetPos(this.x, this.y); // GameObjectManager.Regist(playerOnGoal); playerOnGoal.OnRegist(parent); //こいつ自身は消える Kill(); } protected function OnEnemyDead(in_Event:CEventEnemyDead):void{ PushBaloonText_Timer("ヤッタネ", 1.0); } //=Input= private function OnKeyDown(event:KeyboardEvent):void{ if(event.keyCode == Keyboard.LEFT){ m_InputL = 1; m_Dir = -1.0; m_Graphic.scaleX = -1; } if(event.keyCode == Keyboard.RIGHT){ m_InputR = 1; m_Dir = 1.0; m_Graphic.scaleX = 1; } if(event.keyCode == Keyboard.UP){ m_InputU = 1; } if(event.keyCode == Keyboard.DOWN){ m_InputD = 1; } if(event.keyCode == Keyboard.SPACE){ m_InputSpace = 1; } if(event.keyCode == KEY_S){ //ここで生成してしまう // Shot(); if(m_ShotTimer < 0.0){ //溜めを開始 m_ShotTimer = 0.0; } } } private function OnKeyUp(event:KeyboardEvent):void{ if(event.keyCode == Keyboard.LEFT){ m_InputL = 0; } if(event.keyCode == Keyboard.RIGHT){ m_InputR = 0; } if(event.keyCode == Keyboard.UP){ m_InputU = 0; } if(event.keyCode == Keyboard.DOWN){ m_InputD = 0; } if(event.keyCode == Keyboard.SPACE){ m_InputSpace = 0; } if(event.keyCode == KEY_S){ //キーを放したら発射 if(m_ShotTimer >= 0.0){ Shot(); m_ShotTimer = -1.0; } } } //=Shot= //弾の生成 private function Shot():void{ var x:Number = this.x + m_Dir*160.0/PhysManager.PHYS_SCALE; var y:Number = this.y - (COLLISION_R + 80.0)/PhysManager.PHYS_SCALE; var vx:Number = m_Dir * BULLET_V; var vy:Number = 0.0; var text:String = "o"; var damage:int = 1; if(m_ShotTimer >= SUPER_SHOT_TIME){ text = "◎"; damage = 5; } var bullet:CBullet = new CBullet(text, damage); bullet.SetPos(x, y); bullet.SetVel(vx, vy); bullet.OnRegist(parent); } //衝突した時に呼ばれる override public function OnContact(in_Obj:IObject, in_NrmX:Number, in_NrmY:Number):void{ if(in_NrmY > 0.707){//45度より平坦な坂の上でないとジャンプできない m_GroundFlag = true; if(in_Obj.m_Type != TYPE_PIECE){ //破片の慣性は受けないことにする m_BaseVX = in_Obj.m_VX; m_BaseVY = in_Obj.m_VY; } } } } //!プレイヤー死亡時のエフェクト(ティウンティウンティウン) class CPlayerDeadEffect extends IObject { //=Param= static public const ALPHA_INTERVAL:Number = 0.5; private var m_Timer:Number = 0.0; public function CPlayerDeadEffect(in_VX:Number, in_VY:Number) { m_VX = in_VX; m_VY = in_VY; //Collision //なし //Graphic SetAA("◎"); } override public function Update(in_DeltaTime:Number):void{ this.x += m_VX * in_DeltaTime; this.y += m_VY * in_DeltaTime; m_Timer += in_DeltaTime; this.alpha = 0.6 - 0.4*Math.cos(2.0*Math.PI * m_Timer/ALPHA_INTERVAL); } } //!ゴール時のプレイヤー表示 class CPlayerOnGoal extends IObject { //=Param= static public const HEAVEN_VY:Number = -80.0; static public const HEAVEN_H:Number = -15.0; public function CPlayerOnGoal() { //Collision //なし //Graphic SetAA(" ⊂⊃ \n\(^o^)/"); } override public function Update(in_DeltaTime:Number):void{ if(this.y < HEAVEN_H){ return; } this.y += HEAVEN_VY * in_DeltaTime; if(this.y < HEAVEN_H){ CreateAASprite("\n\n\n\n/\\nオワタ!"); } } } //!プレイヤーの弾 class CBullet extends IObject { //=Param= static public const COLLISION_R:Number = 5.0; public function CBullet(in_Text:String, in_Damage:int) { //Collision m_PhysParam_Density = 10; m_PhysParam_Friction = 0.0; // m_PhysParam_Restitution = 0.9; m_PhysParam_CategoryBits = CATEGORY_PLAYER_BULLET; m_PhysParam_MaskBits = CATEGORY_TERRAIN | CATEGORY_BLOCK | CATEGORY_ENEMY; CreateCollision_Circle(COLLISION_R); //Graphic SetAA(in_Text); //Type m_Type = TYPE_PLAYER_BULLET; //Damage m_Damage = in_Damage; } //毎フレーム呼ばれる処理 override public function Update(in_DeltaTime:Number):void{ //重力を相殺するような力をかけることで浮きながら移動 AntiGravity(PhysManager.GRAVITY); } //浮きながら移動するために、重力と反対方向の力をかける public function AntiGravity(in_Gravity:Number):void{ m_Body.m_force.Add(b2Math.MulFV(m_Body.GetMass(), new b2Vec2(0.0, -in_Gravity))); } //衝突した時に呼ばれる override public function OnContact(in_Obj:IObject, in_NrmX:Number, in_NrmY:Number):void{ if(in_Obj.m_Type == TYPE_ENEMY){ in_Obj.m_HP -= m_Damage; } if(in_Obj.m_Type == TYPE_PIECE){ //破片には当たっても消えない return; } Kill(); } } //!敵 class CEnemy extends IObject { //=Param= static public const COLLISION_R:Number = 20.0; public function CEnemy() { //Collision m_PhysParam_Density = 5; m_PhysParam_Friction = 1.0; // m_PhysParam_Restitution = 0.9; m_PhysParam_CategoryBits = CATEGORY_ENEMY; m_PhysParam_MaskBits = CATEGORY_TERRAIN | CATEGORY_BLOCK | CATEGORY_PLAYER | CATEGORY_PLAYER_BULLET | CATEGORY_ENEMY; m_PhysParam_AllowSleep = false; CreateCollision_Circle(COLLISION_R); //Graphic SetAA(" / ̄\ \n| ^o^ |\n \_/"); //Type m_Type = TYPE_ENEMY; //HP m_HP = 3; //Damage m_Damage = 1; } override public function Update(in_DeltaTime:Number):void{ //死亡判定 if(m_HP <= 0){ Kill(); } } //衝突した時に呼ばれる override public function OnContact(in_Obj:IObject, in_NrmX:Number, in_NrmY:Number):void{ if(in_Obj.m_Type == TYPE_PLAYER){ in_Obj.m_HP -= m_Damage; } } override protected function OnDestruct():void{ if(m_HP <= 0){ CreateGroRagdoll(m_AA); } CreateBaloonObj("ウワー!", 1.0); DispatchEvent(new CEventEnemyDead()); } } //!ダメージ床 class CFloor_Damage extends IObject { public function CFloor_Damage(in_LX:Number, in_RX:Number, in_UY:Number, in_DY:Number) { var width:Number = in_RX - in_LX; var height:Number = in_DY - in_UY; m_GraphicW = width; // m_GraphicH = height + 25; m_GraphicH = height; //Collision { m_PhysParam_Density = 0.0;//Fix m_PhysParam_Friction = 0.0; // m_PhysParam_Restitution = 0.9; m_PhysParam_CategoryBits = CATEGORY_TERRAIN; CreateCollision_Box(width, height); } //Graphic { var aa:String = ""; //幅に応じて、AA用の文字列を供給する var floor_top:String = "△△△△△"; var floor1:String = "\^o^/"; var floor2:String = "/^o^\"; // var floor_bottom:String = " ̄ ̄ ̄"; for(var w:Number = 40.0; w <= width; w += 60.0){ floor_top += "△△△△△△"; floor1 += "^o^\^o^/"; floor2 += "^o^/^o^\"; // floor_bottom += " ̄ ̄ ̄ ̄ ̄"; } aa += floor_top; aa += "\n"; var flag:Boolean = true; // for(var h:Number = 5.0; h <= height; h += 15.0) for(var h:Number = 0.0; h <= height; h += 15.0) { if(flag){ aa += floor1; }else{ aa += floor2; } aa += "\n"; flag = !flag; } // aa += floor_bottom; SetAA(aa); } {//枠 var shape:Shape = new Shape(); addChild(shape); shape.x = -width/2.0; shape.y = -height/2.0; /* shape.graphics.lineStyle(1, 0x00000000, 1.0); shape.graphics.beginFill(0xFFFFFF, 0.0); shape.graphics.drawRect(0, 0, width, height); /*/ shape.graphics.lineStyle(1, 0x00000000, 1.0); shape.graphics.moveTo( 0, 0); shape.graphics.lineTo( 0, height); shape.graphics.lineTo(width, height); shape.graphics.lineTo(width, 0); //*/ } //Type { m_Type = TYPE_TERRAIN_DAMAGE; } //Position { SetPos((in_LX+in_RX)/2.0, (in_UY+in_DY)/2.0); } } //衝突した時に呼ばれる override public function OnContact(in_Obj:IObject, in_NrmX:Number, in_NrmY:Number):void{ if(in_Obj.m_Type == TYPE_PLAYER){ in_Obj.m_HP = 0; } } } //! class ObjectParam extends Object {//ブロックを生成する際に渡すパラメータ //ブロックの範囲(絶対座標で端を設定) public var m_LX:Number = 0; public var m_RX:Number = 0; public var m_UY:Number = 0; public var m_DY:Number = 0; /* //コリジョンまわりのパラメータ public var m_PhysParam_Density:Number = 1.0;//密度 public var m_PhysParam_Friction:Number = 0.0;//摩擦 // public var m_PhysParam_Restitution:Number = 0.0;// public var m_PhysParam_CategoryBits:int = 1;//自分のカテゴリー public var m_PhysParam_MaskBits:int = ~0;//どのカテゴリーにぶつかるか public var m_PhysParam_AllowSleep:Boolean = true;//スリープ状態になるか否か public var m_PhysParam_StartSleep:Boolean = false;//スリープ状態で始まるか否か //破壊されてグロ・ラグドールになるか public var m_BecomeGro:Boolean = false; //重力を無視するか public var m_AntiGravity:Boolean = false; /*/ static public const PARAM_NAME:Array = [ "density", "friction", "restitution", "category_bits", "mask_bits", "allow_sleep", "start_sleep", "become_gro", "anti_gravity", "damage_l", "damage_r", "damage_u", "damage_d", ]; //上のPARAM_NAMEのデフォルトの値 public var density:Number = 1.0; public var friction:Number = 0.0; public var restitution:Number = 0.0; public var category_bits:int = 1; public var mask_bits:int = ~0; public var allow_sleep:Boolean = true; public var start_sleep:Boolean = false; public var become_gro:Boolean = false; public var anti_gravity:Boolean = false; public var damage_l:Boolean = false; public var damage_r:Boolean = false; public var damage_u:Boolean = false; public var damage_d:Boolean = false; //*/ }; //!ブロック class CBlock extends IObject { // protected var m_BecomeGro:Boolean = false; // protected var m_AntiGravity:Boolean = false; // protected var m_DamageL:Boolean = false; protected var m_DamageR:Boolean = false; protected var m_DamageU:Boolean = false; protected var m_DamageD:Boolean = false; // public function CBlock(in_LX:Number, in_RX:Number, in_UY:Number, in_DY:Number, in_StartSleep:Boolean = false) public function CBlock(in_Param:ObjectParam) { //Common var width:Number = in_Param.m_RX - in_Param.m_LX; var height:Number = in_Param.m_DY - in_Param.m_UY; //Param m_GraphicW = width; // m_GraphicH = height + 25; m_GraphicH = height; /* m_BecomeGro = in_Param.m_BecomeGro; m_AntiGravity = in_Param.m_AntiGravity; /*/ m_BecomeGro = in_Param["become_gro"]; m_AntiGravity = in_Param["anti_gravity"]; m_DamageL = in_Param["damage_l"]; m_DamageR = in_Param["damage_r"]; m_DamageU = in_Param["damage_u"]; m_DamageD = in_Param["damage_d"]; //*/ //Collision { /* m_PhysParam_Density = in_Param.m_PhysParam_Density;//5.0; m_PhysParam_Friction = in_Param.m_PhysParam_Friction;//1.0; // m_PhysParam_Restitution = 0.9; m_PhysParam_CategoryBits = in_Param.m_PhysParam_CategoryBits;//CATEGORY_TERRAIN; m_PhysParam_MaskBits = in_Param.m_PhysParam_MaskBits;//in_StartSleep; m_PhysParam_AllowSleep = in_Param.m_PhysParam_AllowSleep;//in_StartSleep; m_PhysParam_StartSleep = in_Param.m_PhysParam_StartSleep;//in_StartSleep; if(m_AntiGravity){ m_PhysParam_AllowSleep = false; } /*/ m_PhysParam_Density = in_Param["density"];//5.0; m_PhysParam_Friction = in_Param["friction"];//1.0; // m_PhysParam_Restitution = in_Param["restitution"]; m_PhysParam_CategoryBits = in_Param["category_bits"];//CATEGORY_TERRAIN; m_PhysParam_MaskBits = in_Param["mask_bits"];//in_StartSleep; m_PhysParam_AllowSleep = in_Param["allow_sleep"];//in_StartSleep; m_PhysParam_StartSleep = in_Param["start_sleep"];//in_StartSleep; if(m_AntiGravity){ m_PhysParam_AllowSleep = false; } //*/ CreateCollision_Box(width, height); } //Graphic { var aa:String = ""; //幅に応じて、AA用の文字列を供給する // var floor_top:String = "___"; var floor1:String = "\^o^/"; var floor2:String = "/^o^\"; // var floor_bottom:String = " ̄ ̄ ̄"; for(var w:Number = 40.0; w <= width; w += 60.0){ // floor_top += "_____"; floor1 += "^o^\^o^/"; floor2 += "^o^/^o^\"; // floor_bottom += " ̄ ̄ ̄ ̄ ̄"; } // aa += floor_top; // aa += "\n"; var flag:Boolean = true; // for(var h:Number = 5.0; h <= height; h += 15.0) for(var h:Number = 0.0; h <= height; h += 15.0) { if(flag){ aa += floor1; }else{ aa += floor2; } aa += "\n"; flag = !flag; } // aa += floor_bottom; SetAA(aa); } {//枠 var shape:Shape = new Shape(); addChild(shape); shape.x = -width/2.0; shape.y = -height/2.0; shape.graphics.lineStyle(1, 0x00000000, 1.0); shape.graphics.beginFill(0xFFFFFF, 0.0); shape.graphics.drawRect(0, 0, width, height); } //Type { m_Type = TYPE_TERRAIN; } //Position { SetPos((in_Param.m_LX+in_Param.m_RX)/2.0, (in_Param.m_UY+in_Param.m_DY)/2.0); } } //毎フレーム呼ばれる処理 override public function Update(in_DeltaTime:Number):void{ if(m_AntiGravity){ //重力を相殺するような力をかけることで浮きながら移動 AntiGravity(PhysManager.GRAVITY); } //死亡判定 if(m_HP <= 0){ Kill(); CreateGroRagdoll(m_AA); // DispatchEvent(new CEventEnemyDead()); } } //浮きながら移動するために、重力と反対方向の力をかける public function AntiGravity(in_Gravity:Number):void{ m_Body.m_force.Add(b2Math.MulFV(m_Body.GetMass(), new b2Vec2(0.0, -in_Gravity))); } //衝突した時に呼ばれる override public function OnContact(in_Obj:IObject, in_NrmX:Number, in_NrmY:Number):void{ if(m_BecomeGro){ if(in_Obj.m_Type == TYPE_PLAYER_BULLET){ m_HP = 0; } } /* //in_NrmX > 0.0//自分の右に当たった //in_NrmX < 0.0//自分の右に当たった //in_NrmY > 0.0//自分の下に当たった //in_NrmY < 0.0//自分の上に当たった if(m_DamageL){ if(in_NrmX < 0.0){ SendMessage(in_Obj, CEventDamage(10)); } } //*/ } } //!ゴール0 class CGoal extends IObject { // private var m_Player:CPlayer; //=Param= static public const COLLISION_R:Number = 20.0; public function CGoal(in_Player:CPlayer) { m_Player = in_Player; //Collision //なし //Graphic SetAA("____\n| GOAL |\n ̄ ̄ ̄ ̄"); } override public function Update(in_DeltaTime:Number):void{ if(m_Player == null){ //すでにゴールした return; } var gapX:Number = m_Player.x - this.x; var gapY:Number = m_Player.y - this.y; if(Math.sqrt(gapX*gapX + gapY*gapY) < COLLISION_R){ m_Player.OnGoal(); m_Player = null; } } } //! class IEvent { public var m_Type:String = ""; } //! class CEventEnemyDead extends IEvent { static public const EVENT_TYPE:String = "EnemyDead"; public function CEventEnemyDead(){ m_Type = EVENT_TYPE; } }