[Day6] Vite 出小蜜蜂~ Scene 场景!

Day6

Scenes

Web 的领域里,一个网站会有页面,像是 Main Page, Login Page, Dashboard ... etc。
Game 里面也有类似的概念,我们称之为 Scene 场景。

每个 Scene 会有不同的目的,
根据目的的不同,Scene 需要的实作方式也不一样,
但是我们一样可以设计出一个共同的介面,
Scene 可以与 GameLoop 这两个 Pattern 进行串接。

-- src/types.ts

export interface Scene<T> extends GameObject {
  render(stage: T): void;
}

Game Scene

接下来我们要实作 Game Scene,用於主游戏的场景。
建立一个新的资料夹 scenes 并建立 Game.ts

-- src/scenes/Game.ts

import { Container, Rectangle } from "pixi.js";
import LaserCannon from "../characters/LaserCannon";
import Squid from "../characters/Squid";
import { GameObject, Scene } from "../types";

export default function Game(): Scene<Container> {
  const instances: GameObject[] = [LaserCannon(), Squid()];

  return {
    render(stage) {},
  };
}

-- src/main.ts

+ import Game from "./scenes/Game";

const app = new Application({
  width: 80,
  height: 80,
  resolution: 5,
});

document.querySelector("#app")?.append(app.view);

- const instance = LaserCannon();
+ const scene = Game();

app.ticker.add(() => {
  app.stage.removeChildren();

- instance.handleInput?.(getKeyPressed());
- instance.update?.(app.ticker.deltaMS);

- instance.render(app.stage);
+ scene.render(app.stage);
});

接着将 updaterender 的相关逻辑移到 scene

为了知道哪些物件用有 render 的元件跟 handleInput 元件,
跟上一个章节一样,我们要新增判断函式。

-- src/types.ts

export function canControl<T extends GameObject>(
  instance: T
): instance is T & Control {
  return "handleInput" in instance;
}

export function canRender<T extends GameObject>(
  instance: T
): instance is T & Renderer {
  return "renderer" in instance;
}

-- src/scenes/Game.ts

import { canControl, canRender, GameObject, Scene } from "../types";

export default function Game(): Scene<Container> {
  const instances: GameObject[] = [LaserCannon(), Squid()];

  return {
    update(delta) {
      instances.forEach((instance) => {
        if (canControl(instance)) {
          instance.handleInput(getKeyPressed());
        }

        instance.update?.(delta);
      });
    },

    render(stage) {
      instances
        .filter(canRender)
        .forEach((instance) => render(stage, instance));
    },
  };
}

接着在 GameLoop 执行 scene.update
我们就成功接上 GameLoopScene 这两个 Pattern 了。

-- src/main.ts

import Game from "./scenes/Game";

const app = new Application({
  width: 80,
  height: 80,
  resolution: 5,
});

document.querySelector("#app")?.append(app.view);

const scene = Game();

app.ticker.add(() => {
  app.stage.removeChildren();

+ scene.update?.(app.ticker.deltaMS);

  scene.render(app.stage);
});

关於兔兔们:


<<:  Day02 线上金流再做什麽?

>>:  [DAY 03] FormApp

Day02 工欲善其事必先利其器

VS Code Extension外挂套件 在建立React应用程序之前,建议可先安装VS Code...

Day21 Open-Match 端点暴露

今天会说明一下,实务上如何将 Open-Match svc endpoints,从 kubernet...

30-18 之 DataSource Layer- DataMapper

这一篇文章我们将要谈谈常常听到的 DataMapper 这个东西,应该是有不少人在一些 ORM 的 ...

[Day 19] 突如其来的需求变更!来聊函数式编程

我们好不容易写了 userAddTag() 和 updateUsersTags() 的逻辑,突然又出...

D25. 学习基础C、C++语言

D25. 输入输出 在C语言里,如果要输入是scanf("%d",&a)...