ts实现贪吃蛇记录
只记录TS逻辑,不做布局说明
一、主体:
1、食物
2、分数、等级变化
3、蛇(蛇头,蛇身)
4、控制器(键盘监听)
二、模块:
1、Food.ts
// 食物类 class Food { // 定义一个属性表示食物所对应的元素 element: HTMLElement; constructor() { // 获取页面中的food元素并赋值给element this.element = document.getElementById('food')! ; // 叹号表示不可能为空 } // 定义一个获取食物X轴坐标的方法 get X() { return this.element.offsetLeft; } // 定义一个获取食物Y轴坐标的方法 get Y() { retutn this.element.offsetTop; } // 修改食物的位置 change() { // 生成一个随机的位置 // 食物的位置最小是0 最大是290 // 蛇移动一次就是一格,一格的大小就是10 let top = Math.round( Math.random() * 29 ) * 10; let left = Math.round( Math.random() * 29 ) * 10; this.element.style.left = left + 'px' ; this.element.style.top = top + 'px' ; } } export default Food;
2、ScorePanel.ts
// 记分牌类 class ScorePanel { // score 和 level 用来记录分数和等级 score = 0 ; level = 1 ; maxLevel = 10; // 分数和等级所在的元素,在构造函数中进行初始化 scoreEle : HTMLElement; levelEle : HTMLElement; maxLevel : number; upScore : number; constructor( maxLevel:number = 10, upScore:number = 10 ){ this.scoreEle = document.getElementById('scoreEle') this.levelEle = document.getElementById('levelEle') this.maxLevel = maxLevel; this.upScore = upScore; } // 设置一个加分的方法 addScore(){ this.scoreEle.innderHTML = ++this.score + ''; //分数自增 if (this.score % this.upScore === 0 ) { this.levelUp(); } } // 设置一个等级提升的方法 levelUp(){ if (this.level < this.maxLevel) { this.levelEle.innderHTML = ++this.level + ''; //等级自增 } } } export default ScorePanel;
3、Snake.ts
class Snake { // 表示蛇头的元素 head: HTMLElement; // 蛇的身体(包括蛇头) bodies: HTMLCollection; // 获取蛇的容器 element: HTMLElement; construcotr(){ this.element = document.getElementById('snake')! ; this.head = document.querySelector('#snake > div') as HTMLElement ; this.bodyies = this.element.getElementsByTagName('div') ; } // 获取蛇的坐标(蛇头坐标) get X(){ return this.head.offsetLeft; } get Y(){ return this.head.offsetTop; } // 设置蛇的坐标(蛇头坐标) set X( value : number ){ // 如果新值和旧值相同,则直接返回不再修改 if (this.X === value) return; // X的值是否再合法范围0-290 if ( value<0 || value>290 ) { throw new Error("蛇撞墙了"); } // 蛇向左时不能往右移动,反之 if ( this.bodies[1] && (this.bodies[1] as HTMLElement).offerLeft === value ) { // 如果发生了掉头,让蛇继续向反方向移动 if (value>this.X) { // 如果新值value大于旧值X,说明蛇在往右走,此时发生掉头,应该使蛇继续向左走 value = this.X - 10; } else { value = this.X + 10; } } // 移动身体 this.moveBody(); this.head.style.left = value + 'px'; // 检查有没有撞到自己 this.checkHeadBody(); } set Y( value : number ){ if (this.Y === value) return; if ( value<0 || value>290 ) { throw new Error("蛇撞墙了"); } // 蛇向上时不能往下移动,反之 if ( this.bodies[1] && (this.bodies[1] as HTMLElement).offerTop === value ) { // 如果发生了掉头,让蛇继续向反方向移动 if (value>this.Y) { // 如果新值value大于旧值X,说明蛇在往下走,此时发生掉头,应该使蛇继续向上走 value = this.Y - 10; } else { value = this.Y + 10; } } // 移动身体 this.moveBody(); this.head.style.top = value + 'px'; // 检查有没有撞到自己 this.checkHeadBody(); } // 蛇增加身体的方法 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"; } } } export default Snake;
4、GameControl.ts
// 游戏控制器,控制其他所有类 import Snake from "./Snake"; import Food from "./Food"; import ScorePanel from "./ScorePanel"; class GameControl { // 定义三个属性 snake: Snake; food: Food; scorePanel : ScorePanel; // 创建一个属性来存储蛇的移动方向(按键方向) direction: string=''; // 字符串默认为空串 // 创建一个属性用来记录游戏是否结束 isLive = true; constructor() { this.snake = new Snake(); this.food = new Food(); this.scorePanel = new ScorePanel(); } // 游戏的初始化方法,调用后游戏即开始 init() { // 绑定键盘按下事件 document.addEventListener('keydown', this.keyboardEvent.bind(this) ) // bind // 调用run方法,使蛇移动 this.run(); } // 创建一个键盘按下的响应函数 keydownHandler(event:keyboardEvent) { // 检查event.key的值是否合法 // ArrowUp ArrowDown ArrowLeft ArrowRight 、 Up Down Left Right // 修改direction属性(方向) if( event.key ) this.direction = event.key; } // 创建一个控制蛇移动的方法 run(){ // 获取蛇现在的坐标 let X = this.snake.X; let Y = this.snake.y; // 根据方向(this.direction)来使蛇的位置改变 top- top+ left- left+ switch (this.direction) { case "ArrowUp" : case "Up" : Y -= 10; break; case "ArrowDown" : case "Down" : Y += 10; break; case "ArrowLeft" : case "Left" : X -= 10; break; case "ArrowRight" : case "Right" : X += 10; break; } // 检查蛇是否吃到了食物 this.checkEat(X,Y) // 修改蛇的x和y值 try{ this.snake.x = X this.snake.y = Y }catch(e){ // 进入到catch 说明出现了异常 游戏结束 alert(e.message); this.isLive = false; } // 开启一个定时调用 this.isLive && setTimeout( this.run.bind(this), 300 - (this.ScorePanel.level-1)*30 ) } // 定义一个方法,检查蛇是否吃到了食物 checkEat(X: number, Y: number){ if (X === this.food.X && Y === this.food.Y) { // 食物位置重制 this.food.change(); // 分数增加 this.scorePanel.addScore(); // 蛇要增加一节 this.snake.addBody(); } } //获取所有的身体,检查是否发生重叠 checkHeadBody(){ for(let i = 1; i<this.bodies.length; i++){ let bd = this.bodies[i] as HTMLElement; if (this.X === bd.offsetTop) { // 进入判断说明蛇头撞到了自己 throw new Error("撞到自己了"); } } } }
来自: https://www.bilibili.com/video/BV1Xy4y1v7S2?p=30&spm_id_from=pageDriver
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~