赞
踩
基于TypeScript的贪食蛇项目 此项目学习于-哔哩哔哩尚硅谷TypeScript教程(李立超老师TS新课)
TypeScript
node版本 v18.17.0
https://gitee.com/shen_jinlong/snake-ts.git
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>贪食蛇</title> </head> <body> <!-- 游戏容器 --> <div id="main"> <!--游戏屏幕--> <div id="screen"> <div id="snake"> <div></div> </div> <!-- 设置食物 --> <div id="food"> <!-- 设置食物样式 --> <div></div> <div></div> <div></div> <div></div> </div> </div> <!--记分牌--> <div id="score-panel"> <div> SCORE:<span id="score">0</span> </div> <div> level:<span id="level">1</span> </div> </div> </div> </body> </html>
// 设置变量 @bg-color: #b7d4a8; // 清除默认样式 * { margin: 0; padding: 0; // 改变盒子模型计算方式 box-sizing: border-box; } body { font: bold 20px "Courier"; } // 设置主窗口的样式 #main { width: 360px; height: 420px; background-color: @bg-color; margin: 100px auto; border: 10px solid black; border-radius: 40px; // 开启弹性盒模型 display: flex; // 设置主轴方向 flex-flow: column; // 设置侧轴的对齐方式 align-items: center; // 设置主轴的对齐方式 justify-content: space-around; // 操作屏幕 #screen { // 开启相对定位 position: relative; margin-top: 20px; width: 304px; height: 304px; border: 2px solid black; #snake { &>div { // 开启绝对定位 position: absolute; width: 10px; height: 10px; border: 1px solid @bg-color; background-color: #000; } } // 设置食物 &>#food { position: absolute; left: 40px; top: 100px; display: flex; flex-flow: row wrap; justify-content: space-between; align-content: space-between; width: 10px; height: 10px; &>div { width: 4.5px; height: 4.5px; background-color: black; transform: rotate(45deg); } } } // 记分牌 #score-panel { width: 300px; display: flex; // 设置主轴的对齐方式 justify-content: space-around; } }
/** 定义食物类 */ class Food { /* 属性 */ element: HTMLElement; // 食物元素实例 constructor() { // 获取dom元素 this.element = document.getElementById('food')!; } /* 方法 */ /** 定义一个获取食物X轴坐标的方法 */ get X() { return this.element.offsetLeft; } /** 定义一个获取食物Y轴坐标的方法 */ get Y() { return this.element.offsetTop; } /** 生成随机位置 */ change() { /** * 生成随机位置 * 1. 取值范围(0~290)&& 10的倍数(配合蛇的运动) */ let elementLeft = Math.round(Math.random() * 29) * 10; let elementTop = Math.round(Math.random() * 29) * 10; // Math.floor(Math.random() * 30) * 10; // 向下取整 this.element.style.left = elementLeft + 'px'; this.element.style.top = elementTop + 'px'; } } export default Food;
/** 记分牌类 */ class ScorePanel { /* 属性 */ score = 0; level = 1; scoreElement: HTMLElement; levelElement: HTMLElement; maxLevel: number; // 最大等级 upScore: number; // 升级需要的分数 constructor(maxLevel: number = 10, upScore: number = 10) { this.scoreElement = document.getElementById('score')!; this.levelElement = document.getElementById('level')!; this.maxLevel = maxLevel; this.upScore = upScore; } /** 方法 */ /** 得分 */ addScore() { this.scoreElement.innerHTML = ++this.score + ''; if (this.score % this.upScore === 0) { this.upLevel(); // this.upScore = this.upScore * 2; } } /** 升级 */ upLevel() { if (this.level < this.maxLevel) { this.levelElement.innerHTML = ++this.level + ''; } } } export default ScorePanel;
class Snake { head: HTMLElement; // 蛇的身体(包括头部) bodies: HTMLCollection; // 获取蛇的容器 element: HTMLElement; constructor() { this.element = document.getElementById('snake')!; this.head = document.querySelector('#snake > div')!; this.bodies = 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; } // 撞墙检测 if (value < 0 || value > 290) { // 撞墙啦 throw new Error('游戏结束!') } // 设置不能反方向移动 if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetLeft === value) { value += 10; if (value > this.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).offsetTop === value) { value += 10; if (value > this.Y) { 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() { /** * 后一节的身体等于前一节的身体位置 * eg: * 第四节 = 第三节位置 * 第三节 = 第二节位置 * 第二节 = 第一节位置 * 第一节自己走了 */ 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'; } } /** 判断蛇头是否撞了身体 */ checkHeadBody() { // 获取所有身体,检查是否和蛇头的坐标发生重叠 for (let i = 1; i < this.bodies.length; i++) { let bd = this.bodies[i] as HTMLElement; if (this.X === bd.offsetLeft && this.Y === bd.offsetTop) { throw new Error('游戏结束!') } } } } export default Snake;
// 引入其他的类 import Snake from "./Snake"; import Food from "./Food"; import ScorePanel from "./ScorePanel"; /** 游戏控制器,控制其他所有类 */ class GameControl { // 定义三个属性 snake: Snake; // 蛇 food: Food; // 食物 scorelPanel: ScorePanel; // 记分牌 direction: string = 'ArrowRight'; // 蛇的移动方向 isLive: boolean = true; // 记录游戏是否结束 constructor() { this.snake = new Snake(); this.food = new Food(); this.scorelPanel = new ScorePanel(); } /** 游戏的初始化方法 */ init() { // 绑定键盘按下的事件 // document.addEventListener('keydown', this.keydownHandler.bind(this)); // document.addEventListener('keydown', (event) => this.keydownHandler(event)); document.addEventListener('keydown', this.keydownHandler); // 调用蛇移动 this.run(); } /** 创建一个键盘按下的响应函数 */ keydownHandler = (event: KeyboardEvent) => { this.direction = event.key; } // keydownHandler(event: KeyboardEvent) { // this.direction = event.key; // } /** 创建一个控制蛇移动的方法 */ run() { /** * 根据方向(this.direction)来使蛇的位置改变 * 向上——top 减少 * 向下——top 增加 * 向左——left 减少 * 向右——left 增加 */ // 获取蛇的坐标 let X = this.snake.X; let Y = this.snake.Y; switch (this.direction) { case "ArrowUp": // 向上移动top减少 Y -= 10; break; case "ArrowDown": // 向下移动top增加 Y += 10; break; case "ArrowLeft": // 向左移动left减少 X -= 10; break; case "ArrowRight": // 向右移动left增加 X += 10; break; } // 吃到食物 this.checkEat(this.snake.X, this.snake.Y); // 修改蛇的位置 try { this.snake.X = X; this.snake.Y = Y; } catch (e: any) { // 进入到catch,出现异常,游戏结束,弹出一个提示 alert(e.message); this.isLive = false; } // 开启定时调用 this.isLive && setTimeout(this.run.bind(this), 300 - (this.scorelPanel.level - 1) * 30); // setTimeout(() => { // this.run(); // }, 300 - (this.scorelPanel.level - 1) * 30); } // 检测蛇是否吃到食物 checkEat(X: number, Y: number) { if (X === this.food.X && Y === this.food.Y) { // 更新食物位置 this.food.change(); // 分数增加 this.scorelPanel.addScore(); // 增长蛇 this.snake.addBody(); } } } export default GameControl;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。