开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情
上一章中,我们留下了课后作业-如何让贪吃蛇在运动过程中吃到奖励并且身体变长。
处理奖励点
那么,我们继续敲代码,在lib.rs文件添加下面几行:
pub fn update_snake(&mut self, input: Option<Direction>) -> GameState {
....
if state == GameState::Run {
....
//蛇头接触奖励点
if self.reward_cell == self.snake_spawn() {
//生成新奖励点
self.reward_cell = World::new_reward_cell(&self.snake.body);
//蛇身变长
self.snake.body.push(SnakeCell(self.snake.body[1].0));
}
}
state
}
仅仅3行代码,其实逻辑也很简单。当蛇头编号与奖励点相等时(即蛇头吞噬奖励点),就会重新生成新的奖励点,并且蛇身长度增加一格。
将项目重新打包,打开index.html文件。运行游戏,这时候贪吃蛇能够成功吃掉奖励点,并且长度随之增加了。
其他小功能
现在,游戏的基本功能已经完成了。但是我们还可以在此基础上进行一点点优化,比如新增游戏难度:按照正常逻辑,游戏难度应该是按照蛇身长度逐步增加的。也就是根据蛇身长度进行计算得到蛇的运行速度。
那么,接着在index.ts文件中,对init函数内容进行调整:
init().then(wasm => {
....
let fps = 2
...
const run = () => {
let len = world.snake_length()
fps = Math.floor(len / 10) + 1
gameRunner = setTimeout(() => {
...
}, 1000 / fps)
}
....
})
游戏难度的计算也非常简单,根据蛇身长度计算,每增加10格长度,就把运行速度提升一些。其实就是把定时器的时间间隔再缩短一点,这样蛇头运行速度会逐渐加快。
当然,游戏失败之后,我们把动画清除了。现在还缺少重置游戏的功能。
继续在init函数内进行修改:
init().then(wasm => {
....
gameRunner = setTimeout(() => {
context.clearRect(0, 0, canvas.width, canvas.height)
let state = world.update_snake()
if (state === GameState.Run) {
initMap(wasm, world, context, worldWidth, worldHeight, cell_size)
gameCanvas = window.requestAnimationFrame(run)
} else if (state === GameState.Failed) {
clearTimeout(gameRunner)
window.cancelAnimationFrame(gameCanvas)
alert('游戏失败')
const restPoint = randomPointer(worldWidth * worldWidth)
world = World.new(worldWidth, worldHeight, restPoint)
context.clearRect(0, 0, canvas.width, canvas.height)
initMap(wasm, world, context, worldWidth, worldHeight, cell_size)
snake_move(world)
}
}, 1000 / fps)
....
})
在游戏失败后,对游戏进行重置。同时对canvas进行重新渲染。
重新打包项目,运行游戏,游戏失败后会重置游戏。这样我们的贪吃蛇游戏,就基本开发完成了!
虽然游戏功能已经开发完成,但是游戏界面只是用canvas进行简单的渲染,实在是太简陋了😅。