Forked from: hacker_n2ylj3ym's flash on 2009-6-5 diff:1 forked from: flash on 2009-6-5 owo forked:0favorite:0lines:291license : MIT License modified : 2010-04-22 15:27:51 Embed Tweet // forked from hacker_n2ylj3ym's flash on 2009-6-5 package { import Box2D.Collision.Shapes.*; import Box2D.Collision.b2AABB; import Box2D.Common.Math.b2Vec2; import Box2D.Dynamics.Joints.*; import Box2D.Dynamics.b2Body; import Box2D.Dynamics.b2BodyDef; import Box2D.Dynamics.b2DebugDraw; import Box2D.Dynamics.b2World; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.events.TimerEvent; import flash.text.TextField; import flash.utils.Timer; public class Box2DGame2 extends Sprite { private var world:b2World; private var joint1:b2RevoluteJoint; private var joint2:b2RevoluteJoint; private var textfield:TextField; private var payTextfield:TextField; private var coinTextfield:TextField; private var money:int = 30; private var payMoney:int = 0; private var floorList:Array; private static const DRAW_SCALE:Number = 100; public function Box2DGame2():void { init(); addEventListener(Event.ENTER_FRAME, enterFrameHandler); textfield = new TextField(); this.addChild(textfield); } public function init():void { initWorld(); initWall(); initBar(); initPin(); initFloor(); initButton(); } /** * world設定 */ private function initWorld():void { // 外枠を定義する var worldAABB:b2AABB = new b2AABB(); worldAABB.lowerBound.Set(-100, -100); worldAABB.upperBound.Set(100, 100); // 重力加速度 var gravity:b2Vec2 = new b2Vec2(0, 10); // 外枠と重力を指定して、物理エンジン全体をセットアップする world = new b2World(worldAABB, gravity, true); // 描画設定 var debugDraw:b2DebugDraw = new b2DebugDraw(); debugDraw.m_sprite = this; debugDraw.m_drawScale = DRAW_SCALE; // 1mを100ピクセルにする debugDraw.m_fillAlpha = 1; // 不透明度 debugDraw.m_lineThickness = 1; // 線の太さ debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit; world.SetDebugDraw(debugDraw); } /** * ジョイントバーの設置 */ private function initBar():void { joint1 = createJointBar(1.23, 0); joint2 = createJointBar(1.67, 0); } private function createJointBar(x:Number, y:Number):b2RevoluteJoint { // 動くバーの支点となるオブジェクト var point:b2Body = createBox(0.01, 0.01, x, y, 0, true); // 動くバー var bar:b2Body = createBox(0.02, 0.4, x, y + 0.4); // 回転ジョイントの設定 var jointDef:b2RevoluteJointDef = new b2RevoluteJointDef(); jointDef.enableMotor = true; jointDef.motorSpeed = 0; // ここで初期速度を設定すると、joint.SetMoterSpeed()の指定時におかしくなる? jointDef.maxMotorTorque = 300000; // 謎。 0だと動かない jointDef.Initialize(bar, point, point.GetPosition()); // pointにbarをくっつける var joint:b2RevoluteJoint = world.CreateJoint(jointDef) as b2RevoluteJoint; joint.SetMotorSpeed(1); // こっちで初期スピードの設定をする return joint; } /** * ピンの設置 */ private function initPin():void { for (var i:int = 0; i < 7; i++) { for (var j:int = 0; j < 10; j++) { if (i % 2 == 1 && j == 9) { continue; } var x:Number = j*0.3 + (i % 2 == 1 ? 0.15 : 0) + 0.05; var y:Number = i*0.3 + 1.3; // createCircle(0.01, x, y, true); createBox(0.01, 0.01, x, y, Math.PI/4, true); } } } /** * 床の設置 消したり出したりする */ private function initFloor():void { floorList = []; for (var j:int = 0; j < 10; j++) { var x:Number = j*0.3 + 0.05; var y:Number = 6*0.3 + 1.3; // 横の壁 createBox(0.01, 0.2, x, y + 0.2, 0, true); if (j < 9) { // こっちが床 floorList.push(createBox(0.15, 0.01, x + 0.15, y + 0.4, 0, true)); } } } /** * 壁の設置 */ private function initWall():void { createBox(0.05, 3, 3.1, 3, 0, true); createBox(0.05, 3, 4.2, 3, 0, true); createBox(1, 3, -1.25, 3, 0, true); // createBox(0.5, 0.6, 3.6, 3.5, 0, true); createBox(0.07, 0.07, 3.15, 0.8, Math.PI/4, true); createBox(0.07, 0.07, 3.15, 0.7*3 + 0.2, Math.PI/4, true); createBox(0.07, 0.07, 4.15, 0.6*2 + 0.2, Math.PI/4, true); createBox(0.01, 0.01, 3.65 , 0.8*0.5, Math.PI/4, true); createBox(0.01, 0.01, 3.65 , 0.8*1.5, Math.PI/4, true); createBox(0.01, 0.01, 3.65 , 0.8*2.5, Math.PI/4, true); createBox(0.01, 0.01, 3.65 , 0.8*3.5, Math.PI/4, true); } /** * ボタン作成 */ private function initButton():void { // コイン投入ボタン var button:Sprite = new Sprite(); button.graphics.beginFill(0xFFFFFF); button.graphics.drawRoundRectComplex(320, 300, 80, 30, 5, 5, 5, 5); button.graphics.endFill(); button.buttonMode = true; button.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); coinTextfield = new TextField(); coinTextfield.text = '投入: 残' + money+'枚'; coinTextfield.selectable = false; coinTextfield.x = 325; coinTextfield.y = 305; button.addChild(coinTextfield); addChild(button); // 払い出しボタン var buttonPay:Sprite = new Sprite(); buttonPay.graphics.beginFill(0xFFFFFF); buttonPay.graphics.drawRoundRectComplex(320, 340, 80, 30, 5, 5, 5, 5); buttonPay.graphics.endFill(); buttonPay.buttonMode = true; buttonPay.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void { if (payMoney) { var timer:Timer = new Timer(150, payMoney); timer.addEventListener(TimerEvent.TIMER, function (et:TimerEvent):void { createCircle(0.12, Math.random()*0.5 + 3.3, -1); }); timer.addEventListener(TimerEvent.TIMER_COMPLETE, function(et:TimerEvent):void { timer.stop(); }); timer.start(); payMoney = 0; dropCoins(); } }); payTextfield = new TextField(); payTextfield.selectable = false; payTextfield.text = '払戻: 0枚'; payTextfield.x = 330; payTextfield.y = 345; buttonPay.addChild(payTextfield); addChild(buttonPay); } /** * クリック時の処理 */ private function onMouseDown(event:MouseEvent):void { // クリックされた場所に何か落とす if (money > 0) { var circle:b2Body = createCircle(0.12, 1.5, -1); circle.m_userData.name = 'ball'; money--; coinTextfield.text = '投入: 残' + money.toString() +'枚'; } } /** * フレームごとの更新処理 */ private function update():void { // バーを左右に振る var angle:int = joint1.GetJointAngle() / Math.PI * 180; if (angle < -50) { joint1.SetMotorSpeed(0.8); } else if (50 < angle) { joint1.SetMotorSpeed(-0.8); } // 2つめのバーは1つ目のバーと同じ動きをさせる joint2.SetMotorSpeed(joint1.GetMotorSpeed()); var check_list:Array = new Array(9); var hit_list:Array = new Array(9); for (var i:int = 0; i < hit_list.length; i++) { hit_list[i] = 0; } // spriteを描画しつつ点数の計算も行う 処理がすごく怪しい for (var b:b2Body = world.GetBodyList(); b; b = b.GetNext()) { // 物体の位置を更新する処理。中身は後述 if (!b.m_userData || !(b.m_userData as Object).hasOwnProperty('sprite')) { continue; } try { if ((b.m_userData as Object).hasOwnProperty('sprite')) { var sprite:Sprite = b.m_userData.sprite as Sprite; sprite.x = b.GetWorldCenter().x * DRAW_SCALE; sprite.y = b.GetWorldCenter().y * DRAW_SCALE; sprite.rotation = b.GetAngle() * 180 / Math.PI; // 終了判定 for (var j:int = 0; j < 9; j++) { var x:Number = j*0.3 + 0.05 + 0.15; var y:Number = 6*0.3 + 1.3 + 0.35; // 床に落ちた下のコイン if (sprite.hitTestPoint(x * DRAW_SCALE, y * DRAW_SCALE)) { hit_list[j] = 1; if (check_list[j] == 1) { dropCoins(); } } // 床に重なったコインの上のコイン if (sprite.hitTestPoint(x * DRAW_SCALE, (y - 0.35) * DRAW_SCALE)) { check_list[j] = 1; } } } } catch (e:Error) { } } calculatePayment(hit_list); } /** * 払い戻し枚数の計算 * 2枚隣合っていたら4枚、3枚隣り合っていたら8枚,4枚隣り合っていたら16枚・・・ */ private function calculatePayment(hit_list:Array):void { payMoney = 0; var result:String = hit_list.join(''); hit_list = null; result = result.replace(/0+/g, '0'); var list:Array = result.split('0'); for (var i:int = 0; i < list.length; i++) { var value:String = list[i]; if (value.length > 1) { payMoney += Math.pow(2, value.length); } } payTextfield.text = "払戻: " + payMoney.toString() + "枚"; } /** * 床を消してコインを全部落とす */ private function dropCoins():void { for each (var floorBox:b2Body in floorList) { // world.DestroyBodyでb2bodyオブジェクトを削除 world.DestroyBody(floorBox); } floorList = new Array();; // 1秒後に再構築 var timer:Timer = new Timer(1000, 1); timer.addEventListener(TimerEvent.TIMER_COMPLETE, function(te:TimerEvent):void { initFloor(); timer.stop(); }); timer.start(); } /** * 毎フレーム呼び出される */ private function enterFrameHandler(event:Event):void { if (world == null) { return; } update(); world.Step(1 / 48, 10); } ////////////////////////////////////////////////////////////////////////////////// // ここから下はオブジェクト生成用メソッド ////////////////////////////////////////////////////////////////////////////////// /** * 四角形を作成 */ private function createBox(width:Number, height:Number, x:Number, y:Number, angle:Number = 0, is_static:Boolean=false):b2Body { var boxBodyDef:b2BodyDef = new b2BodyDef(); boxBodyDef.position.Set(x, y); var body:b2Body = world.CreateBody(boxBodyDef); body.CreateShape(createBoxShapeDef(width, height, angle, is_static)); if (!is_static) { body.SetMassFromShapes(); } body.m_userData = new Object(); body.m_userData.name = 'box'; return body; } /** * 円作成 */ private function createCircle(radius:Number, x:Number, y:Number, is_static:Boolean = false):b2Body { // 円の場所を設定する var bodyDef:b2BodyDef = new b2BodyDef(); bodyDef.position.Set(x, y); // 円の大きさなどを設定する var shapeDef:b2CircleDef = new b2CircleDef(); shapeDef.radius = radius; shapeDef.density = 1; // 密度 [kg/m^2] shapeDef.restitution = 0.3; // 反発係数、通常は0~1 shapeDef.density = is_static ? 0 : 1; // 円を動く物体として作る var body:b2Body = world.CreateBody(bodyDef); body.CreateShape(shapeDef); if (!is_static) { body.SetMassFromShapes(); } body.m_userData = new Object(); body.m_userData.name = 'circle'; body.m_userData.sprite = createCircleSprite(x, y, radius); this.addChild(body.m_userData.sprite); return body; } private function createCircleSprite(x:Number, y:Number, radius:Number):Sprite { var s:Sprite = new Sprite(); s.graphics.beginFill(0x0000FF, 0); s.graphics.drawCircle(0, 0, radius * DRAW_SCALE); s.graphics.endFill(); s.x = x * DRAW_SCALE; s.y = y * DRAW_SCALE; s.addEventListener(Event.ENTER_FRAME, function(e:Event):void { if (s.y >= 500) { s.parent.removeChild(s); if (315 <= s.x && s.x <= 405) { money++; coinTextfield.text = '投入: 残' + money.toString() +'枚'; } } }); return s; } /** * 箱の形を設定 */ private function createBoxShapeDef(width:Number, height:Number, angle:Number = 0, is_static:Boolean = false):b2PolygonDef { var boxShapeDef:b2PolygonDef= new b2PolygonDef(); if (angle) { // 傾いた物体 boxShapeDef.SetAsOrientedBox(width, height, new b2Vec2(0, 0), angle); } else { // まっすぐな物体 boxShapeDef.SetAsBox(width, height); } boxShapeDef.density = is_static ? 0 : 1; boxShapeDef.restitution = 0.3; // 反発係数、通常は0~1 return boxShapeDef; } } } Code Fullscreen Preview Fullscreen sort new page view favorite forked pv0 forked from: forked from: flas.. owo forked:0 favorite:0lines:291 (diff:1)