【EgretEngine】p2.js 物理エンジンを使用した自然落下

はじめに
この記事では p2.js 物理エンジンを使用して、
EgretEngineのオブジェクトに物理現象を加えていきます。
フィア: 結構むずかしかったね…
カレン: Unityと比べると手順も多いから頑張ろうね
準備
p2.js 物理エンジンのダウンロード
1、egret-game-libraryのダウンロード
GitHubより、「egret-game-library」をダウンロード。
https://github.com/egret-labs/egret-game-library
「egret-game-library」を解凍して、egret-game-library-master/physics/libsrc/binを開きます。
その中の「physics」フォルダを、プロジェクトフォルダがある場所にコピーしてください。
場所は、「Egret Launcher」を起動して、Open project locationを押せば分かります。
2、p2.js物理エンジンの適用
プロジェクトを開き、「egretProperties.json」を開いてください。
次に、
{
"name": "physics",
"path": "../physics"
},を追加してください。
{
"engineVersion": "5.2.13",
"compilerVersion": "5.2.13",
"template": {},
"target": {
"current": "web"
},
"modules": [
{
"name": "egret"
},
{
"name": "eui"
},
{
"name": "assetsmanager"
},
{
"name": "tween"
},
{
"name": "promise"
},
{
"name": "physics",
"path": "../physics"
},
{
"name": "game"
}
]
}ここで注意点です。
このjsonファイル内では、ダブルスラッシュでコメントを付けるとエラーになります。
できるだけ、余計なものはつけないようにしましょう。
「../」は、jsonファイルの1つ上のフォルダへ行くという意味です。
また、
{
"name": "game"
}をついでに付けておきましょう。
これは「MainContext」というコードを使用するときに使用します。
MainContextは、
egret.MainContext.instance.stage.stageHeight;のように使用し、ステージ(画面)の高さや幅を取得するときに使います。
ゲームをデバッグで実行すると、modulesフォルダ内にphysicsが生成されます。これで完了です。
p2.js 物理エンジンを使用した自然落下
Main.ts
class Main extends eui.UILayer {
public constructor() {
super();
this.once(egret.Event.ADDED_TO_STAGE, this.addToStage, this);
}
private addToStage(event:egret.Event) {
//物理エンジンを使うようのフィールドを作成
const world = new p2.World();
world.sleepMode = p2.World.BODY_SLEEPING;
world.gravity = [0, 9.8 * 50];
//物理挙動をもつコライダーの生成
const body : p2.Body = new p2.Body({mass:1, position:[200,300]});
const bodyShape = new p2.Circle({ radius: 100 });
body.addShape(bodyShape);
world.addBody(body);
//ループ処理
egret.Ticker.getInstance().register(loopMethod,this);
function loopMethod(dt:number) {
world.step(1/60, dt/1000, 10);
drawBall();
}
//図形の表示用オブジェクトのインスタンス化
const shape:egret.Shape = new egret.Shape();
this.addChild(shape);
//ボールの描画
function drawBall(){
//ステージに残っている図形を一度消す
shape.graphics.clear();
shape.graphics.beginFill(0xff0000);
shape.graphics.drawCircle(body.position[0], body.position[1], 100);
shape.graphics.endFill();
}
}
}物理現象をステージに付与
const world = new p2.World();
world.sleepMode = p2.World.BODY_SLEEPING;
world.gravity = [0, 9.8 * 50];「world.sleepMode = p2.World.BODY_SLEEPING; 」は、一定時間が経過したオブジェクトの物理エンジンをスリープ状態にし、パフォーマンスを向上させます。
「world.gravity = [0, 9.8 * 50];」でステージに重力を付与します。
ここで注意点ですが、p2.js と EgretEngineは長さの単位が異なるうえ、座標系も違います。
なので、座標を補正してあげる必要があるため、50を掛けています。
物理挙動を持つコライダーの生成
const body : p2.Body = new p2.Body({mass:1, position:[200,300]});
const bodyShape = new p2.Circle({ radius: 100 });
body.addShape(bodyShape);
world.addBody(body);コライダーは接触判定をおこなったり、壁にめり込まないように計算してくれるワイヤーフレームです。
詳しくは、こちらのコライダーの記事もご覧ください。
「const body : p2.Body = new p2.Body({mass:1, position:[200,300]});」でコライダーを生成します。
var body = new Body({
mass: 1,
position: [0, 0],
angle: 0,
velocity: [0, 0],
angularVelocity: 0
});のように、{ } の中でposition や angle 等を設定できます。
BodyのAPIについては以下の公式サイトをご覧ください。
「const bodyShape = new p2.Circle({ radius: 100 });」でコライダーを円形に切り取る準備をします。
最後に「body.addShape(bodyShape);」でコライダーを円形に切り取り、「world.addBody(body);」で画面に追加します。
ループ処理「egret.Ticker.getInstance()」
//ループ処理
egret.Ticker.getInstance().register(loopMethod,this);
function loopMethod(dt:number) {
world.step(1/60, dt/1000, 10);
drawBall();
}
ループ処理を行うには「egret.Ticker.getInstance().register( 関数 ,this);」を使用します。
「world.step(秒, 関数が最後に呼び出されてからの経過時間, 関数の呼び出しごとにとる固定ステップの最大数);」です。
このメソッドを使って円の描画をしていきます。
コライダーだけでは無色透明なので、図形の描画は必要です。
図形の描画
//図形の表示用オブジェクトのインスタンス化
const shape:egret.Shape = new egret.Shape();
this.addChild(shape);
//ボールの描画
function drawBall(){
//ステージに残っている図形を一度消す
shape.graphics.clear();
shape.graphics.beginFill(0xff0000);
shape.graphics.drawCircle(body.position[0], body.position[1], 100);
shape.graphics.endFill();
}上記コードで円の描画をおこなっております。円の描画方法は以下の記事も参照してください。
【eui.UILayer】図形の描画方法「drawCircle」「drawRect」「lineTo」
「shape.graphics.clear();」で現在ステージに描画してあるオブジェクトを消去します。
これがないと、以下のように線状になります。
参考URL
EgretEngineで超簡単なゲームを作ってみよう(2) 物理エンジン エクステンションの導入
EgretEngineで超簡単なゲームを作ってみよう(3) タップでの操作の実装





