Flashで物理演算を使ったミニゲーム その1「Box2Dについて」
Flashで物理演算を使ったミニゲーム その2「WorldとBodyとジョイント」
Flashで物理演算を使ったミニゲーム その3「動かないBody」
Flashで物理演算を使ったミニゲーム その4「カウントダウンするタイマーと動くBody」
Flashで物理演算を使ったミニゲーム その5「動かないBodyに衝突した時の処理」
Flashで物理演算を使ったミニゲーム その6「動くBodyに衝突した時の処理」
Flashで物理演算を使ったミニゲーム その7「効果音・BGM・背景」
Flashで物理演算を使ったミニゲーム その8「lemonovelで使う」
前回までにWorldと作成し、Bodyを1つ作り、
動かないBodyを作り、タイマーに合わせて出現する動くBodyを作り、
ボスの衝突時の処理の処理を作成しました。
今回はボスの時と似ていますが動くBodyに衝突した時の処理を作りたいと思います。
敵に衝突した時は赤い火花が出て自分の生命を示すクリスタルが1つづつ消えていきます。
仲間に衝突するとピンクの光が出てボスのHPがたくさん減るようにしたいと思います。
衝突時の処理は画像を差し替えて使い回すでフォルダ内は
「Box2D」フォルダ
「caurina」フォルダ
game05.fla
game05.as
Zangeki.png
Kougeki.png
Hojyo.png
ContactListener.as
こんな感じ。
攻撃エフェクト用の画像と補助エフェクト用の画像が増えています。
ステージ側にクリスタルを配置
crystal1、crysta2、crysta3という名前でそれぞれASリンゲージ。
インスタンス名は
crystal1_img、crystal2_img、crystal3_imgという名前がそれぞれついています。
ASリンゲージした時のクラス名とインスタンス名は必ず違う名前にします。
敵と衝突した時の処理はボスと全く一緒ですが
衝突時に敵は消えます。
仲間も衝突した時の処理はボスと一緒ですが
衝突時に仲間は消え、ボスのHPを減す処理を加えてまいす。
// 敵と衝突し、クリスタルが消える if ((bb.m_userData.name == "na_enemy1") || (bb.m_userData.name == "na_enemy2") || (bb.m_userData.name == "na_enemy3")) { var ie:int = int(er_life.text); switch (ie) { case 3: ie = 2; er_life.text = String(ie); removeChild(crystal1_img); break; case 2: ie = 1; er_life.text = String(ie); removeChild(crystal2_img); break; case 1: ie = 0; er_life.text = String(ie); removeChild(crystal3_img); break; case 0: break; } }
クリスタルを消す処理はなぜか衝突時の処理に加えるとうまくいかないので
更新時の処理に加えました。
idしか使ってなかったけどnameも付けたことを思い出したかのようにnameを使います。
これを見て「er_life.text」どこに居るんだと思った方。
ここに居ます(滝汗
どうするか処理に迷って結局見えないところに置いちゃいました。
◆ポップアップでサンプルswfを開く
(ボス・仲間・敵・エフェクト画像:MGS技研)
敵・仲間と衝突した時の処理が加えられ、
敵と衝突するとクリスタルが減り、仲間と衝突するとボスのHPが減るようになりました。
◆サンプルソース全文
(ContactListener.asは変更が無いので省略します)
package{ ////////////////////////////////////////////////////////////////////////////// // インポート ////////////////////////////////////////////////////////////////////////////// import flash.display.MovieClip; import flash.display.Sprite; import flash.display.Bitmap; import flash.events.Event; import Box2D.Common.Math.*; import Box2D.Dynamics.*; import Box2D.Collision.*; import Box2D.Collision.Shapes.*; import Box2D.Dynamics.Joints.b2Joint; import Box2D.Dynamics.Joints.b2MouseJoint; import Box2D.Dynamics.Joints.b2MouseJointDef; import Box2D.Dynamics.Joints.b2RevoluteJoint; import Box2D.Dynamics.Joints.b2RevoluteJointDef; import caurina.transitions.Tweener; import flash.events.MouseEvent; import flash.utils.Timer; import flash.events.TimerEvent; import flash.text.*; public class game06 extends Sprite{ //定数定義 private static const DRAW_SCALE:Number = 30; // ジョイントの定義 private var mouseJointDef:b2MouseJointDef; private var mouseJoint:b2MouseJoint; // 値セット用 private var centerX:Number; private var centerY:Number; // 斬撃の画像 [Embed(source='Zangeki.png')] private static const ZanImage:Class; // 攻撃の画像 [Embed(source='Kougeki.png')] private static const KouImage:Class; // 補助の画像 [Embed(source='Hojyo.png')] private static const HoImage:Class; public function game06(){ createWorld(); createMy(); createBoss(); createEnemy1(); addEventListener(Event.ENTER_FRAME, Update, false, 0, true); var timer:Timer = new Timer(1000); timer.addEventListener(TimerEvent.TIMER,onTimer); timer.start(); } ////////////////////////////////////////////////////////////////////////////// // ワールドの作成 ////////////////////////////////////////////////////////////////////////////// private function createWorld():void{ //物理エンジンのセットアップ var worldAABB:b2AABB = new b2AABB(); worldAABB.lowerBound.Set(-100,-100); worldAABB.upperBound.Set(100,100); //重力のセットアップ var gravity:b2Vec2 = new b2Vec2(0.0, 0.4); //範囲・重力・スリープの有無 var doSleep:Boolean = true; // ワールド内のセットアップ m_world = new b2World(worldAABB, gravity, true); // ワールド内座標の設定 centerX = stage.stageWidth / 2 / DRAW_SCALE; centerY = stage.stageHeight / 2 / DRAW_SCALE; // 上 var bodyTop:b2BodyDef = new b2BodyDef(); bodyTop.position.Set(centerX, 0); var topShapeDef:b2PolygonDef = new b2PolygonDef(); topShapeDef.SetAsBox(centerX, 0.2); topShapeDef.density = 0; // 下 var bodyBottom:b2BodyDef = new b2BodyDef(); bodyBottom.position.Set(centerX, centerY * 2); var BottomShapeDef:b2PolygonDef = new b2PolygonDef(); BottomShapeDef.SetAsBox(centerX, 0.2); BottomShapeDef.density = 0; // 右 var bodyRight:b2BodyDef = new b2BodyDef(); bodyRight.position.Set(centerX * 2, centerY); bodyRight.angle = Math.PI; var rightShapeDef:b2PolygonDef = new b2PolygonDef(); rightShapeDef.SetAsBox(0.2, centerY); rightShapeDef.density = 0; // 左 var bodyLeft:b2BodyDef = new b2BodyDef(); bodyLeft.position.Set(0, centerY); bodyLeft.angle = Math.PI; var leftShapeDef:b2PolygonDef = new b2PolygonDef(); leftShapeDef.SetAsBox(0.2, centerY); leftShapeDef.density = 0; var top:b2Body = m_world.CreateBody(bodyTop); top.CreateShape(topShapeDef); var bottom:b2Body = m_world.CreateBody(bodyBottom); bottom.CreateShape(BottomShapeDef); var right:b2Body = m_world.CreateBody(bodyRight); right.CreateShape(rightShapeDef); var left:b2Body = m_world.CreateBody(bodyLeft); left.CreateShape(leftShapeDef); // 描画設定 var debugDraw:b2DebugDraw = new b2DebugDraw(); debugDraw.m_sprite = this; debugDraw.m_drawScale = DRAW_SCALE; debugDraw.m_fillAlpha = 0.3; debugDraw.m_lineThickness = 1; debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit; m_world.SetDebugDraw(debugDraw); // イベントハンドラの登録 addEventListener(Event.ENTER_FRAME, enterFrameHandler); stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler); stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler); stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler); // コンタクトリスナ var contactListener:ContactListener = new ContactListener(); contactListener.parent = this; m_world.SetContactListener(contactListener); } ////////////////////////////////////////////////////////////////////////////// // 自分の作成 ////////////////////////////////////////////////////////////////////////////// private function createMy():void{ var body:b2Body; var bodyDef:b2BodyDef; var boxDef:b2PolygonDef; var circleDef:b2CircleDef; bodyDef = new b2BodyDef(); bodyDef.position.x = 10; bodyDef.position.y = 15; circleDef = new b2CircleDef(); circleDef.radius = 1.66; circleDef.density = 0.3; circleDef.friction = 0.2; circleDef.restitution = 0.5; bodyDef.userData = new my(); bodyDef.userData.id = 'id_my'; bodyDef.userData.name = 'na_my'; bodyDef.userData.enable = true; bodyDef.userData.width = 100; bodyDef.userData.height = 100; body = m_world.CreateBody(bodyDef); body.CreateShape(circleDef); body.SetMassFromShapes(); addChild(bodyDef.userData); // ジョイントの定義 mouseJointDef = new b2MouseJointDef(); mouseJointDef.body1 = m_world.GetGroundBody(); mouseJointDef.body2 = body; mouseJointDef.target = body.GetWorldCenter(); mouseJointDef.maxForce = 30; mouseJointDef.timeStep = 1 / 24; } ////////////////////////////////////////////////////////////////////////////// // ボスの作成 ////////////////////////////////////////////////////////////////////////////// private function createBoss():void{ var body:b2Body; var bodyDef:b2BodyDef; var boxDef:b2PolygonDef; var circleDef:b2CircleDef; bodyDef = new b2BodyDef(); bodyDef.position.x = 13.5; bodyDef.position.y = 4; boxDef = new b2PolygonDef(); boxDef.SetAsBox(312.5 / 2 / DRAW_SCALE, 200 / 2 / DRAW_SCALE); boxDef.density = 0; bodyDef.userData = new boss(); bodyDef.userData.id = 'id_boss'; bodyDef.userData.name = 'na_boss'; bodyDef.userData.enable = true; bodyDef.userData.width = 312.5; bodyDef.userData.height = 200; body = m_world.CreateBody(bodyDef); body.CreateShape(boxDef); body.SetMassFromShapes(); addChild(bodyDef.userData); } ////////////////////////////////////////////////////////////////////////////// // 敵1の作成 ////////////////////////////////////////////////////////////////////////////// private function createEnemy1():void{ var body:b2Body; var bodyDef:b2BodyDef; var boxDef:b2PolygonDef; var circleDef:b2CircleDef; bodyDef = new b2BodyDef(); bodyDef.position.Set(25.5 / 2, 2); circleDef = new b2CircleDef(); circleDef.radius = 1.16; circleDef.density = 0.8; circleDef.friction = 0; circleDef.restitution = 1; bodyDef.userData = new enemy(); bodyDef.userData.id = 'id_enemy1'; bodyDef.userData.name = 'na_enemy1'; bodyDef.userData.enable = true; bodyDef.userData.width = 70; bodyDef.userData.height = 70; body = m_world.CreateBody(bodyDef); body.CreateShape(circleDef); body.SetLinearVelocity(new b2Vec2(5, 0)); body.SetMassFromShapes(); addChild(bodyDef.userData); } ////////////////////////////////////////////////////////////////////////////// // 敵2の作成 ////////////////////////////////////////////////////////////////////////////// private function createEnemy2():void{ var body:b2Body; var bodyDef:b2BodyDef; var boxDef:b2PolygonDef; var circleDef:b2CircleDef; bodyDef = new b2BodyDef(); bodyDef.position.Set(25.5 / 2, 2); circleDef = new b2CircleDef(); circleDef.radius = 1.16; circleDef.density = 0.8; circleDef.friction = 0; circleDef.restitution = 1; bodyDef.userData = new enemy(); bodyDef.userData.id = 'id_enemy2'; bodyDef.userData.name = 'na_enemy2'; bodyDef.userData.enable = true; bodyDef.userData.width = 70; bodyDef.userData.height = 70; body = m_world.CreateBody(bodyDef); body.CreateShape(circleDef); body.SetLinearVelocity(new b2Vec2(5, 0)); body.SetMassFromShapes(); addChild(bodyDef.userData); } ////////////////////////////////////////////////////////////////////////////// // 敵3の作成 ////////////////////////////////////////////////////////////////////////////// private function createEnemy3():void{ var body:b2Body; var bodyDef:b2BodyDef; var boxDef:b2PolygonDef; var circleDef:b2CircleDef; bodyDef = new b2BodyDef(); bodyDef.position.Set(25.5 / 2, 2); circleDef = new b2CircleDef(); circleDef.radius = 1.16; circleDef.density = 0.8; circleDef.friction = 0; circleDef.restitution = 1; bodyDef.userData = new enemy(); bodyDef.userData.id = 'id_enemy3'; bodyDef.userData.name = 'na_enemy3'; bodyDef.userData.enable = true; bodyDef.userData.width = 70; bodyDef.userData.height = 70; body = m_world.CreateBody(bodyDef); body.CreateShape(circleDef); body.SetLinearVelocity(new b2Vec2(5, 0)); body.SetMassFromShapes(); addChild(bodyDef.userData); } ////////////////////////////////////////////////////////////////////////////// // 仲間1の作成 ////////////////////////////////////////////////////////////////////////////// private function createFriend1():void{ var body:b2Body; var bodyDef:b2BodyDef; var boxDef:b2PolygonDef; var circleDef:b2CircleDef; bodyDef = new b2BodyDef(); bodyDef.position.Set(25.5 / 2, 2); circleDef = new b2CircleDef(); circleDef.radius = 1.16; circleDef.density = 0.1; circleDef.friction = 0; circleDef.restitution = 1; bodyDef.userData = new friend(); bodyDef.userData.id = 'id_friend1'; bodyDef.userData.name = 'na_friend1'; bodyDef.userData.enable = true; bodyDef.userData.width = 70; bodyDef.userData.height = 70; body = m_world.CreateBody(bodyDef); body.CreateShape(circleDef); body.SetLinearVelocity(new b2Vec2(5, 0)); body.SetMassFromShapes(); addChild(bodyDef.userData); } ////////////////////////////////////////////////////////////////////////////// // 仲間2の作成 ////////////////////////////////////////////////////////////////////////////// private function createFriend2():void{ var body:b2Body; var bodyDef:b2BodyDef; var boxDef:b2PolygonDef; var circleDef:b2CircleDef; bodyDef = new b2BodyDef(); bodyDef.position.Set(25.5 / 2, 2); circleDef = new b2CircleDef(); circleDef.radius = 1.16; circleDef.density = 0.1; circleDef.friction = 0; circleDef.restitution = 1; bodyDef.userData = new friend(); bodyDef.userData.id = 'id_friend2'; bodyDef.userData.name = 'na_friend2'; bodyDef.userData.enable = true; bodyDef.userData.width = 70; bodyDef.userData.height = 70; body = m_world.CreateBody(bodyDef); body.CreateShape(circleDef); body.SetLinearVelocity(new b2Vec2(5, 0)); body.SetMassFromShapes(); addChild(bodyDef.userData); } ////////////////////////////////////////////////////////////////////////////// // 仲間3の作成 ////////////////////////////////////////////////////////////////////////////// private function createFriend3():void{ var body:b2Body; var bodyDef:b2BodyDef; var boxDef:b2PolygonDef; var circleDef:b2CircleDef; bodyDef = new b2BodyDef(); bodyDef.position.Set(25.5 / 2, 2); circleDef = new b2CircleDef(); circleDef.radius = 1.16; circleDef.density = 0.1; circleDef.friction = 0; circleDef.restitution = 1; bodyDef.userData = new friend(); bodyDef.userData.id = 'id_friend3'; bodyDef.userData.name = 'na_friend3'; bodyDef.userData.enable = true; bodyDef.userData.width = 70; bodyDef.userData.height = 70; body = m_world.CreateBody(bodyDef); body.CreateShape(circleDef); body.SetLinearVelocity(new b2Vec2(5, 0)); body.SetMassFromShapes(); addChild(bodyDef.userData); } ////////////////////////////////////////////////////////////////////////////// // ジョイントの処理 ////////////////////////////////////////////////////////////////////////////// private function mouseDownHandler(event:MouseEvent):void { mouseJoint = b2MouseJoint(m_world.CreateJoint(mouseJointDef)); } private function mouseUpHandler(event:MouseEvent):void { m_world.DestroyJoint(mouseJoint); mouseJoint = null; } private function mouseMoveHandler(event:MouseEvent):void { if (mouseJoint) { var x:Number = event.stageX / DRAW_SCALE; var y:Number = event.stageY / DRAW_SCALE; mouseJoint.SetTarget(new b2Vec2(x, y)); } } ////////////////////////////////////////////////////////////////////////////// // 更新時の処理 ////////////////////////////////////////////////////////////////////////////// public function Update(e:Event):void{ m_world.Step(m_timeStep, m_iterations); for (var bb:b2Body = m_world.m_bodyList; bb; bb = bb.m_next){ if (bb.m_userData is Sprite){ bb.m_userData.x = bb.GetPosition().x * 30; bb.m_userData.y = bb.GetPosition().y * 30; bb.m_userData.rotation = bb.GetAngle() * (180/Math.PI); if (bb.m_userData.enable == false) { m_world.DestroyBody(bb); removeChild(getChildByName(bb.m_userData.name)); // 敵と衝突し、クリスタルが消える if ((bb.m_userData.name == "na_enemy1") || (bb.m_userData.name == "na_enemy2") || (bb.m_userData.name == "na_enemy3")) { var ie:int = int(er_life.text); switch (ie) { case 3: ie = 2; er_life.text = String(ie); removeChild(crystal1_img); break; case 2: ie = 1; er_life.text = String(ie); removeChild(crystal2_img); break; case 1: ie = 0; er_life.text = String(ie); removeChild(crystal3_img); break; case 0: break; } } } } } } ////////////////////////////////////////////////////////////////////////////// // 衝突時の処理 ////////////////////////////////////////////////////////////////////////////// public function addContactEffect(point:b2ContactPoint):void { // 衝突したシェイプ var s1:b2Shape = point.shape1; var s2:b2Shape = point.shape2; // 衝突したボディ var b1:b2Body = s1.m_body; var b2:b2Body = s2.m_body; if (b1.m_userData && b2.m_userData) { // ボスと衝突した if ((b1.m_userData.id == "id_my" && b2.m_userData.id == "id_boss") || (b2.m_userData.id == "id_my" && b1.m_userData.id == "id_boss")) { // 斬撃の画像のサイズと位置のセットアップ var zanImage:Bitmap = new ZanImage(); zanImage.width = 50; zanImage.height = 50; zanImage.x = -zanImage.width / 2; zanImage.y = -zanImage.height / 2; var spritez:Sprite = new Sprite(); spritez.x = point.position.x * DRAW_SCALE; spritez.y = point.position.y * DRAW_SCALE; spritez.addChild(zanImage); addChild(spritez); var anglez:Number = Math.random() * 360; var lengthz:Number = Math.random() * 100 + 50; var dxz:Number = spritez.x + lengthz * Math.cos(anglez); var dyz:Number = spritez.y + lengthz * Math.sin(anglez); // Tweenerで斬撃画像を飛ばす Tweener.addTween(spritez, { time: 3, scaleX: 0, scaleY: 0, alpha: 0, rotation: 600, x: dxz, y: dyz, onComplete: function():void { removeChild(spritez); } }); var i:int = int(lp_txt.text); i = i-20; lp_txt.text = String(i); } // 敵と衝突した if ((b1.m_userData.id == "id_my" && b2.m_userData.id == "id_enemy1") || (b2.m_userData.id == "id_my" && b1.m_userData.id == "id_enemy1") || (b1.m_userData.id == "id_my" && b2.m_userData.id == "id_enemy2") || (b2.m_userData.id == "id_my" && b1.m_userData.id == "id_enemy2") || (b1.m_userData.id == "id_my" && b2.m_userData.id == "id_enemy3") || (b2.m_userData.id == "id_my" && b1.m_userData.id == "id_enemy3")) { // 攻撃の画像のサイズと位置のセットアップ var kouImage:Bitmap = new KouImage(); kouImage.width = 50; kouImage.height = 50; kouImage.x = -kouImage.width / 2; kouImage.y = -kouImage.height / 2; var sprite:Sprite = new Sprite(); sprite.x = point.position.x * DRAW_SCALE; sprite.y = point.position.y * DRAW_SCALE; sprite.addChild(kouImage); addChild(sprite); var angle:Number = Math.random() * 360; var length:Number = Math.random() * 100 + 50; var dx:Number = sprite.x + length * Math.cos(angle); var dy:Number = sprite.y + length * Math.sin(angle); // Tweenerで攻撃画像を飛ばす Tweener.addTween(sprite, { time: 3, scaleX: 0, scaleY: 0, alpha: 0, rotation: 200, x: dx, y: dy, onComplete: function():void { removeChild(sprite); } }); b2.m_userData.enable = false; } // 仲間と衝突した if ((b1.m_userData.id == "id_my" && b2.m_userData.id == "id_friend1") || (b2.m_userData.id == "id_my" && b1.m_userData.id == "id_friend1") || (b1.m_userData.id == "id_my" && b2.m_userData.id == "id_friend2") || (b2.m_userData.id == "id_my" && b1.m_userData.id == "id_friend2") || (b1.m_userData.id == "id_my" && b2.m_userData.id == "id_friend3") || (b2.m_userData.id == "id_my" && b1.m_userData.id == "id_friend3")) { // 補助の画像を読み込んでセットアップ var hoImage:Bitmap = new HoImage(); hoImage.width = 50; hoImage.height = 50; hoImage.x = -hoImage.width / 2; hoImage.y = -hoImage.height / 2; var spriteh:Sprite = new Sprite(); spriteh.x = point.position.x * DRAW_SCALE; spriteh.y = point.position.y * DRAW_SCALE; spriteh.addChild(hoImage); addChild(spriteh); var angleh:Number = Math.random() * 360; var lengthh:Number = Math.random() * 100 + 50; var dxh:Number = spriteh.x + lengthh * Math.cos(angleh); var dyh:Number = spriteh.y + lengthh * Math.sin(angleh); // Tweenerで補助画像を飛ばす Tweener.addTween(spriteh, { time: 3, scaleX: 0, scaleY: 0, alpha: 0, rotation: 0, x: dxh, y: dyh, onComplete: function():void { removeChild(spriteh); } }); b2.m_userData.enable = false; var i2:int = int(lp_txt.text); i2 = i2-20; lp_txt.text = String(i2); } } } ////////////////////////////////////////////////////////////////////////////// // 時間経過ごとの処理 ////////////////////////////////////////////////////////////////////////////// private function onTimer(e:TimerEvent):void{ var i:int = int(disp_txt.text); i = i-1; disp_txt.text = String(i); switch (i) { case 25 : createFriend1(); break; case 20 : createEnemy2(); break; case 15 : createFriend2(); break; case 10 : createEnemy3(); break; case 5 : createFriend3(); break; } } private function enterFrameHandler(event:Event):void { m_world.Step(1 / 24, 10); } public var m_world:b2World; public var m_iterations:int = 10; public var m_timeStep:Number = 1.0/30.0; } }
コメント