这边卡比要介绍一个名词,
Software Architecture 软件架构。
软件架构 旨在如何更好的处理各个程序码段落之间的沟通,
虽然并不会让你的程序码增加什麽新的功能,但能让撰写程序码变得更容易判读,
但如果做完之後反而变累赘或是更难懂的时候,重新思考一下,
Don't overengineer your code。
如果要论游戏程序设计最关键的部分,那一定是 GameLoop。
Loop 的概念在现代开发时常出现,像是 REPL (Read-Eval-Print Loop)、 Event Loop ...etc.
同样的概念在游戏程序中,一样存在一个 Loop,
并会以下面的方式,重复的执行动作,直到使用者主动关闭程序。
示意用
while (true) {
processesInput();
update();
render();
}
根据平台与工具的不同,
实作方式可能会有差异,但主要的思考方向不变,
像是在 Web 端, JavaScript 是无法直接对底层直接做操作的,
必须透过 requestAnimationFrame 等 API 来实现 GameLoop
。
实际上,卡比在前一章节就已经实作 GameLoop 了,
不过接下来,卡比会做一些调整。
随着程序的功能越来越复杂,如果将所有的逻辑,都写在一个函式的话,
最後程序码会变的难以理解跟维护,
所以卡比会开始整理这些逻辑跟功能到对应的物件进行封装。
但是,不同的物件会有不同的实作内容,我们需要定义一个共同的 interface,
GameLoop 不需要了解是什麽物件,但是知道实作 interface 一定会有其定义的 method,
他只需要去执行那个 method 即可。
卡比接下来示范如何用 interface 定义 update 以及 render,来规范架构。
首先建立一个新的档案 src/types.ts
,
-- src/types.ts
import { Application } from "pixi.js";
export interface GameObject {
update(delta: number): void;
render(stage: Application): void;
}
然後,在 src/characters/Crab.ts
,
卡比将实作 GameObject
介面,并将他回传出去。
-- src/characters/Crab.ts
import { Graphics } from "pixi.js";
import { GameObject } from "../types";
const image = [
[0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1],
[0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0],
];
const image2 = [
[0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
[1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1],
[1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0],
];
export default function Crab(): GameObject {
let current = 0;
const images = [image, image2];
let timePass = 0;
return {
update(delta) {
timePass += delta;
if (timePass > 1000) {
current += 1;
timePass = 0;
}
},
render(app) {
const graphics = new Graphics();
const image = images[current % images.length];
for (let y = 0; y < image.length; y++) {
for (let x = 0; x < image[y].length; x++) {
if (image[y][x] === 0) continue;
graphics.beginFill(0xffffff);
graphics.drawRect(x, y, 1, 1);
graphics.endFill();
}
}
app.stage.addChild(graphics);
},
};
}
最後在 src/main.ts
。
-- src/main.ts
const app = new Application({
width: 20,
height: 20,
resolution: 10,
});
document.querySelector("#app")?.append(app.view);
const instance = Crab();
app.ticker.add(() => {
app.stage.removeChildren();
instance.update(app.ticker.deltaMS);
instance.render(app);
});
接着确认有没有出现错误,或是任何非预期行为,
如果没有那重构就成功了。
请帮 Crab
,LaserCannon
,Octopus
,Squid
也进行重构。
请在场上同时显示 Crab
,LaserCannon
,Octopus
,Squid
。
>>: JAVA - Windows 10 安装 Maven
一般在写 windows form 程序时 如果不是大型开发 老板只要求 东西能动 项目立刻好 我们...
今天跟大家分享关机与服务中断的警报,如果有仔细观察 Problem: /etc/passwd has...
我把它分成使用基本款 (可安装 Agent)、通用款 (支援监控类通讯协定)、简易款 (无法安装 A...
Keyword: KMM Gradle,Kotlinx serialization 到Day9使用K...
学会游泳会好的方法就是掉进水里 今天就直接来用react 取api 我直接参考React官网的教学:...