玩家控制与移动实现:霓虹三角形的飞行逻辑
> 一个三角形,怎么在 1280×720 的画布上"飞"起来?
## 当前状态:占位符
在 NEON RUNNER 2077 的当前版本里,玩家控制还没有真正实现。`GameScene` 里的玩家精灵是静态的——它出现在画布中心,呼吸动画让它"看起来在动",但实际上它不会移动。
```ts
// GameScene.ts(当前状态)
this.player = this.add.sprite(width / 2, height / 2, 'player')
.setDepth(10)
.setAlpha(0.9);
```
但这不影响我们讨论**设计意图**——从代码结构来看,玩家控制应该怎么实现。
## 设计方向:两种移动模式
在霓虹射击游戏里,玩家移动通常有两种模式:
### 模式一:光标跟随(Mouse Follow)
玩家精灵跟随鼠标位置移动。这种模式在《几何冲刺》(Geometry Dash)类游戏里很常见:
```ts
// 伪代码:光标跟随
this.input.on('pointermove', (pointer) => {
this.player.x = pointer.x;
this.player.y = pointer.y;
});
```
优点:直观,玩家不需要记按键。
缺点:不适合高速战斗——鼠标移动太快时,玩家会"飞出屏幕"。
### 模式二:键盘控制(WASD / 方向键)
玩家用 WASD 或方向键移动。这种模式在《太空侵略者》(Space Invaders)类游戏里很常见:
```ts
// 伪代码:键盘控制
this.cursors = this.input.keyboard.createCursorKeys();
this.wasd = {
up: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W),
down: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S),
left: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A),
right: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D),
};
```
在 `update()` 里每帧更新位置:
```ts
// 伪代码:每帧更新
update(): void {
const speed = 5;
if (this.cursors.left.isDown || this.wasd.left.isDown) {
this.player.x -= speed;
}
if (this.cursors.right.isDown || this.wasd.right.isDown) {
this.player.x += speed;
}
if (this.cursors.up.isDown || this.wasd.up.isDown) {
this.player.y -= speed;
}
if (this.cursors.down.isDown || this.wasd.down.isDown) {
this.player.y += speed;
}
// 边界限制
this.player.x = Phaser.Math.Clamp(this.player.x, 40, 1240);
this.player.y = Phaser.Math.Clamp(this.player.y, 90, 590);
}
```
## 边界限制:为什么重要
`Phaser.Math.Clamp(this.player.x, 40, 1240)` 确保玩家不会飞出 arena 边界。40 和 1240 是 arena 边框的左右边界(1280 - 40 - 40 = 1200 的可移动宽度)。
如果不做边界限制,玩家会飞出屏幕,然后——在 Phaser 的 `arcade` 物理模式下——玩家会"消失"(因为 `worldBounds` 默认不检查)。
## 移动速度:5px/frame 是怎么来的
5px/frame 在 60fps 下是 300px/s。在 1280×720 的画布上,从左到右需要 4.27 秒。这个速度在"霓虹射击"里是**中等偏慢**的——如果玩家觉得"太慢了",可以把 `speed` 改成 8 或 10。
## 设计意图:从 MenuScene 的输入系统推断
`MenuScene` 里已经实现了完整的键盘输入系统(WASD + 方向键 + Enter + Space),所以 `GameScene` 的玩家控制**几乎肯定**会用键盘。
`MenuScene` 的输入处理:
```ts
keyboard.on('keydown-UP', () => this.moveSelection(-1));
keyboard.on('keydown-DOWN', () => this.moveSelection(1));
keyboard.on('keydown-W', () => this.moveSelection(-1));
keyboard.on('keydown-S', () => this.moveSelection(1));
```
这个模式可以直接复用到 `GameScene`——只是 `moveSelection()` 换成 `movePlayer()`。
## 下一章预告
玩家控制讲完了,但 NEON RUNNER 2077 的战斗循环里还有一个关键系统——**敌人波次**。敌人是怎么生成的?波次是怎么推进的?下一章我会拆解这个设计。
> 玩家控制的核心原则:**输入要即时,移动要平滑**。玩家按下的键必须在同一帧生效,不能有"延迟感"。
- 点赞
- 收藏
- 关注作者
评论(0)