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を作成し
動かないBodyとタイマーに合わせて出現する動くBodyを作り、
Bodyに衝突した時の処理を作りました。
最初にlemonovelにロードする事を目的としていると言いながら
lemonovelについてがまったく出てきませんでしたね。
少しづつ出てきます。
lemonovelを使う人ってFlashに親しみがある、もしくは使い勝手の良さを感じているけど
Flashのみでゲームを作成する事が出来ない方が使うと思うので
ミニゲーム自体の作り方もそこそこ記載した方が良いかな、と思ったんです。
ゲームがFlashで作れるくらいならlemonovel使わないと思いますので……
では、今回は効果音とBGMと背景を付けたいと思います。
まず、背景とBGMはライブラリに読み込んで
ステージにドーンです。
タイムラインは全部1フレームのみ。
ちなみに背景を敷くとコンテナやジョイントの描画が隠れて見えなくなります。
もちろん描画をやめれば表示されなくなりますが
デバック用に残しておいても良いと思います。
se1.mp3・se2.mp3・se3.mp3の効果音を
それぞれライブラリに追加し
se1、se2、se3というクラス名でASリンゲージしました。
// 斬撃の効果音 public var ZanSe:se1 = new se1(); // 攻撃の効果音 public var BanSe:se2 = new se2(); // 補助の効果音 public var KiraSe:se3 = new se3();
名前が前回当たりからだんだんいい加減になっていますが許して下さい。
効果音の読み込みです。
斬撃がボスに攻撃した時の音(ザシュ)で
攻撃が敵と接触した時の音(バーン)で
補助が仲間に接触した時の音(キラキラ)です。
public var mySoundTransform = soundTransform;
ボリュームを設定する為の定義
mySoundTransform.volume=0.5; soundTransform = mySoundTransform;
ここは本来であればlemonovel内でロードした際
lemonovel本体で設定したボリュームを受け渡し
設定するのですがまだlemonovel用のコードにまったくなっていないので一旦「0.5」を設定して置きます。
ZanSe.play(0,1,mySoundTransform);
ボスや敵や仲間の衝突時に音を出します。
◆ポップアップでサンプルswfを開く
(ボス・仲間・敵・エフェクト・背景画像:MGS技研/BGM:魔王魂)
背景が追加されBGMが流れ衝突時に音がなるようになりました。
一応、適当ではありますがこちらのミニゲームをlemonovelに組み込む部分を次回書こうと思います。
ちなみにこの状態のswfをlemonovelで読み込むと一切動きません……
ので、どのように動くまで改変して行ったかを記載していきます。
◆サンプルソース全文
(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 game07 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 var ZanSe:se1 = new se1(); // 攻撃の効果音 public var BanSe:se2 = new se2(); // 補助の効果音 public var KiraSe:se3 = new se3(); public var mySoundTransform = soundTransform; public function game07(){ mySoundTransform.volume=0.5; soundTransform = mySoundTransform; 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")) { ZanSe.play(0,1,mySoundTransform); // 斬撃の画像のサイズと位置のセットアップ 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")) { BanSe.play(0,1,mySoundTransform); // 攻撃の画像のサイズと位置のセットアップ 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")) { KiraSe.play(0,1,mySoundTransform); // 補助の画像を読み込んでセットアップ 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; } }
コメント