接下来,要帮 Squid
也装上 Laser
,
敌人的 Laser
跟我们的外观是不一样的,
但是卡比希望可以利用原本已经写好的 Laser
函式,
减少重复的程序码。
首先,新建一个资料夹 src/army
并建立 src/army/index.ts
,
将 Laser
搬到 src/army/index.ts
,
并将其重构成 Base
,用来当我们的基础。
type Army = GameObject & Transform & Renderer & Collision;
type BaseProps = {
src: number[][];
position: Vector;
update: (army: Army) => void;
};
function Base({ src, position, update }: BaseProps): Army {
return {
renderer: {
type: "graphics",
src,
},
position,
update() {
update(this);
},
collider: {
size: { x: src[0].length, y: src.length },
},
collision: {
start(other) {
other.destroy = true;
this.destroy = true;
},
},
};
}
接着,建立 Laser
。
type LaserProps = Omit<BaseProps, "src">;
export function Laser({ position, update }: LaserProps) {
return Base({ src: [[1], [1], [1], [1]], position, update });
}
并透过 LaserCannon
来提供我们 position
跟 update
。
export default function LaserCannon(screen: {
width: number;
height: number;
}): TLaserCannon {
let timePass = 0;
return {
renderer: {
type: "graphics",
src: [
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
],
},
position: { x: 10, y: screen.height - 20 },
canShoot: false,
shoot() {
const { x, y } = this.position;
+ return Laser({
+ position: { x: x + 5, y: y - 4 },
+ update(it) {
+ it.position.y -= 1;
+ },
+ });
},
handleInput(this: TLaserCannon, pressed) {
if (pressed.includes(Key.Space) && timePass > 500) {
this.canShoot = true;
timePass = 0;
}
const width = screen.width - this.renderer.src[0].length;
if (pressed.includes(Key.Left)) {
this.position.x = clamp(0, width, this.position.x - 1);
return;
}
if (pressed.includes(Key.Right)) {
this.position.x = clamp(0, width, this.position.x + 1);
return;
}
},
update(delta) {
timePass += delta;
},
};
}
接着来建立 EnemyLaser
,
因为我们将一些逻辑共用了,所以很快就可以做出来。
export function EnemyLaser({ position, update }: LaserProps) {
return Base({
src: [
[0, 1, 0],
[1, 0, 0],
[0, 1, 0],
[0, 0, 1],
[0, 1, 0],
[1, 0, 0],
[0, 1, 0],
],
position,
update,
});
}
调整一下 Squid
,使其每一秒射击一次,便大功告成了。
type Enemy = GameObject & Transform & Renderer & Collision & Shooter;
export default function Squid(): Enemy {
const images = [image1, image2];
let current = 0;
let timePass = 0;
return {
position: { x: 0, y: 0 },
update(delta) {
timePass += delta;
if (timePass > 1000) {
current += 1;
timePass = 0;
this.renderer.src = images[current % images.length];
this.canShoot = true;
}
},
canShoot: false,
shoot() {
const { x, y } = this.position;
const [w, h] = [image1[0].length, image1.length];
return EnemyLaser({
position: { x: x + w / 2, y: y + h + 1 },
update(it) {
it.position.y += 1;
},
});
},
renderer: {
type: "graphics",
src: images[current % images.length],
},
collider: {
size: { x: image1[0].length, y: image1.length },
},
};
}
<<: Day12 - 敏捷式接案实践( 四 ) - 收入管理
最近几天在网站上看了有管git的资料, 发现了 "连猴子都能懂的Git指南" 就...
为什麽我们需要 SWR ? 先前我们已经了解了 CSR、SSR 与 SSG 的优劣,SSR 与 SS...
什麽是RWD? 响应式网页设计(Responsive Web Design),可以让不同的设备都可以...
前言 大家好,我是 Enola~ 正在坎坷自学 iOS 开发中, 参加这次 30 天的铁人赛是为了记...
居高临下远眺百塔之城布拉格的高堡区,卡夫卡的衣冠冢就藏身其中 就让每天一点的卡夫卡陪伴我们熬过这3...