iT邦幫忙

2021 iThome 鐵人賽

DAY 1
0

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);
});

關於兔兔們:


上一篇
[Day5] Vite 出小蜜蜂~ Component 元件!
下一篇
[Day7] Vite 出小蜜蜂~Shoot 射擊系統!
系列文
Vite 出小蜜蜂~和卡比一起玩網頁遊戲開發!19
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言