jiglibflashでバントの練習 Ver 0.2
2011-01-14
バットの質量をガッツり重くしたら、上手く跳ね返るようになりました。
ただ、力学的にはおかしいので(バットを振っている力を考慮していない)、まだまだ調査します。
---------------------------------------------------------------
2011-01-13
jiglibFlashの習作です。
サンプルコードを元に、jiglibFlashを理解するため、ちょちょいと変更を加えています。
マウス操作でバットを振り、飛んでくるボールに当てるというものです。
跳ね返るようにするためはどのようにすればよいか調査中なため
バットにあたったとき、上手く跳ね返らないのでバントみたいになってしまっています。
/**
* Copyright sasa ( http://wonderfl.net/user/sasa )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/icd1
*/
package
{
import flash.ui.Keyboard;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
import jiglib.cof.JConfig;
import jiglib.geometry.*;
import jiglib.math.*;
import jiglib.physics.*;
import jiglib.physics.constraint.*;
import jiglib.plugin.papervision3d.*;
import org.papervision3d.cameras.CameraType;
import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.core.math.Number3D;
import org.papervision3d.core.math.Plane3D;
import org.papervision3d.core.utils.Mouse3D;
import org.papervision3d.events.*;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.materials.shadematerials.*;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.*;
import org.papervision3d.view.BasicView;
import org.papervision3d.view.layer.ViewportLayer;
import org.papervision3d.view.layer.util.ViewportLayerSortMode;
import org.papervision3d.view.stats.StatsView;
[SWF(width="800", height="600", backgroundColor="#ffffff", frameRate="60")]
public class Main extends BasicView
{
private var mylight:PointLight3D;
private var mouse3D:Mouse3D;
private var shadeMateria:FlatShadeMaterial;
private var ground:RigidBody;
private var ballBody:Vector.<RigidBody>;//ボールの剛体
private var batBody:RigidBody;//バットの剛体
private var onDraging:Boolean = false;
private var currDragBody:RigidBody;
private var dragConstraint:JConstraintWorldPoint;
private var startMousePos:Vector3D;
private var planeToDragOn:Plane3D;
private var keyRight :Boolean = false;
private var keyLeft :Boolean = false;
private var keyForward :Boolean = false;
private var keyReverse :Boolean = false;
private var keyUp:Boolean = false;
private var physics:Papervision3DPhysics;
public function Main():void
{
super(800, 600, true, true, CameraType.TARGET);
init3D();
}
private function init3D():void
{
JConfig.numContactIterations = 12;
physics = new Papervision3DPhysics(scene, 8);
Mouse3D.enabled = true;
mouse3D = viewport.interactiveSceneManager.mouse3D;
viewport.containerSprite.sortMode = ViewportLayerSortMode.INDEX_SORT;
mylight = new PointLight3D(true, true);
mylight.y = 300;
mylight.z = -400;
shadeMateria = new FlatShadeMaterial(mylight, 0x77ee77);
var materiaList :MaterialsList = new MaterialsList();
materiaList.addMaterial(shadeMateria, "all");
ground = physics.createCube(materiaList, 500, 500, 10);
ground.movable = false;
ground.friction = 0.9;
ground.restitution = 8;
viewport.getChildLayer(physics.getMesh(ground)).layerIndex = 1;
var vplObjects:ViewportLayer = new ViewportLayer(viewport,null);
vplObjects.layerIndex = 2;
vplObjects.sortMode = ViewportLayerSortMode.Z_SORT;
viewport.containerSprite.addLayer(vplObjects);
//バットの生成
var batHeight:Number = 200;
shadeMateria = new FlatShadeMaterial(mylight, 0xFFFF00);
var capsuleSkin:Cylinder;
capsuleSkin = new Cylinder(shadeMateria, 20, batHeight);
//バットの原点を長さの半分だけずらす
for each (var v:Vertex3D in capsuleSkin.geometry.vertices) {
v.y += batHeight/2;
}
scene.addChild(capsuleSkin);
vplObjects.addDisplayObject3D(capsuleSkin);
//本当は剛体の中心位置もバット同様にずらす必要がありますが、方法がわからないのでとりあえず長さを二倍にして、バットの先端でも衝突が起きるようにしています。
//但し、本当はモノが何も無いバットの(持っている原点を中心とした)反対側でも衝突が検知されてしまいます。
batBody = new JCapsule(new Pv3dMesh(capsuleSkin), 20, batHeight * 2);
//バットの質量をガッツり重くする。質量0では上手く動かないため(地面のような静的剛体にならない?)、5000程度の値を与えてかなり重くしています。
batBody.mass = 5000;
//摩擦、反発の仕様は調査中のため、適当な値を設定
batBody.friction = 0.8;
batBody.restitution = 0.8;
batBody.moveTo(new Vector3D(50, 100, 0));
PhysicsSystem.getInstance().addBody(batBody);
//ボールの生成
//本当は1個つくればいいのですが、めんどくさかったのでサンプルのコードそのまま使っています。
ballBody = new Vector.<RigidBody>();
var color:uint;
for (var i:int = 0; i < 1; i++)
{
color = (i == 0)?0xff8888:0xeeee00;
shadeMateria = new FlatShadeMaterial(mylight, color);
shadeMateria.interactive = true;
ballBody[i] = physics.createSphere(shadeMateria, 22);
ballBody[i].mass = 2;
ballBody[i].friction = 0.8;
ballBody[i].restitution = 0.8;
ballBody[i].moveTo(new Vector3D( -100, 200, -500));
//ボールに対してZ軸方向に4000の力を加えます。
//一瞬のうちに大きな力を加えることで、ボールが投げられているような動きをします。
ballBody[i].addWorldForce(new Vector3D(0, 0, 4000), ballBody[i].currentState.position);
vplObjects.addDisplayObject3D(physics.getMesh(ballBody[i]));
}
camera.y = mylight.y;
camera.z = mylight.z;
//var stats:StatsView = new StatsView(renderer);
//addChild(stats);
startRendering();
}
private function findSkinBody(skin:DisplayObject3D):int
{
for (var i:String in PhysicsSystem.getInstance().bodies)
{
if (skin == physics.getMesh(PhysicsSystem.getInstance().bodies[i]))
{
return int(i);
}
}
return -1;
}
private function resetBox():void
{
for (var i:int = 0; i < ballBody.length;i++ )
{
if (ballBody[i].currentState.position.y < -200)
{
ballBody[i].moveTo(new Vector3D( -100, 200, -500));
ballBody[i].addWorldForce(new Vector3D(0, 0, 4000), ballBody[i].currentState.position);
}
}
}
private function testFreezeObject():void {
var _body:RigidBody;
for (var i:int = 0; i < ballBody.length; i++ )
{
_body = ballBody[i];
if (_body.isActive)
{
shadeMateria = (i == 0)? new FlatShadeMaterial(mylight, 0xff8888):new FlatShadeMaterial(mylight, 0xeeee00);
shadeMateria.interactive = true;
physics.getMesh(_body).material = shadeMateria;
}
else
{
shadeMateria = new FlatShadeMaterial(mylight, 0xff7777);
shadeMateria.interactive = true;
physics.getMesh(_body).material = shadeMateria;
}
}
}
protected override function onRenderTick(event:Event = null):void {
//剛体の回転はrotationX, rotationY, rotationZと
//pitch, roll, yawがあるみたいです。
//どのように動くかは調査中
batBody.rotationZ = (stage.mouseY / stage.stageHeight) * 180;
batBody.yaw(((stage.stageWidth / 2) - stage.mouseX) / 2);
//バットの位置は初期位置から変えたくないため、毎度初期位置に位置させるコードを追加しています。
batBody.moveTo(new Vector3D(50, 100, 0));
//physics.step();//dynamic timeStep
physics.engine.integrate(0.1);//static timeStep
resetBox();
//testFreezeObject();
super.onRenderTick(event);
}
}
}