LoginSignup
0
0

More than 5 years have passed since last update.

EgretEngineでRPGマップはどう実現するか?(4) カメラ回り

Posted at

updateCameraPosを呼び出しているのはCameraComponent .dealBgCameraメソッドです

CameraComponent.ts
class CameraComponent extends Component {
:
    public dealBgCamera(): void {
        this.background.updateCameraPos(this.playerX, this.playerY);
    }
}

CameraComponent.dealBgCameraを呼び出しているのは、同じくCameraComponentのupdateメソッドです。

CameraComponent.ts
class CameraComponent {
:
    public update(advancedTime: number): void {
        super.update(advancedTime);

        if (this.playerPosChange()) {
            this.playerX = this.entity.x;
            this.playerY = this.entity.y;

            this.dealMoveObjs();
        }

        if (this.playerCellChange()) {
            this.playerCol = this.entity.col;
            this.playerRow = this.entity.row;

            this.dealBgCamera();
        }
    }

では、CameraComponentはどこで生成されて、だれがCameraComponent.updateを呼び出しているのかを調べていきます。

結論から言うとRpgPlayerクラスの初期化時(initメソッド)のaddComponentです。

RpgPlayer.ts
class RpgPlayer extends RpgGameObject {
:
    public init(data: any): void {
:
        this.addComponent(ComponentType.Camera);

addComponentが定義されているのは親クラスのRpgGameObjectです。

下記のように、まずオブジェクトプールObjectPoolからすでに存在している場合はそのオブジェクト取得して、存在していない場合は新規作成をします。

そのオブジェクトをコンポーネントの管理クラスComponentSystemaddComponentで管理対象として追加されます。

RpgGameObject.ts
    public addComponent(componentName: string): void {
        if (this._components[componentName]) {
            return;
        }

        var component: Component = ObjectPool.pop(componentName);
        component.type = componentName;
        component.entity = this;
        component.start();

        ComponentSystem.addComponent(component);

        this._components[componentName] = component;
    }

ComponentSystem.addComponentでは、コンポネント種別毎に生成されたコンポーネントが管理されます。

ComponentSystem.ts
    public static addComponent(component: Component): void {
        if (!this._Components[component.type]) {
            this._Components[component.type] = [];
        }
        this._Components[component.type].push(component);
    }

そしてフレーム毎に呼び出されるComponentSystem.onEnterFrameで各コンポーネントのupdateメソッドが呼び出されます。

ComponentSystem.ts
    private static onEnterFrame(advancedTime: number): void {
:
        this.dealComponents(this._Components[ComponentType.Camera], advancedTime);
:
    }

    private static dealComponents(arr: Component[], advancedTime: number): void {
        if (!arr) {
            return;
        }
        arr.forEach(function (component: Component) {
            if (!component.isRuning) {
                return;
            }

            component.dealTime += advancedTime;
            if (component.dealTime >= component.dealInterval) {
                component.dealTime = 0;
                component.update(advancedTime);
            }
        })
    }

つまり
1. 各フレーム毎に、ComponentSystem.onEnterFrameが呼ばれ
2. すべてのコンポーネントのupdateが呼びされた結果CameraComponent.updateが呼ばれ
3. CameraComponent.dealMoveObjsでカメラ位置に応じてすべてのオブジェクトの位置がされて
4. CameraComponent.dealBgObjsでカメラの可視範囲に応じてマップタイルが破棄されたり生成されたりします

CameraComponent
    public dealMoveObjs(): void {
        var left: number = Math.max(this.playerX - App.StageUtils.getWidth() * 0.5, 0);
        var top: number = Math.max(this.playerY - App.StageUtils.getHeight() * 0.5, 0);

        left = Math.min(this.background.mapWidth - App.StageUtils.getWidth(), left);
        top = Math.min(this.background.mapHeight - App.StageUtils.getHeight(), top);

        this.moveObjs.forEach(function (obj: egret.DisplayObject) {
            obj.x = -left;
            obj.y = -top;
        })
    }

このようにBackgroundは、moveObjsでもありbackgroundでもあります。

CameraComponent
    public start(): void {
:
        this.moveObjs.push(this.entity.gameView.getBackground());

        this.background = this.entity.gameView.getBackground();
    }
0
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
0
0