使用TypeScript实现贪吃蛇小游戏(网页版)

本项目使用webpack+ts所编写

下边是项目的文件目录

/src下边的index.html页面是入口文件

index.ts是引入所有的ts文件

/modules文件夹是用来存放所有类的

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 id="main"><!-- 游戏的舞台 --><div id="stage"><!-- 设置蛇 --><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>

index.ts

import "./style/index.less"import GameControl from "./modules/GameControl"
new GameControl()

 /style/less

@bg-color: #b7d4a8;// 清楚默认样式
*{padding: 0;margin: 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;justify-content: space-around;align-items: center;#stage{width: 304px;height: 304px;border: 2px solid black;position: relative;// 设置蛇的样式#snake{&>div{width: 10px;height: 10px;background-color: #000;border: 1px solid @bg-color;// 开启绝对定位position: absolute;}}// 设置食物#food{width: 10px;height: 10px;position: absolute;left: 40px;top: 100px;display: flex;flex-flow: row wrap;justify-content: space-between;align-content: space-between;&>div{width: 4px;height: 4px;background-color: #000;transform: rotate(45deg);}}}#score-panel{width: 300px;display: flex;justify-content: space-between;}
}

/modules/Food.ts

// 定义一个食物 food类
class Food{// 定义一个属性表示食物所对应的元素element:HTMLElement;constructor () {// 获取页面中的food元素饼将其赋给element   !表示一定有元素存在this.element = document.getElementById('food')!;}// 定义获取食物的x轴坐标的方法get X(){return this.element.offsetLeft}// 获取食物的y轴坐标的方法get Y(){return this.element.offsetTop}// 修改食物的一个位置change(){// 生产一个随机的位置// 食物最小的位置是0   最大是300-10=290    // 蛇移动一次就是一格(10),所以食物的坐标必须是整10let top =  Math.round(Math.random()*29)*10     //0-29之间的数,然后是每10倍let left =  Math.round(Math.random()*29)*10     //0-29之间的数,然后是每10倍this.element.style.top = top +'px'this.element.style.left = left +'px'}
}
export default Food

/modules/GameControl.ts

