TypeScript实现一个贪吃蛇小游戏

游戏效果

文件目录

准备1:新建index.html,编写游戏静态页面

<!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 class="main"><div class="stage"><div id="snake"><div></div></div><div id="food"><div></div></div></div><div class="score-panel"><div>SCORE: <span id="score">0</span></div><div>level: <span id="level">1</span></div></div></div>
</body>
</html>

准备2:使用less,修改样式,编写CSS

//设置变量
@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;//游戏舞台.stage {width: 304px;height: 304px;border: 2px solid black;position: relative;//蛇的样式#snake{&>div{width: 10px;height: 10px;background-color: black;border: 1px solid @bg-color;//绝对定位position: absolute;}}#food{position: absolute;left: 40px;top: 100px;background-color: rebeccapurple;display: flex;flex-flow: row wrap;justify-content: space-between;align-content: space-between;&>div{width: 4px;height: 4px;background-color: black;transform: rotate(45deg);}}}//记分牌.score-panel {width: 300px;display: flex;justify-content: space-between;}
}

准备3:创建4个类:食物类-Food、记分牌等级类-ScorePanel、蛇类-Snake、操控类-GameControl

//食物类Food
class Food{//定义一个属性表示食物所对应的元素element : HTMLElement;constructor(){//获取页面中的food元素并将其赋值给elementthis.element = document.getElementById('food') ! ;}//定义一个获取食物X轴坐标的方法get X (){return this.element.offsetLeft}//定义一个获取食物Y轴坐标的方法get Y (){return this.element.offsetTop}//修改食物的位置change(){//生成一个随机的位置let top = Math.round(Math.random()*29)*10let left = Math.round(Math.random()*29)*10//食物的位置最小的0,最大是290//蛇移动一次就是一格,一格的大小就是10,所以就要求食物的this.element.style.left = left + 'px'this.element.style.top = top + 'px'}
}
export default Food
//记分牌的类
class ScorePanel {score = 0;level = 1 //分数和等级所在的元素,在构造函数中进行初始化scoreEle:HTMLElementlevelEle:HTMLElement//设置一个变量限制等级maxLevel :number//设置一个变量表示多少分时升级upScore : numberconstructor(maxLevel:number = 10,upScore:number = 10){this.scoreEle = document.getElementById('score')!this.levelEle = document.getElementById('level')!this.maxLevel = maxLevelthis.upScore =  upScore}//设置一个加分的方法addScore(){//使分数自增this.scoreEle.innerHTML = ++this.score + ''if(this.score % this.upScore ===0){this.levelUp()}}//提升等级方法levelUp(){if(this.level < this.maxLevel){this.levelEle.innerHTML = ++this.level + ''}}
}
export default ScorePanel
//蛇类-Snake
class Snake {//表示蛇头的元素head : HTMLElement//蛇的身体bodies: HTMLCollection//获取蛇的容器element :HTMLElement constructor(){this.element = document.getElementById('snake')!this.head = document.querySelector('#snake >div') as HTMLElementthis.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}//X的值的合法范围在0-290之间if(value <0 || value >290){//进入判断说明蛇撞墙了throw new Error('蛇撞墙了')}//修改X时,是在修改水平坐标,蛇在左右移动,蛇向左移动时,不能向右移动,反之亦然if(this.bodies[1]&&(this.bodies[1] as HTMLElement).offsetLeft ===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('蛇撞墙了')}//修改Y时,是在修改垂直坐标,蛇在上下移动,蛇向上移动时,不能向下移动,反之亦然if(this.bodies[1]&&(this.bodies[1] as HTMLElement).offsetTop ===value){//如果发送了掉头,让蛇向反方向继续移动if(value >this.Y){//如果新值value大于旧值Y,则说明蛇在向下走,此时发送掉头,应该使蛇继续向上走value = this.Y - 10;}else{//向左走value = this.Y + 10}}this.moveBody()this.head.style.top = value + 'px'//检查有没有撞到自己this.checkHeadBody()}//蛇增加身体的方法addBody(){//向element中添加一个divthis.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';}}//检查蛇头是否撞到身体上checkHeadBody(){//获取所有身体,检查是否和蛇头的坐标发生重叠for(let i = 1 ;i<this.bodies.length;i++){let bd = this.bodies[i] as HTMLElementif(this.X ===bd.offsetLeft && this.Y === bd.offsetTop){//进入判断说明蛇头撞到了身体,游戏结束throw new Error('撞到了自己!!!')}}}
}
export default Snake
//控制类
import Food from './Food'
import ScorePanel from './ScorePanel'
import Snake from './Snake'
//游戏控制器,控制其他的所有类
class GameControl{//定义一个属性//蛇snake :Snake//食物food:Food//记分牌scorePanel:ScorePanel//创建一个属性来存储蛇的移动方向(也就是按键的方向)direction :string = ''//创建一个属性用来记录游戏是否结束isLive = trueconstructor(){this.snake = new Snake()this.food = new Food()this.scorePanel = new ScorePanel()this.init()}//游戏的初始化方法,调用后游戏即开始init(){//绑定键盘按键按下的事件document.addEventListener('keydown',this.keydownHandler.bind(this))//调用run方法,使蛇移动this.run()}//创建一个键盘按下的响应函数keydownHandler(event:KeyboardEvent){//需要检查event.key的值是否合法(用户是否按了正确的按键)//修改direction属性this.direction = event.key}//创建一个控制蛇移动的方法run (){/** 根据方向(this.direction)来使蛇的位置改变* 向上 top减少* 向下top增加* 向左 left减少* 向右left 增加 *///获取蛇现在的坐标let X  = this.snake.Xlet Y = this.snake.Y//根据按键方向switch(this.direction){case "ArrowUp":case 'Up'://向上移动top减少Y -=10;break;case 'ArrowDown':case 'Down'://向下移动top增加Y+=10;break;case 'ArrowLeft':case 'Left'://向左移动left 减少X-=10;break;case 'ArrowRight':case 'Right'://向右移动left 增加X+=10;break;}//检查蛇是否吃到食物this.checkEat(X,Y)//修改蛇的X、Y方向try {this.snake.X = X;this.snake.Y = Y ;           } catch (e:any) {//进入到catch,说明出现了异常,游戏结束,弹出一个提示信息alert(e.message + 'GAME OVER')//将isLive设置为falsethis.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()}   }
}
export default GameControl

