なんか夏休みろくにとれなかったので、
最近インドネシアはバリ島に遊びに行ってました。
バリ島は雨季が近いということでスコールも1度味わってきました。
というわけで、雨と風にたなびく葉っぱのようなものを強引にBox2Dで作ってみました。
雨粒のあたり判定が甘いのは仕様です。
ちょっとこれを使ってまた別のものを作ろうと考えています。
↓ 以下、種明かしのようなもの
これをみると、いかに強引かがわかりますね。
ただBox2Dを使うことで、強引でも簡単にそれっぽいものができると思います。

今回は回転ジョイントを用意し、常に葉っぱの先端部分の棒が右回転する力を加えました。
その棒に対して、重りを加え、ときどき重りに下向きの力を加えることによって、
風を受けている感じを表現している・・・つもりです。
以下ソースコード・・・強引です。
FlowLeafを呼び出す Box2DWorldTestクラス
ACTIONSCRIPT:
- package {
- import Box2D.Collision.Shapes.b2CircleDef;
- import Box2D.Collision.Shapes.b2PolygonDef;
- import Box2D.Collision.b2AABB;
- import Box2D.Common.Math.b2Vec2;
- import Box2D.Dynamics.b2Body;
- import Box2D.Dynamics.b2BodyDef;
- import Box2D.Dynamics.b2DebugDraw;
- import Box2D.Dynamics.b2World;
- import flash.display.Sprite;
- import flash.display.StageAlign;
- import flash.events.Event;
- import flash.events.MouseEvent;
- import flash.utils.*;
- public class Box2DWorldTest extends Sprite
- {
- private var world:b2World;
- private var floor:b2Body;
- private var leafArea:Sprite;
- private var dropArea:Sprite;
- private var drop:b2Body;
- private var circleDef:b2BodyDef;
- private var dropShapeDef:b2CircleDef;
- private var f1:FlowLeaf;
- private var f2:FlowLeaf;
- private var f3:FlowLeaf;
- public function Box2DWorldTest()
- {
- stage.scaleMode = "noScale";
- stage.align = StageAlign.TOP_LEFT;
- leafArea = new Sprite;
- dropArea = new Sprite;
- this.addChild(dropArea);
- this.addChild(leafArea);
- // 縦横200メートルの世界を作成
- var worldAABB:b2AABB = new b2AABB();
- worldAABB.lowerBound.Set(-100, -100);
- worldAABB.upperBound.Set(100, 100);
- // 重力を下方向に10m/s^2とする 今回は風の感じで右方向にも1m/s^2
- var gravity:b2Vec2 = new b2Vec2(-1, 10);
- // 外枠と重力を指定して、物理エンジン全体をセットアップする
- world = new b2World(worldAABB, gravity, true);
- f1 = new FlowLeaf(5, 7, 2, 4, 0.5, world, "leaf");
- leafArea.addChild(f1);
- f2 = new FlowLeaf(4, 7, 2, 3, 0.5, world, "leaf");
- leafArea.addChild(f2);
- f3 = new FlowLeaf(3, 7, 2, 3, 0.5, world, "leaf");
- leafArea.addChild(f3);
- var debugDraw:b2DebugDraw = new b2DebugDraw;
- debugDraw.m_sprite = this;
- debugDraw.m_drawScale = 45; // 1mを45ピクセルにする
- debugDraw.m_fillAlpha = 60; // 不透明度
- debugDraw.m_lineThickness = 2; // 線の太さ
- debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit;
- world.SetDebugDraw(debugDraw);
- this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
- circleDef = new b2BodyDef();
- circleDef.userData = new Object;
- circleDef.userData.id = "circle";
- var spt:Sprite = new Sprite;
- spt.graphics.lineStyle(1, 0x6481F5);
- spt.graphics.beginFill(0x6481f5, 50);
- spt.graphics.drawCircle( 0, 0, 4 );
- spt.graphics.endFill();
- spt.y = -10;
- circleDef.userData.spt = spt;
- dropArea.addChild(spt);
- var randomX = Math.floor(Math.random()*(240))+100;
- circleDef.position.Set(randomX / 45, -10);
- dropShapeDef = new b2CircleDef;
- dropShapeDef.radius = 0.15;
- dropShapeDef.restitution = 0.2;
- dropShapeDef.density = 0.5;
- drop = world.CreateBody(circleDef);
- drop.CreateShape(dropShapeDef);
- drop.SetMassFromShapes();
- setInterval(dropRain, 2500);
- }
- private function dropRain():void{
- world.DestroyBody(drop);
- var randomX:Number = Math.floor(Math.random()*(240))+100;
- circleDef.position.Set(randomX / 45, -10 / 45);
- drop = world.CreateBody(circleDef);
- drop.CreateShape(dropShapeDef);
- drop.SetMassFromShapes();
- }
- 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) {
- bb.m_userData.spt.x = bb.GetPosition().x * 45;
- bb.m_userData.spt.y = bb.GetPosition().y * 45;
- }
- }
- var random = Math.floor(Math.random()*10)+1;
- if(random == 1){
- f1.wind(2);
- f2.wind(2);
- f3.wind(2);
- }
- world.Step(1 / 24, 10);
- }
- }
- }
FlowLeaf 葉っぱ一枚分
ACTIONSCRIPT:
- package
- {
- import Box2D.Collision.Shapes.b2CircleDef;
- import Box2D.Collision.Shapes.b2PolygonDef;
- import Box2D.Common.Math.b2Vec2;
- import Box2D.Dynamics.Joints.b2DistanceJointDef;
- import Box2D.Dynamics.Joints.b2RevoluteJoint;
- import Box2D.Dynamics.Joints.b2RevoluteJointDef;
- import Box2D.Dynamics.b2Body;
- import Box2D.Dynamics.b2BodyDef;
- import Box2D.Dynamics.b2World;
- import flash.display.Sprite;
- import flash.events.Event;
- import flash.utils.*;
- public class FlowLeaf extends Sprite
- {
- private var flowBody:b2Body;
- private var fixedBody:b2Body;
- private var sinker:b2Body;
- private var _height:Number;
- private var _width:Number
- private var _x:Number;
- private var _y:Number;
- private var barSize:Number;
- private var bend:Number;
- public function FlowLeaf(x:Number,y:Number,width:Number, height:Number, bend:Number, world:b2World, id:String):void
- {
- barSize = width/10;
- this.x = 45 * x;
- this.y = 45 * y;
- this._height = height;
- this._width = width;
- this._x = x;
- this._y = y;
- this,bend = bend;
- var fixedBodyDef:b2BodyDef = new b2BodyDef;
- fixedBodyDef.userData = new Object;
- fixedBodyDef.userData.id = id;
- fixedBodyDef.position.Set(x - barSize * 0.5, y - height * bend * 0.5);
- var fixedBodyPolygonDef:b2PolygonDef = new b2PolygonDef();
- fixedBodyPolygonDef.friction = 0.1;
- fixedBodyPolygonDef.density = 0.1;
- fixedBodyPolygonDef.SetAsBox(barSize * 0.5, height * bend * 0.5);
- fixedBodyPolygonDef.filter.maskBits = 0x01;
- fixedBodyPolygonDef.filter.categoryBits = 0x01;
- fixedBody = world.CreateBody(fixedBodyDef);
- fixedBody.CreateShape(fixedBodyPolygonDef);
- var flowBodyDef:b2BodyDef = new b2BodyDef;
- flowBodyDef.userData = new Object;
- flowBodyDef.userData.id = id;
- flowBodyDef.position.Set(x - width, y - height);
- var flowBodyPolygonDef:b2PolygonDef = new b2PolygonDef;
- flowBodyPolygonDef.vertices[0].Set(0,0);
- flowBodyPolygonDef.vertices[1].Set(barSize*2, 0);
- flowBodyPolygonDef.vertices[2].Set(width , height - height * bend);
- flowBodyPolygonDef.vertices[3].Set(width -barSize*2, height - height * bend);
- flowBodyPolygonDef.vertexCount = 4;
- flowBodyPolygonDef.friction = 0.5;
- flowBodyPolygonDef.density = 0.1;
- flowBody = world.CreateBody(flowBodyDef);
- flowBody.CreateShape(flowBodyPolygonDef);
- flowBody.SetMassFromShapes();
- var sinkerBodyDef:b2BodyDef = new b2BodyDef;
- sinkerBodyDef.userData = new Object;
- sinkerBodyDef.userData.id = id + "_sinker";
- sinkerBodyDef.position.Set(x - width +barSize , y - height * bend);
- var sinkerShapeDef:b2CircleDef = new b2CircleDef;
- sinkerShapeDef.radius = barSize;
- sinkerShapeDef.density = 0.5;
- sinkerShapeDef.filter.maskBits = 0x00;
- sinker = world.CreateBody(sinkerBodyDef);
- sinker.CreateShape(sinkerShapeDef);
- sinker.SetMassFromShapes();
- var jointDef:b2RevoluteJointDef = new b2RevoluteJointDef;
- jointDef.motorSpeed = 0.3;
- jointDef.maxMotorTorque = 5;
- jointDef.enableMotor = true;
- jointDef.lowerAngle = -20 * Math.PI / 180;
- jointDef.upperAngle = 15 * Math.PI / 180;
- jointDef.enableLimit = true;
- jointDef.Initialize(fixedBody, flowBody, new b2Vec2(flowBody.GetPosition().x + width - barSize / 2, flowBody.GetPosition().y + height * bend));
- var joint:b2RevoluteJoint = b2RevoluteJoint(world.CreateJoint(jointDef));
- var sinkerJointDef:b2DistanceJointDef = new b2DistanceJointDef;
- sinkerJointDef.Initialize(flowBody, sinker, flowBody.GetPosition(), sinker.GetPosition());
- var sinkerJoint = world.CreateJoint(sinkerJointDef);
- this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
- }
- private function enterFrameHandler(event:Event){
- this.graphics.clear();
- this.graphics.lineStyle(1,0x66FF66);
- this.graphics.beginFill(0xCCFFCC, 0.8);
- this.graphics.curveTo(0, - _height * 0.8 * 45,(flowBody.GetPosition().x - _x ) * 45, (flowBody.GetPosition().y - _y )* 45);
- this.graphics.curveTo(0 - barSize * 4 * 45, - _height * 0.8 * 45,0 - barSize * 4 * 45, 0);
- this.graphics.lineTo(0,0);
- this.graphics.endFill();
- }
- public function wind(power:Number):void{
- sinker.m_linearVelocity.y = power;
- }
- }
- }
- Newer: ベジェ曲線と、すごい単純な波の表現(2)
- Older: Box2D オブジェクトにオブジェクトをあてて回転させる
Comments:0
Trackbacks:0
- Trackback URL for this entry
- http://parpue.net/web/329/trackback
- Listed below are links to weblogs that reference
- Box2d で風雨に揺れる葉っぱのようなもの from parpue.net


