forked from: Box2Dの練習
あまり変更しない範囲でなんとかアーティファクトを押さえ込んでみました。
・iterationsを増加
・エレベーターを座標の指定ではなく目標座標への速度を与えて動かしてみた。
・fixedRotationで回転を抑制し、かつ質量をかなり重くして動かないように。
(1つあたり100トンありますw Infinityが設定できないかと試したけど無理だった)
角度固定のRevolute Jointで間接的に動かしてもいいかもしれません。
もっといい方法があるかも?
/**
* Copyright k0rin ( http://wonderfl.net/user/k0rin )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/sdpJ
*/
// forked from rsakane's Box2Dの練習
// あまり変更しない範囲でなんとかアーティファクトを押さえ込んでみました。
//
// ・iterationsを増加
// ・エレベーターを座標の指定ではなく目標座標への速度を与えて動かしてみた。
// ・fixedRotationで回転を抑制し、かつ質量をかなり重くして動かないように。
// (1つあたり100トンありますw Infinityが設定できないかと試したけど無理だった)
//
// 角度固定のRevolute Jointで間接的に動かしてもいいかもしれません。
// もっといい方法があるかも?
package
{
import Box2D.Collision.*;
import Box2D.Common.Math.*;
import Box2D.Dynamics.*;
import Box2D.Collision.Shapes.*;
import flash.display.Sprite;
import flash.display.StageScaleMode;
import flash.display.StageAlign;
import flash.events.Event;
import flash.utils.*;
[SWF(width="465", height="465", frameRate="30", backgroundColor="0x000000")]
public class Test extends Sprite
{
private var iterations:int = 10;
private var timeStep:Number = 1.0 / 30.0;
private var world:b2World;
private const SCALE:Number = 100;
public function Test()
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
box2dInit();
addEventListener(Event.ENTER_FRAME, step, false, 0, true);
}
public function box2dInit():void
{
var worldAABB:b2AABB = new b2AABB();
worldAABB.lowerBound.Set(-100.0, -100.0);
worldAABB.upperBound.Set(100.0, 100.0);
var gravity:b2Vec2 = new b2Vec2(0.0, 10);
var doSleep:Boolean = true;
world = new b2World(worldAABB, gravity, doSleep);
var dbgDraw:b2DebugDraw = new b2DebugDraw();
dbgDraw.m_sprite = this;
dbgDraw.m_drawScale = SCALE;
dbgDraw.m_fillAlpha = 0.3;
dbgDraw.m_lineThickness = 1.0;
dbgDraw.m_alpha = 1.0;
dbgDraw.m_xformScale = 1.0
dbgDraw.m_drawFlags = b2DebugDraw.e_shapeBit;
world.SetDebugDraw(dbgDraw);
createPolygon(stage.stageWidth / 2 / SCALE, 1.0, 354, 1.1, 0.1);
createPolygon(stage.stageWidth / 4 / SCALE, 2.1, 20, 1.2, 0.1);
createPolygon(stage.stageWidth / 2 / SCALE, 3.2, 354, 1.1, 0.1);
createPolygon(stage.stageWidth / 4 / SCALE, 4.0, 12, 2.3, 0.1);
createPolygon(0.5, 5.1, 0, 6, 0.5);
createPolygon(0, stage.stageHeight / 2 / SCALE, 90, stage.stageHeight / 2 / SCALE, 0.1);
createPolygon(3.32, stage.stageHeight / 2 / SCALE, 90, 1.5, 0.1);
createPolygon(4.58, stage.stageHeight / 2 / SCALE, 90, stage.stageHeight / 2 / SCALE, 0.1);
for (var i:int = 0; i < 14; i++)
{
//if (i % 2) createPolygon(3.7, i * 0.4, 0, 0.23, 0.1, "elevator");
//else createPolygon(4.2, i * 0.4, 0, 0.23, 0.1, "elevator");
}
for (i = 0; i < 20; i++)
{
createCircle(0.7, -i * 0.05, 0.1, true, 1.0, 0.5);
}
}
private function createCircle(posX:Number, posY:Number, radius:Number, setMass:Boolean = false, density:Number = 0.0, restitution:Number = 0.0):void
{
var ballBodyDef:b2BodyDef = new b2BodyDef();
ballBodyDef.position.Set(posX, posY);
var ballShape:b2CircleDef = new b2CircleDef();
ballShape.radius = radius;
ballShape.density = density;
ballShape.restitution = restitution;
var ballBody:b2Body = world.CreateBody(ballBodyDef);
ballBody.CreateShape(ballShape);
if (setMass) ballBody.SetMassFromShapes();
}
private function createPolygon(posX:Number, posY:Number, degree:Number, hx:Number, hy:Number, id:String = "", density:Number = 0.0, restitution:Number = 0.0,
setMass:Boolean = false):void
{
var blockBodyDef:b2BodyDef = new b2BodyDef();
blockBodyDef.position.Set(posX, posY);
blockBodyDef.angle = degree * Math.PI / 180;
if (id)
{
blockBodyDef.userData = new Object();
blockBodyDef.userData.id = id;
blockBodyDef.userData.posX = posX;
blockBodyDef.userData.posY = posY;
}
blockBodyDef.fixedRotation = true;
var blockShape:b2PolygonDef = new b2PolygonDef();
blockShape.SetAsBox(hx, hy);
blockShape.density = density;
blockShape.restitution = restitution;
blockShape.filter.groupIndex = -1;
var blockBody:b2Body = world.CreateBody(blockBodyDef);
blockBody.CreateShape(blockShape);
if (setMass) blockBody.SetMassFromShapes();
}
private var elevatorCount:int = 0;
private var elevatorLR:int = 0;
private function step(event:Event):void
{
if (++elevatorCount >= 25) {
elevatorCount = 0;
elevatorLR = 1 - elevatorLR;
createPolygon(3.7 + elevatorLR * 0.5, 4.8, 0, 0.23, 0.1, "elevator", 1000000, 0.3, true);
}
var num:int = 0;
for (var b2body:b2Body = world.m_bodyList; b2body; b2body = b2body.m_next)
{
if (b2body.m_userData)
{
if (b2body.m_userData.id == "elevator")
{
b2body.m_userData.posY -= 0.02;
var pos:b2Vec2 = b2body.GetPosition();
b2body.SetLinearVelocity(new b2Vec2((b2body.m_userData.posX - pos.x) * 10, (b2body.m_userData.posY - pos.y) * 10));
if (b2body.GetPosition().y < -0.1) world.DestroyBody(b2body);
if (b2body.GetPosition().y < 0.8) b2body.SetXForm(b2body.GetPosition(), -0.2);
}
}
}
world.Step(timeStep, iterations);
}
}
}