// 引入其他的类
import Food from "./Food";
import Snake from "./snake";
import ScorePanel from "./ScorePanel";// 游戏控制器,控制所有的类
class GameControl{// 定义三个属性 food:Food;snake:Snake;scorePanel: ScorePanel;// 创建一个属性用来存储蛇的移动方向(也就是按键的方向)direction:string = "";// 创建一个属性用来记录游戏是否结束isLIve = trueconstructor(){this.food = new Food()this.snake = new Snake()this.scorePanel = new ScorePanel()this.init()}// 游戏的初始化方法,调用后游戏即开始init(){document.addEventListener('keydown',this.keydownHandler.bind(this ))// 调用run方法,让蛇移动this.run()}// 创建一个键盘按下的响应函数/*ArrowUp    Up ArrowDown   DownArrowLeft   LeftArrowRight   Right*/keydownHandler(event:KeyboardEvent){// 修改direction的属性this.direction = event.key}// 创建一个控制蛇移动的方法run(){// 获取蛇现在的坐标let X = this.snake.Xlet Y = this.snake.Yswitch(this.direction){case "ArrowUp":case "Up":// 向上移动   top减少Y -= 10break;case "ArrowDown":case "Down":// 向下移动   top增加Y += 10break;case "ArrowLeft":case "Left":// 向左移动   left减少X -= 10break;case "ArrowRight":case "Right":// 向左移动   left减少X += 10 break;}// 检查蛇是否吃到了食物this.checkEat(X,Y)// 修改蛇的值try{this.snake.X = Xthis.snake.Y = Y }catch (e) {console.log(e,'1212')// 进入catch,捕获异常,弹出信息alert(e + 'GOME 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

/modules/ScorePanel.ts

// 定义计分牌
class ScorePanel{// score和level用来记录分数和等级score = 0;level = 1;// 分数和等级所在的元素,再构造函数中进行初始化scoreEle:HTMLElement;levelEle: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

/modules/Snake.ts

class Snake{// 表示蛇头的元素head: HTMLElement;// 表示蛇的身体bodies:HTMLCollection;// 蛇的容器element:HTMLElement;constructor(){// 使用断言定义head的类型this.element = document.getElementById('snake')!;this.head = document.querySelector('#snake > div') as HTMLElement;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}// X的值合法范围  0-290if(value <0 || value > 290){//说明蛇撞墙了throw new Error('蛇撞墙了!')}// 修改X时,是在修改水平坐标,蛇在左右移动,蛇在向左移动时,不能向右掉头,反之亦然if(this.bodies[1] && (this.bodies[1] as HTMLElement).offsetLeft === value){// 掉头了,让蛇向反向继续移动if(value > this.X){//如果新值value大于旧值,则说明向右走,发生掉头,应该继续向左走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}// Y的值合法范围  0-290if(value <0 || value > 290){//说明蛇撞墙了throw new Error('蛇撞墙了!')}// 修改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';// 检查有没有撞到自己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'}}// 检查蛇头是否撞到身体方法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

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

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

相关文章

SpringCloud:微服务技术

一、认识微服务&#xff1a; 首先&#xff0c;微服务架构不等于SpringCloud&#xff0c;微服务架构是一种经过良好架构设计的分布式架构方案&#xff0c; &#xff0c;它将应用构建成一系列按业务领域划分模块的&#xff0c;小的自治服务&#xff0c;并解决服务拆分所产生的各种…

【网络】TCP协议详解

目录 TCP协议格式 感性理解TCP报头 认识报头中的字段 序号和确认序号 4位首部长度 窗口大小 标记位 确认应答机制 超时重传机制 TCP协议格式 感性理解TCP报头 linux内核是用C语言写的&#xff0c;所以报头实际上就是一种结构化的数据对象&#xff0c;用伪代码可表示为…

UNI-APP_subNVue原生子窗口使用,web-view层级问题解决

subNVues文档 app-subnvues文档 subNVues开发指南 需求&#xff1a;在pages/cloud_control/index页面使用subNVue原生子窗口 1.pages文件配置 "app-plus": {"bounce": "none","subNVues":[{"id": "control_popup&qu…

Chapter 3: Conditional | Python for Everybody 讲义笔记_En

文章目录 Python for Everybody课程简介Chapter 3: Conditional executionBoolean expressionsLogical operatorsConditional executionAlternative executionChained conditionalsNested conditionalsCatching exceptions using try and exceptShort-circuit evaluation of lo…

idea 启动项目 java: Compilation failed: internal java compiler error

1. 首先查看 项目的 编译的 JDK 版本是否是 匹配了或匹配的 2. 堆分配的内存不足导致&#xff0c;如下图位置 堆 构建程序的 堆大小调大

【JavaWeb】了解JavaScript DOM API

目录 1、什么是DOM 1.1、DOM树 1.2、 了解事件 2、常用的DOM API 2.1、选中页面元素 2.2、获取/修改元素内容 2.2.1、innerHTML和innerText 2.2、获取/修改元素属性 2.3、获取/修改表单元素属性 3、JQuery框架的简单了解和使用 4、代码案例&#xff1a;实现聚合索引功…

Ruoyi单体项目与Echarts4.2.1地图集成时的思路及解决办法

目录 背景 一、相关数据 1、湖南省2021全省地区生产总值 2、湖南Geojson数据 二、Ruoyi集成设计与实现 1、自定义地图注册 2、湖南地图引用 3、图表初始化及数据绑定 4、实际效果 总结 背景 在之前博客中&#xff0c;介绍了Echarts和Ruoyi集成的一些博客基于Echarts2.X的…

味尚食品 味尚拉面半干面是一种非常经典的中式面食

尊敬的客户&#xff0c;您好&#xff01;感谢您对我们电商平台的关注&#xff0c;我们很高兴为您介绍我们平台上的一款热销产品——味尚拉面半干面。 味尚拉面半干面是一种非常经典的中式面食&#xff0c;其主要特点体现在面条的口感和味道方面&#xff0c;让人感觉仿佛在享受正…

密码学学习笔记(八):Public-Key Encryption - 公钥加密1

简介 公钥加密也被称为非对称加密。下面是一个例子&#xff1a; Bob生成一个密钥对&#xff0c;发布他的公钥&#x1d443;&#x1d43e;&#x1d435;, 保管密钥&#x1d446;&#x1d43e;&#x1d435; 私有的Alice使用&#x1d443;&#x1d43e;&#x1d435; 加密明文M…

Windows系统中将markdown文件批量转化为PDF

需要将一个文件夹下的多个md文件转化为PDF 下载安装pandoc 官网下载地址&#xff1a;Pandoc &#xff0c;下载位置如下图。 下载后按照默认文件路径安装完成 使用everything软件查找pandoc.exe文件路径&#xff0c;如下图&#xff1a; 安装完成之后就可以在cmd窗口或Window…

深度学习技巧应用22-构建万能数据生成类的技巧,适用于CNN,RNN,GNN模型的调试与训练贯通

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下深度学习技巧应用22-构建万能数据生成类的技巧&#xff0c;适用于CNN,RNN,GNN模型的调试与训练贯通。本文将实现了一个万能数据生成类的编写&#xff0c;并使用PyTorch框架训练CNN、RNN和GNN模型。 目录&#xff1…

Jupyter Notebook的内核添加新的虚拟环境

最近&#xff0c;在搭建环境的时候发现 Jupyter Notebook 的内核只有基础的python和pytorch&#xff0c;现在我想要在 Jupyter Notebook 中使用新的虚拟环境。 下面是解决的方法&#xff1a; &#xff08;1&#xff09;首先在Anaconda Prompt中激活虚拟环境&#xff0c;比如我…