文章目录
一、项目来源:uniquemo
已果断star
二、学习笔记
1、在html中同时引入多个js文件顺序问题
由于html为由上至下顺序执行,若parent.js引用了child.js,需将child.js先引入html文件中,以便parent.js使用。
通常child.js为构造函数,parent.js为主执行函数。
例如:
<script src="./Snake.js"></script>
<script src="./index.js"></script>
其中index.js中使用了Snake构造函数。
若将二者调换顺序,不会报错,但主函数将不会执行。
2、检测键盘点击事件:key()
idea:键盘呈现脚本——实时展示被按下按键
3、简化名称表达:replace()
W3school-JavaScript replace()方法
4、计时器:setInterval()
W3shool-HTML DOM setInterval() 方法
用作周期性调用某一段代码
可令
let timer = null
timer = setInterval( () => {
console.log("hello,World!")
}, 1000)
停止
clearInterval(timer)
三、新增功能
1、触壁结束
(1)构造函数 Snake.js
- 判断触壁
Snake.prototype.touchWall = function() {
const { width, height } = this.canvasOptions.canvas
if( this.x < 0 || this.y < 0 || this.x > width || this.y > height ){
this.die()
return true
}
return false
}
- 死亡变色
Snake.prototype.die = function() {
ctx.fillStyle = '#ffaa33'
for(let i = 0; i< this.tails.length; i++){
const {x, y} = this.tails[i]
ctx.fillRect(x, y, this.size, this.size)
}
}
遍历重新绘制贪吃蛇,改变颜色
(2)主函数 index.js
- start()中添加结束判断条件
function start() {
timer = setInterval(() => {
...
if(snake.touchWall()){
gameOver()
}
}, 150 )
}
- 结束执行函数
function gameOver(){
clearInterval(timer)
ctx.font = 3 * size + "px Arial"
ctx.fillStyle = '#fff'
ctx.textAlign = 'center'
ctx.textBaseLine = 'middle'
ctx.fillText( "GAME OVER !!", canvas.width / 2, canvas.height / 2 )
}
画布绘制‘GAME OVER’文字
四、优化
1、禁止回退&向前加速
- 禁止贪吃蛇向反方向爬行,保持头在前尾在后
- 同方向再次按键则向前加速一倍
- 在Snake中添加accelerate属性,定义画布刷新周期;
在原项目中,画布每刷新一次,贪吃蛇向前运动一格,刷新周期变短,速度变快。
this.accelerate = 150
(1)更新改变方向函数
- 判断当键盘按键与当前运动方向相反时,提示不能后退。
- 判断当键盘按键与当前运动方向相同时,进行加速。
- 在加速状态下改变有效方向,速度更新为最低档。
Snake.prototype.changeDirection = function(direction) {
switch(direction) {
case 'Up':
if(this.xSpeed == 0 && this.ySpeed > 0 ) {
console.log ( 'You can not go back !' )
}
else if(this.xSpeed == 0 && this.ySpeed < 0) {
this.speedUp()
}
else {
this.accelerate = 150
this.xSpeed = 0
this.ySpeed = -size
}
break
case 'Down':
if(this.xSpeed == 0 && this.ySpeed < 0 ){
console.log ( 'You can not go back !' )
}
else if(this.xSpeed == 0 && this.ySpeed > 0) {
this.speedUp()
}
else {
this.accelerate = 150
this.xSpeed = 0
this.ySpeed = size
}
break
case 'Left':
if(this.xSpeed > 0 && this.ySpeed == 0 ){
console.log ( 'You can not go back !' )
}
else if(this.xSpeed < 0 && this.ySpeed == 0) {
this.speedUp()
}
else {
this.accelerate = 150
this.xSpeed = -size
this.ySpeed = 0
}
break
case 'Right':
if(this.xSpeed < 0 && this.ySpeed == 0 ){
console.log ( 'You can not go back !' )
}
else if(this.xSpeed > 0 && this.ySpeed == 0) {
this.speedUp()
}
else {
this.accelerate = 150
this.xSpeed = size
this.ySpeed = 0
}
break
}
console.log(this.accelerate)
}
(2)加速函数
- 加速次数提示
- 设置加速上限,防止速度过快。
Snake.prototype.speedUp = function() {
if(this.accelerate == 50) {
console.log('SPEED LIMIT !!')
}
else {
this.accelerate = this.accelerate - 50
console.log (`Speed Up: ${(150-this.accelerate)/50} times`)
}
}
主程序中
let lastSpeed = snake.accelerate
(3)主程序中实时检测速度变化
- 设置frequency参数,用于接收刷新周期,达到改变速度的目的。
- setInterval()方法中的刷新周期不能在函数进行时改变,只能先停止执行(clearInterval()),更新周期后再开始刷新。
刷新时通过if( lastSpeed != snake.accelerate )
判断速度是否发生改变,若发生改变,则停止当前timer,更新速度。
function motion(frequency) {
timer = setInterval(() => {
ctx.clearRect(0, 0, canvas.width, canvas.height)
target.draw()
snake.update()
snake.draw()
if(snake.eatTarget(target)){
target.genRandomLocation()
}
snake.checkCollision()
document.getElementById('score').innerHTML = snake.targetNum
if(snake.touchWall()){
gameOver()
}
if( lastSpeed != snake.accelerate ){
clearInterval(timer)
start()
}
}, frequency)
}
- 将timer与start()分离
- 停止刷新后更新速度,对timer计时器传入新的刷新周期,并重新开始执行。
function start() {
console.log(`current speed: ${snake.accelerate}`)
lastSpeed = snake.accelerate
motion(lastSpeed)
}
2、重新开始
(1)参数清零 Snake.js
Snake.prototype.init= function() {
this.x = 0
this.y = 0
this.xSpped = size * 1
this.ySpeed = 0
this.targetNum = 0
this.tails = []
}
(2)主函数初始化
- 加入snake.init函数
function init() {
target.genRandomLocation()
snake.init()
target.draw()
snake.draw()
}
(3)清空画布、加入初始化函数init()
startBtn.addEventListener('click', () => {
ctx.clearRect(0, 0, canvas.width, canvas.height)
init()
start()
})
写在最后
本人初入前端,许多代码写的比较冗余或含有隐藏bug或造成性能损耗,希望大家评论指出;如有讲述不明之处,也可评论询问,我会尽自己最大所能回复大家!