【Egret Engine】1000個作っても大丈夫!p2.js物理ボールの生成方法
2019-02-07
はじめに
過去記事のように、何度か p2.js 物理エンジンを使用したボールの生成を行ってきました。
これらのコードをより軽く、拡張性の高いコードを作成したので公開します。
過去記事
【EgretEngine】p2.js 物理エンジンを使用した自然落下
【EgretEngine】p2.js 物理エンジンを使用して1000個の玉を描画する方法
1000個作っても大丈夫!p2.js物理ボールの生成方法
Main.ts
class Main extends egret.DisplayObjectContainer {
private createPhysicsBall :CreatePhysicsBall[] = [];
private world : p2.World;
private BallNumber : number = 1000;
public constructor() {
super();
this.once(egret.Event.ADDED_TO_STAGE, this.addToStage, this);
}
private addToStage(event:egret.Event) {
this.world = new p2.World();
this.world.sleepMode = p2.World.BODY_SLEEPING;
this.world.gravity = [0, 9.8*50];
//見えない壁や地面の生成
for(let i = 0; i < 3; i++){
const planeBody: p2.Body[] = [];
planeBody[i] = new p2.Body({fixedRotation:true ,type:p2.Body.STATIC});
const planeShape: p2.Plane[] = [];
planeShape[i] = new p2.Plane();
switch(i){
//地面
case 0:
planeBody[i].position= [0, 700];
planeBody[i].angle = Math.PI;//rad表記
break;
//右の壁
case 1:
planeBody[i].position= [1260, 700];
planeBody[i].angle = Math.PI/2;//rad表記
break;
//左の壁
case 2:
planeBody[i].position= [20, 700];
planeBody[i].angle = 3* Math.PI/2;//rad表記
break;
}
planeBody[i].addShape(planeShape[i]);
this.world.addBody(planeBody[i]);
}
for(let i = 0; i < this.BallNumber; i++){
this.createPhysicsBall[i] = new CreatePhysicsBall(this.world, i , i);
this.createPhysicsBall[i].drawBall();
this.addChild(this.createPhysicsBall[i]);
}
//ループ処理
this.addEventListener(egret.Event.ENTER_FRAME,this.worldBigin,this);
}
private worldBigin(dt: number): Boolean{
//bodyを自然落下
this.world.step(1/60, dt/1000, 10);
//console.log(this.body.position[1]);
for(let i = 0; i < this.BallNumber; i++){
this.createPhysicsBall[i].moveBall();
}
return false;
}
}CreatePhysicsBall.ts
class CreatePhysicsBall extends egret.DisplayObjectContainer {
/**
* クラスに代入されて引数の受け取り用変数
*/
protected dx : number = 1;
protected dy : number = 1;
protected world;
protected ballPositionX : number = 30;
protected ballPositionY : number = 100;
public constructor(world : p2.World, dx :number, dy :number) {
super();
this.world = world;
this.dx = dx;
this.dy = dy;
//this.once(egret.Event.ADDED_TO_STAGE, this.addToStage, this);
}
//図形の表示用オブジェクトのインスタンス化
private shape:egret.Shape;
//物理挙動をもつコライダーの生成
private body : p2.Body;
private bodyShape : p2.Circle;
public worldBigin(dt: number): Boolean{
//bodyを自然落下
this.world.step(1/60, dt/1000, 10);
//console.log(this.body.position[1]);
this.moveBall();
return false;
}
//ボールの描画
public drawBall() {
this.shape = new egret.Shape();
this.addChild(this.shape);
this.body = new p2.Body({mass:1, position:[this.ballPositionX + this.dx,+ this.ballPositionY - this.dx * 10], fixedRotation:true});
this.bodyShape = new p2.Circle({ radius: 5 });
this.body.addShape(this.bodyShape);
this.world.addBody(this.body);
//bodyを自然落下
this.shape.x = this.body.position[0];
this.shape.y = this.body.position[1];
this.shape.graphics.beginFill(0xffd700);
this.shape.graphics.drawCircle(0, 0, 5);
this.shape.graphics.endFill();
}
public moveBall(){
this.shape.x = this.body.position[0];
this.shape.y = this.body.position[1];
this.addChild(this.shape);
}
}
GitHub
https://github.com/squmari/EgretEngine/tree/master/PhysicsBall1000