exportdefaultclassSnake{// 蛇头head:HTMLElement
// 蛇身体,包括蛇头bodies:HTMLCollection
// 蛇的父容器element:HTMLElement
constructor(){this.element = document.getElementById("snake")!this.bodies =this.element.children
this.head =this.element.firstElementChild as HTMLElement
}// 蛇头的坐标getX(){returnthis.head.offsetLeft
}getY(){returnthis.head.offsetTop
}// 设置蛇头的坐标setX(value){// 当蛇的第二节与蛇头的x轴坐标重合,说明发生了水平方向的掉头if(this.bodies[1]&&(this.bodies[1]as HTMLElement).offsetLeft === value){if(value >this.X){
value =this.X-10}else{
value =this.X+10}}this.moveBody()// 设置蛇头坐标this.head.style.left = value +'px'}setY(value){// 当蛇的第二节与蛇头的Y轴坐标重合,发生了垂直方向的掉头if(this.bodies[1]&&(this.bodies[1]as HTMLElement).offsetTop === value){if(value >this.Y){
value =this.Y-10}else{
value =this.Y+10}}this.moveBody()this.head.style.top = value +'px'}// 蛇增加身体addBody(){this.element.insertAdjacentHTML("beforeend","<div></div>")}// 蛇的移动,从最后一个元素开始,修改坐标为前一个元素moveBody(){for(let i =this.bodies.length -1; i >0; i--){let x =(this.bodies[i-1]as HTMLElement ).offsetLeft;let y =(this.bodies[i-1]as HTMLElement ).offsetTop;(this.bodies[i]as HTMLElement).style.left = x +'px';(this.bodies[i]as HTMLElement).style.top = y +'px';}}checkHandBody():boolean{for(let i =1; i <this.bodies.length; i++){if(this.X===(this.bodies[i]as HTMLElement).offsetLeft &&this.Y===(this.bodies[i]as HTMLElement).offsetTop){returnfalse}}returntrue}}
/modules/ScorePanel.ts
exportdefaultclassScorePanel{
score =0
level =1scoreElement: HTMLElement
levelElement: HTMLElement
maxLevel: number
upScore: number
constructor(maxLevel =10,upScore =10){this.scoreElement = document.getElementById('score')!this.levelElement = document.getElementById('level')!this.maxLevel = maxLevel // 最大等级this.upScore = upScore // 多少分升一级}// 增加积分,每吃一个食物增加1分,在此处设置等级的增加addScore(){this.score ++this.scoreElement.innerText =this.score.toString()if(this.score %this.upScore ===0){this.addLevel()}}// 增加等级addLevel(){if(++this.level <=this.maxLevel){this.levelElement.innerText =this.level.toString()}}}// const a = new ScorePanel()// for (let i = 0; i < 200; i++) {// a.addScore()// }
/modules/Gamecontrol.ts
import Snake from"./snake";import Food from"./Food";import ScorePanel from"./ScorePanel";exportdefaultclassGameControl{snake: Snake
food: Food
scorePanel: ScorePanel
dircter =''// 保存按键的值constructor(){this.snake =newSnake()this.food =newFood()this.scorePanel =newScorePanel()this.init()}// 初始化操作,监听按键事件init(){// 第二个参数如果不写bind(this),那调用的函数中的this就是document,而不是类的实例化对象
document.addEventListener("keydown",this.keydownHandler.bind(this))this.run()}// 按键的回调函数keydownHandler(event: KeyboardEvent){this.dircter = event.key
}run(){// 蛇头的原坐标let x =this.snake.Xlet y =this.snake.Y// 按下按键后,4个方向中某一个方向的坐标需要修改switch(this.dircter){case'ArrowUp':case'Up':
y = y -10break;case'ArrowDown':case'Down':
y = y +10breakcase'ArrowLeft':case'Left':
x = x -10breakcase'ArrowRight':case'Right':
x = x +10break}// 蛇头下一步是不是撞墙了if(x <0|| x >290|| y <0|| y >290){alert("蛇撞墙了")return// 检测蛇头是否撞到自己}elseif(!this.snake.checkHandBody()){alert('你咬到自己尾巴了')return}else{this.eachFood()// 同一时间只可能有一个轴的位置发生改变if(this.snake.Y=== y){this.snake.X= x
}elseif(this.snake.X=== x){this.snake.Y= y
}// 开启定时器,随着等级的升高,蛇的移动速度越来越快let time =this.scorePanel.level *50setTimeout(this.run.bind(this),250- time)}}// 检测蛇是否吃到食物,吃到食物后:新增食物,增加积分,增加蛇的身体eachFood(){if(this.snake.X===this.food.X&&this.snake.Y===this.food.Y){this.food.change()this.scorePanel.addScore()this.snake.addBody()}}}
/modules/Food.ts
classFood{element:HTMLElement
constructor(){this.element = document.getElementById('food')!this.change()}// 获取食物坐标getX(){returnthis.element.offsetLeft
}getY(){returnthis.element.offsetTop
}// 设置食物坐标setX(value){this.element.style.left = value +'px'}setY(value){this.element.style.top = value +'px'}// 随机在地图上新增食物change(){let top = Math.round(Math.random()*29)*10let left = Math.round(Math.random()*29)*10this.X= left
this.Y= top
}}exportdefault Food
// const a = new Food()// console.log(a.X,a.Y);// a.change()// console.log(a.X,a.Y);
4. 配置文件
package.json
{"name":"part2","version":"1.0.0","description":"","main":"index.js","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"webpack","start":"webpack serve --open"},"keywords":[],"author":"","license":"ISC","devDependencies":{"@babel/core":"^7.23.3","@babel/preset-env":"^7.23.3","babel-loader":"^9.1.3","clean-webpack-plugin":"^4.0.0","core-js":"^3.33.3","css-loader":"^6.8.1","html-webpack-plugin":"^5.5.3","less":"^4.2.0","less-loader":"^11.1.3","postcss":"^8.4.31","postcss-loader":"^7.3.3","postcss-preset-env":"^9.3.0","style-loader":"^3.3.3","ts-loader":"^9.5.1","typescript":"^5.3.2","webpack":"^5.89.0","webpack-cli":"^5.1.4","webpack-dev-server":"^4.15.1"}}