Edited at

EgretEngineで超簡単なゲームを作ってみよう(3) タップでの操作の実装


連載記事「EgretEngineで超簡単なゲームを作ってみよう」

(1) プロジェクト作成&ビルド

(2) 物理エンジン エクステンションの導入

(3) タップでの操作の実装

(4) 障害物の実装と各種カプセル化

(5) 書き出し編


こちらの記事EgretEngineで超簡単なゲームを作ってみよう(2)の続き


動作の説明

今回はこんな感じでボールを表示します。

image.png


  1. このボールは自然落下する

  2. タップするとボールに少し上向きのインパクト(力×時間)がかかる

  3. (見えませんが)地面にあたるとバウンドして止まる


完成コード

ひとまずEgretおよびPhysicsエクステンション(p2)の練習ですので、Main.tsのcreateGameSceneメソッドにすべてのコードを書いてしまいます。


Main.ts

    private createGameScene() {

const stageHeight = egret.MainContext.instance.stage.stageHeight;
const stageWidth = egret.MainContext.instance.stage.stageWidth;
const ballRadiusPixel = stageWidth / 10 / 2;
const ballRadiusMeter = 0.6;
const meterPerPixel = ballRadiusMeter / ballRadiusPixel;
const worldWidthMeter = meterPerPixel * stageWidth;
const worldHeightMeter = meterPerPixel * stageHeight;

const sprite: egret.Sprite = new egret.Sprite();
this.addChild(sprite);

const world = new p2.World();
world.sleepMode = p2.World.BODY_SLEEPING;
world.gravity = [0, 9.8];

const groundShape: p2.Plane = new p2.Plane();
const groundBody: p2.Body = new p2.Body();
groundBody.position[1] = worldHeightMeter - 1;
groundBody.angle = Math.PI;
groundBody.addShape(groundShape);
world.addBody(groundBody);

const ball: p2.Body = new p2.Body({ mass: 1, position: [worldWidthMeter/2, ballRadiusMeter] });
let ballShape = new p2.Circle({ radius: ballRadiusMeter });
ball.addShape(ballShape);
world.addBody(ball);

egret.Ticker.getInstance().register(loop,this);
this.stage.addEventListener(egret.TouchEvent.TOUCH_BEGIN,tapUpBall, this);

function loop(dt:number) {
world.step(1/60,dt / 1000,10);
drawBall();
}

function tapUpBall(e: egret.TouchEvent) {
ball.applyImpulseLocal([0,-9.8],[0,0]);
}

function drawBall() {
sprite.graphics.clear();

const g: egret.Graphics = sprite.graphics;
const px = ball.position[0] / meterPerPixel;
const py = ball.position[1] / meterPerPixel;
g.beginFill(0xfff000, 0.5);
g.drawCircle(px, py, ballRadiusPixel);
g.endFill();
}
}



画面描画

Physics(p2)は物理演算は行いますが画面描画は行いません。

そのためにp2が演算してはじきだした位置情報をもとに自前で画面描画を行う必要があります

        function drawBall() {

sprite.graphics.clear();
const g: egret.Graphics = sprite.graphics;
const px = ball.position[0] / meterPerPixel;
const py = ball.position[1] / meterPerPixel;
g.lineStyle(1, 0xfff000);
g.beginFill(0xfff000, 0.5);
g.drawCircle(px, py, ballRadiusPixel);
g.endFill();
}


Physicsの単位

MKS単位系です


単位

長さの単位
メートル(metre; m)

質量の単位
キログラム(kilogram; kg)

時間の単位
秒(second; s)

そのために、画面の単位と物理演算の単位を変換するための比率meterPerPixelを計算する必要があります

ボールは画面の1/10のサイズで描画したい。ただしバスケットボールの論理物理サイズは60cmを想定します。

        const stageWidth = egret.MainContext.instance.stage.stageWidth;

const ballRadiusPixel = stageWidth / 10 / 2;
const ballRadiusMeter = 0.6;
const meterPerPixel = ballRadiusMeter / ballRadiusPixel;