准备4:创建index.ts文件,执行游戏

import './style/index.less'
import GameControl from './moduls/GameControl'new GameControl()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/414530.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu源码安装MySQL

mysql下载路径 创建新数组 mysql sudo groupadd mysql# 创建用户 mysql ,指定属组为 mysql&#xff0c;禁止其登录 # --no-create-home选项&#xff0c;创建用户时不会自动创建主目录 sudo adduser --system --no-create-home --ingroup mysql --shell /sbin/nologin mysql创…

CC工具箱使用指南:【三调_土地利用现状分类面积汇总表(竖版)】

一、简介 之前做了一个统计三调土地利用现状分类面积汇总表的工具。 汇总表的格式采用《TDT 1055-2019 第三次全国国土调查技术规程》的附表2&#xff0c;使用的是横版的表格。 但是有小伙伴反映需要竖版的的统计表格&#xff0c;于是就做了这么一个衍生工具。 表格长这样&…

vue3自定义按钮点击变颜色实现(多选功能)

实现效果图&#xff1a; 默认选中第一个按钮&#xff0c;未选中按钮为粉色&#xff0c;点击时颜色变为红色 利用动态类名&#xff0c;当定义isChange数值和下标index相同时&#xff0c;赋予act类名&#xff0c;实现变色效果 <template><div class"page"&…

表单验证 ---- 在Vue2中使用ElementUI进行表单验证

目录 前言 给表单绑定对应属性 在data中定义数据对象和表单的定义规则 与数据对象双向绑定 对整个表单进行验证 前言 在做项目时&#xff0c;对于表单进行验证是我们必不可少的 例如 搭建一个基本的登录界面 <div class"form"><h1>登录</h1>&…

即时按需原子 CSS 引擎:比 Tailwind JIT 快 5 倍! | 开源日报 No.149

unocss/unocss Stars: 14.6k License: MIT 该项目是一个即时的按需原子 CSS 引擎&#xff0c;受到 Windi CSS、Tailwind CSS 和 Twind 的启发&#xff0c;解决了定制化、速度和体积的问题。 以下是该项目的特点和核心优势&#xff1a; 完全可定制&#xff1a;通过预设提供所…

深度求索开源国内首个 MoE 大模型 | DeepSeekMoE:在专家混合语言模型中实现终极专家专业化

文章目录 一、前言二、主要内容三、总结 &#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、前言 在大语言模型时代&#xff0c;混合专家模型&#xff08;MoE&#xff09;是一种很有前途的架构&#xff0c;用于在扩展模型参数时管理计算成本。然而&a…

OPC UA开源库Open62541源码编译及Client客户端Server服务器端测试[一]

前言 1.Open62541 概述 2.Open62541 的功能 3.Open62541 的开发环境 4.Open62541 编译工具 5.Open62451源码下载 6.Open62541源码编译 7.Open62541 Server服务器端测试 8.Open62541Client客户端测试 Open62541 是一款开源的嵌入式系统开发手册&#xff0c;旨在帮助开…

c# 自定义 滑块TrackBar

辛苦半天做出来的&#xff0c;如果觉得好用&#xff0c;记得点赞 效果图如下&#xff1a; 具体操作&#xff1a; 1 、添加代码&#xff08;代码在下面&#xff09;&#xff0c;重新生成下整个工程&#xff0c;在工具栏中就出现控件&#xff0c;将控件拖到窗体中 2、只需要调整…

分享 GitHub 上的敏感词汇工具类:sensitive-word

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

6.3.5编辑视频

6.3.5编辑视频 除了上面的功能外&#xff0c;Camtasia4还能进行简单的视频编辑工作&#xff0c;如媒体的剪辑、连接、画中画等。 下面我们就利用Camtasia4的强大功能来实现一个画中画效果&#xff0c;在具体操作之前&#xff0c;需要准备好两个视频文件&#xff0c;一个作为主…

Python使用HTTP代理实现网络请求的调试和日志记录

在Python中&#xff0c;使用HTTP代理可以实现网络请求的调试和日志记录。通过HTTP代理&#xff0c;我们可以拦截、修改或记录网络请求和响应的数据&#xff0c;以便更好地了解和调试网络请求。 下面是一个使用Python和httplib2库实现HTTP代理的示例&#xff0c;同时对请求和响…

费斯托工具如何借助CRM为业务赋能?

对于“以客户为中心”的企业来说&#xff0c;要提升企业业绩&#xff0c;就要确保与客户在营销、销售、服务每一个环节上的交互都顺利、高效&#xff0c;而CRM系统正是承载这些功能的数字化工具。从图特斯工具系统技术&#xff08;上海&#xff09;有限公司&#xff08;简称“费…