LoginSignup
2
0

More than 5 years have passed since last update.

【Egret無料ご相談室】 EgretのDisplayObjectをちょいUnity Likeにする

Posted at

話の発端

image.png

元のご相談簡単なソースコードをいただきました


https://github.com/motoyasu-yamada/egret-unity-demo

Before

下記のようにすべてのオブジェクトに egret.startTickを設定していました

class CreateImage extends  egret.DisplayObjectContainer {
:
        public constructor() {
        super();
        this.once(egret.Event.ADDED_TO_STAGE, this.generateEgretImage, this);
    }

   :
    public generateEgretImage(event:egret.Event): void {

        // 画像の生成
        this.egretImage = this.createBitmapByName("egret_icon_png");
        this.egretMoveFlag = true;

        //Enable touchEvent
        this.egretImage.touchEnabled =true;
        //this.egretImage.pixelHitTest = true;
        this.addChild(this.egretImage);

        this.egretImage.x = 100;
        this.egretImage.y = 100 + Math.floor( Math.random() * 300 );

        //画面にタッチした瞬間にtouchMethodを実行
        this.egretImage.addEventListener( egret.TouchEvent.TOUCH_BEGIN, this.egretTouch, this );

        egret.startTick(this.moveEgret, this);
    }
:
}

After

MonoBehaviourという共通なクラスを作ってあげて

export class MonoBehaviour<T extends egret.DisplayObject> 
{ 
    private started : boolean = false;
    protected $egretDisplayObject : T;

    isStarted(): boolean {
        return this.started;
    }

    setStarted() : void {
        if(this.started !== false) {
            throw new Error("MonoBehaviour has been started already");
        }
        this.started = true;
    }

    egretDisplayObject() : T {
        return this.$egretDisplayObject;
    }

    async Start() : Promise<void> {};

    Update() : void {}
}

多数のオブジェクト(MonoBehaviourクラスを継承した)を管理するSceneクラスに引き渡してSceneクラスで一括管理します。

Main.ts
    private createAndStart() {
        const scene = new Scene(this);
        scene.add(new MyImageObject());

フレーム呼び出しは以下の一回だけ設定

Main.ts
    private createAndStart() {
:
        egret.startTick(() => { scene.doFrame(); return true; }, this);
    }

SceneクラスでMonobehaviourクラスの初期化(Start呼び出し)と、フレーム毎の更新処理(Update呼び出し)を行います。

Scene.ts
import { MonoBehaviour } from "./MonoBehaviour";

export class Scene {
    private egretDisplayObjectContainer : egret.DisplayObjectContainer;
    private monoBehaviours: MonoBehaviour<egret.DisplayObject>[] = [];

    constructor(egretDisplayObjectContainer: egret.DisplayObjectContainer) {
        this.egretDisplayObjectContainer = egretDisplayObjectContainer;
    }

    public remove(o : MonoBehaviour<egret.DisplayObject>) {
        this.egretDisplayObjectContainer.removeChild(o.egretDisplayObject());
        this.monoBehaviours = this.monoBehaviours.filter (e => e !== o);
    }

    public add(o: MonoBehaviour<egret.DisplayObject>) {
        this.egretDisplayObjectContainer.addChild(o.egretDisplayObject());
        this.monoBehaviours.push(o);
    }

    public doFrame() {
        const toBeStarted = this.monoBehaviours.filter(e => !e.isStarted());
        Promise.all(toBeStarted.map(e => e.Start()));
        toBeStarted.forEach(e => e.setStarted());

        this.monoBehaviours.forEach(e => e.Update());
    }
}

おまけ

物理エンジンp2とゲームエンジンの表示エンジンをまとめて管理するための上記とは別な例はこちらです

GameObjectGameWorldPhysicsObjectクラスをご自由にお使いください。

こんな風に使います

GameMain.ts
const BASKET_SIZE_METER = 0.15;
const BALL_SIZE_METER = 0.6;
const FPS = 60;

class GameMain 
{
    public static destroy() 
    {
        GameWorld.destroy();
    }

    public static start(stage:egret.Stage, onGameOver:()=>void) 
    {
        const ballPixel = egret.MainContext.instance.stage.stageWidth / 10;
        GameWorld.init(ballPixel / BALL_SIZE_METER, stage);

        new Sky();

        new Ground();
        new TimeGauge(30);
        new ScoreUi();
        const ball = new Ball();

        stage.addEventListener(egret.TouchEvent.TOUCH_BEGIN, (e: egret.TouchEvent) => ball.up(), this);

        const basketManager = new BasketManager();

        GameWorld.on("gameover",() => {
            SoundManager.playGameOver();
            GameWorld.pause();
            onGameOver();
        });

        GameWorld.start();
    }

}
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0