前回作ったものに、pngファイルを重ねて表示しました。
動き回る箱が、音符を拾うゲームです。
箱組曲ですねw
Box2Dで落ちる音符が自然でいい感じです。
だいぶ遊べるものに近づいてきました。
ちなみにエンドレスです。ウハハ!拾い続けるのだ!
画面をクリックして、「←」「→」で左右移動、「s」でジャンプです。
今回やっと、無限ジャンプをさせなくしました。
次回は、箱生命体を改め、ちゃんと歩く何か動かそうかなw
それから音符の種類も増やそうと思っています。
今回は、外部ファイルを埋め込んで、
Spriteとして表示できるようにしています。
埋め込み部
ACTIONSCRIPT:
- [Embed(source='hako.png')]
- private var hakoImg:Class;
- private var spt:Sprite;
- [Embed(source = 'onpu.png')]
- private var onpuImg:Class;
表示できるようにして追加
ACTIONSCRIPT:
- var bmp:Bitmap = new hakoImg();
- // 中心座標と重なるように。
- bmp.x = -18;
- bmp.y = -36;
- spt = new Sprite;
- spt.visible = false;
- spt.addChild(bmp);
- addChild(spt);
「箱はどんなことがあっても転ばない」というところで悩みました。
毎フレーム傾きを戻してやることにしました。
ACTIONSCRIPT:
- // 箱生命体は、決して倒れない!
- var xform:b2XForm = square.GetXForm();
- square.SetXForm(xform.position, 0);
書いてみると2行でしたが、果たしてこれが正しいやり方なのか・・・
あとは、地面にいるときだけジャンプ可能にしたのは、
「地面と衝突しているかどうか」でフラグ判定しているだけです。
悩みながらやったのでソースが、だんだん荒くなってきた。
続く!
↓ソース全部
ACTIONSCRIPT:
- package src {
- import Box2D.Collision.b2AABB;
- import Box2D.Collision.b2ContactID;
- import Box2D.Collision.Shapes.b2CircleDef;
- import Box2D.Collision.Shapes.b2PolygonDef;
- import Box2D.Collision.Shapes.b2Shape;
- import Box2D.Common.Math.b2Vec2;
- import Box2D.Common.Math.b2XForm;
- import Box2D.Dynamics.b2Body;
- import Box2D.Dynamics.b2BodyDef;
- import Box2D.Dynamics.b2DebugDraw;
- import Box2D.Dynamics.b2World;
- import Box2D.Dynamics.Contacts.b2ContactEdge;
- import flash.display.Bitmap;
- import flash.display.Sprite;
- import flash.events.Event;
- import flash.events.KeyboardEvent;
- import flash.events.MouseEvent;
- import flash.events.TextEvent;
- import flash.text.TextField;
- import flash.ui.Keyboard;
- import flash.utils.*;
- /**
- * @author okm
- */
- public class LabyrinsSuite extends Sprite{
- private var world:b2World;
- private var square:b2Body;
- private var floor:b2Body;
- // 床と箱生命体が接触しているか
- private var ground:Boolean = false;
- [Embed(source='hako.png')]
- private var hakoImg:Class;
- private var spt:Sprite;
- [Embed(source = 'onpu.png')]
- private var onpuImg:Class;
- private var onpArea:Sprite;
- private var onpCnt:Number = 0;
- private var onpCntText:TextField;
- public function LabyrinsSuite() {
- var textField:TextField = new TextField;
- textField.text = "click me ";
- textField.x = 100;
- textField.y = 100;
- textField.selectable = false;
- this.addChild(textField);
- // 音符とった数のカウント表示用
- onpCntText = new TextField;
- onpCntText.x = 10;
- onpCntText.y = 10;
- onpCntText.text = "0";
- addChild(onpCntText);
- var bmp:Bitmap = new hakoImg();
- // 中心座標と重なるように。
- bmp.x = -18;
- bmp.y = -36;
- spt = new Sprite;
- spt.visible = false;
- spt.addChild(bmp);
- addChild(spt);
- stage.addEventListener(MouseEvent.CLICK, go);
- }
- public function go(event:MouseEvent):void {
- spt.visible = true;
- // 音符取得数初期化
- onpCntText.text = "0";
- onpCnt = 0;
- if (onpArea != null) this.removeChild(onpArea);
- onpArea = new Sprite;
- this.addChild(onpArea);
- stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
- stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
- ////////////////////////////////////////
- // 物理エンジンのセットアップ
- // 縦横200メートルの世界を作成
- var worldAABB:b2AABB = new b2AABB();
- worldAABB.lowerBound.Set(-100, -100);
- worldAABB.upperBound.Set(100, 100);
- // 重力を下方向に10m/s^2とする
- var gravity:b2Vec2 = new b2Vec2(0, 10);
- // 外枠と重力を指定して、物理エンジン全体をセットアップする
- world = new b2World(worldAABB, gravity, true);
- /////////////////////////////////////////////
- // 部屋の作成 横幅 12M 高さ 8M の部屋を作成
- /////////////////////////////////////////////
- // 床
- // 天井の高さは 8M 床の 中心X座標は 7.5M(真ん中)
- var floorBodyDef:b2BodyDef = new b2BodyDef();
- // 床のIDを floor としておく
- floorBodyDef.userData = new Object;
- floorBodyDef.userData.spt = new Sprite;
- floorBodyDef.userData.id = "floor";
- floorBodyDef.position.Set(6, 8);
- // 床の形を、幅12m、厚さ20cmとする
- // 指定するのはその半分の値
- var floorShapeDef:b2PolygonDef = new b2PolygonDef();
- floorShapeDef.friction = 0.1;
- floorShapeDef.SetAsBox(6, 0.1);
- // 床のcategoryBits/maskBits
- floorShapeDef.filter.maskBits = 0x01;
- floorShapeDef.filter.categoryBits = 0x01;
- // 床を動かない物体として作る
- floor = world.CreateBody(floorBodyDef);
- floor.CreateShape(floorShapeDef);
- // 両端の壁 高さは 8M 幅 10cm
- // 左壁
- var leftWallBodyDef:b2BodyDef = new b2BodyDef();
- leftWallBodyDef.userData = new Object;
- leftWallBodyDef.userData.id = "left";
- leftWallBodyDef.userData.spt = new Sprite;
- leftWallBodyDef.position.Set(0.05, 4);
- var wallShapeDef:b2PolygonDef = new b2PolygonDef();
- wallShapeDef.friction = 0;
- wallShapeDef.SetAsBox(0.05, 4);
- var leftWall:b2Body = world.CreateBody(leftWallBodyDef);
- leftWall.CreateShape(wallShapeDef);
- // 右壁
- var rightWallBodyDef:b2BodyDef = new b2BodyDef();
- rightWallBodyDef.userData = new Object;
- rightWallBodyDef.userData.id = "right";
- rightWallBodyDef.userData.spt = new Sprite;
- rightWallBodyDef.position.Set(11.95, 4);
- var rightWall:b2Body = world.CreateBody(rightWallBodyDef);
- rightWall.CreateShape(wallShapeDef);
- ////////////////////////////////////////
- // 箱生命体
- ////////////////////////////////////////
- // 箱の位置を左から2.5m、上から1mとする
- var boxBodyDef:b2BodyDef = new b2BodyDef();
- boxBodyDef.userData = new Object;
- boxBodyDef.userData.id = "hako";
- boxBodyDef.userData.spt = spt;
- boxBodyDef.position.Set(2.5, 1);
- // 箱の幅 40cm 高さ 80cm 重さは 30kg とする
- var boxShapeDef:b2PolygonDef= new b2PolygonDef();
- //boxShapeDef.SetAsOrientedBox(0.3, 0.2, new b2Vec2(0, 0), 0.8);
- boxShapeDef.SetAsBox(0.4, 0.8);
- boxShapeDef.density = 50; // 密度 [kg/m^2] 30/0.6*1
- boxShapeDef.friction = 0.6; // 摩擦係数
- boxShapeDef.restitution = 0; // 反発係数、通常は0~1
- // 箱を動く物体として作る
- var boxBody:b2Body = world.CreateBody(boxBodyDef);
- boxBody.CreateShape(boxShapeDef);
- // SetMassFromShapes で重力が有効になる
- boxBody.SetMassFromShapes();
- square = boxBody;
- ////////////////////////////////////////
- // 描画設定
- var debugDraw:b2DebugDraw = new b2DebugDraw();
- debugDraw.m_sprite = this;
- debugDraw.m_drawScale = 45; // 1mを45ピクセルにする
- debugDraw.m_fillAlpha = 0.3; // 不透明度
- debugDraw.m_lineThickness = 1; // 線の太さ
- debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit;
- world.SetDebugDraw(debugDraw);
- this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
- setInterval(dropBox, 600);
- }
- private function dropBox():void {
- var dropbox_x:Number = this.xRandomInt(11, 1);
- var dropboxBodyDef:b2BodyDef = new b2BodyDef();
- dropboxBodyDef.userData = new Object;
- dropboxBodyDef.userData.id = "dropbox";
- var onpuBmp:Bitmap = new onpuImg();
- onpuBmp.x = -5;
- onpuBmp.y = -7.5;
- var onpu_spt:Sprite = new Sprite;
- onpu_spt.addChild(onpuBmp);
- dropboxBodyDef.userData.spt = onpu_spt;
- dropboxBodyDef.userData.crash = 0;
- dropboxBodyDef.angle = this.xRandomInt(5, 0) / 10;
- dropboxBodyDef.position.Set(dropbox_x, 0.5);
- onpArea.addChild(dropboxBodyDef.userData.spt);
- // 箱の幅 10cm 高さ 15cm 重さは 1kg とする
- var dropboxShapeDef:b2PolygonDef= new b2PolygonDef();
- //boxShapeDef.SetAsOrientedBox(0.3, 0.2, new b2Vec2(0, 0), 0.8);
- dropboxShapeDef.SetAsBox(0.1, 0.15);
- dropboxShapeDef.density = 25; // 密度
- dropboxShapeDef.friction = 0.2; // 摩擦係数
- dropboxShapeDef.restitution = 0.7; // 反発係数、通常は0~1
- // 箱を動く物体として作る
- dropboxShapeDef.filter.categoryBits = 0x01;
- dropboxShapeDef.filter.maskBits = 0x01;
- var dropbox:b2Body = world.CreateBody(dropboxBodyDef);
- dropbox.CreateShape(dropboxShapeDef);
- dropbox.m_linearVelocity.x = this.xRandomInt(2, -2);
- dropbox.SetMassFromShapes();
- }
- private var m_InputL:Number = 0;
- private var m_InputR:Number = 0;
- private var m_InputS:Number = 0;
- private var m_Dir:Number = 0;
- private var moveTime:Number = 0;
- // キーが押されたときの処理
- private function keyDownHandler(event:KeyboardEvent):void {
- square.WakeUp();
- if(event.keyCode == Keyboard.LEFT && m_InputL != 1){
- m_InputL = 1;
- m_InputR = 0;
- m_Dir = -1.0;
- moveTime = 0;
- }
- if(event.keyCode == Keyboard.RIGHT && m_InputR != 1){
- m_InputR = 1;
- m_InputL = 0;
- m_Dir = 1.0;
- moveTime = 0;
- }
- if(event.keyCode == 83){ // s
- m_InputS = 1;
- }
- }
- private function keyUpHandler(event:KeyboardEvent):void {
- if(event.keyCode == Keyboard.LEFT){
- m_InputL = 0;
- }
- if(event.keyCode == Keyboard.RIGHT){
- m_InputR = 0;
- }
- if(event.keyCode == 83){ // s
- m_InputS = 0;
- }
- }
- private function enterFrameHandler(event:Event):void {
- for (var bb:b2Body = world.m_bodyList; bb; bb = bb.m_next) {
- if (bb.m_userData != null && bb.m_userData.spt is Sprite) {
- if (bb.m_userData.id == "dropbox" ) {
- var onp_spt:Sprite = bb.m_userData.spt;
- // もし箱生命体と触れていたら消す
- if(onp_spt.hitTestObject(square.m_userData.spt)){
- onpArea.removeChild(onp_spt);
- world.DestroyBody(bb);
- // 音符取得数追加
- onpCnt++;
- onpCntText.text = onpCnt.toString();
- }
- bb.m_userData.spt.rotation = bb.GetAngle() * (180 / Math.PI);
- }
- bb.m_userData.spt.x = bb.GetPosition().x * 45;
- bb.m_userData.spt.y = bb.GetPosition().y * 45;
- }
- }
- // 箱生命体は、決して倒れない!
- var xform:b2XForm = square.GetXForm();
- square.SetXForm(xform.position, 0);
- var shape:b2Shape;
- // 衝突判定 箱生命体
- /* 今回はとりあえず箱との衝突はカウントしない方向で。
- for (var ce:b2ContactEdge = square.m_contactList; ce != null; ce = ce.next) {
- var obj1:b2Body = ce.contact.GetShape1().m_body;//1つ目のオブジェクト
- var obj2:b2Body = ce.contact.GetShape2().m_body;//2つ目のオブジェクト
- if(obj1.m_userData && obj2.m_userData && ce.contact.GetManifoldCount() == 1){
- if (obj2.m_userData.id == "dropbox") {
- if (obj2.m_userData.crash> 2){
- shape = obj2.GetShapeList();
- shape.m_filter.maskBits = 0x00;
- }else {
- obj2.m_userData.crash++;
- }
- }
- }
- }
- */
- // 衝突判定 床
- ground = false;
- for (var ce:b2ContactEdge = floor.m_contactList; ce != null; ce = ce.next) {
- var obj1:b2Body = ce.contact.GetShape1().m_body;//1つ目のオブジェクト
- var obj2:b2Body = ce.contact.GetShape2().m_body;//2つ目のオブジェクト
- if(obj1.m_userData && obj2.m_userData && ce.contact.GetManifoldCount() == 1){
- if(obj2.m_userData.id == "dropbox"){
- if (obj2.m_userData.crash> 2){
- shape = obj2.GetShapeList();
- shape.m_filter.maskBits = 0x00;
- }else {
- obj2.m_userData.crash++;
- }
- }else if (obj2.m_userData.id == "hako") { // 地面とプレーヤーが接触
- ground = true;
- }
- }
- }
- if (m_InputS == 1 && ground ) {
- square.m_linearVelocity.y = -7;
- }
- if (m_InputL> 0) {
- var leftForce:Number = this.easeInOutQuad(moveTime, 0.5, 6, 30);
- if (moveTime <30) moveTime++;
- square.m_linearVelocity.x = -leftForce;
- square.m_userData.spt.scaleX = -1;
- }
- if (m_InputR> 0) {
- if (moveTime <30) moveTime++;
- var rightForce:Number = this.easeInOutQuad(moveTime, 0.5, 6, 30);
- square.m_linearVelocity.x = rightForce;
- square.m_userData.spt.scaleX = 1;
- }
- if (world == null) {
- return;
- }
- // Flashはデフォルトで秒間24フレームなので、
- // 物理シミュレーションを1/24秒進める
- world.Step(1 / 24, 10);
- }
- /**
- * t = time
- * b = beginning value
- * c = change in value
- * d = duration
- */
- public function easeInOutQuad(t:Number, b:Number, c:Number, d:Number):Number {
- if ((t/=d/2) <1) return c/2*t*t + b;
- return -c/2 * ((--t)*(t-2) - 1) + b;
- };
- public function xRandomInt (nMax:Number, nMin:Number):Number {
- // nMinからnMaxまでのランダムな整数を返す
- var nRandomInt:Number = Math.floor(Math.random()*(nMax-nMin+1))+nMin;
- return nRandomInt;
- }
- }
- }
なんか、あんまテストしないで、できた勢いでアップしてみたけど、、、
♪ ← ありがイッパイいるみたいでキモー!
- Newer: ベジェ曲線と、すごい単純な波の表現
- Older: wordpress に addthis を追加
Comments:0
Trackbacks:0
- Trackback URL for this entry
- http://parpue.net/web/38/trackback
- Listed below are links to weblogs that reference
- Box2D で 降りしきる音符を拾いまわる箱 from parpue.net


