用TypeScript完成的贪吃蛇小游戏

在这里插入图片描述

食物类Fod

// 定义
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,最大时290//蛇移动一次就是一格,一格的大小就是10,所以就要求食物的大小必须是整10// Math.random()*290  0-290 不包括0,也不包括290;  Math.round(Math.random()*290) 四舍五入包括0也包括290,0到290的整数  不行//包括0,包括29let top=Math.round(Math.random()*29)*10let left=Math.round(Math.random()*29)*10this.element.style.left=left+'px'this.element.style.top=top+'px'}
}
export default Food;

游戏控制器,,控制其他的所有类

//引入其他的类
import Snake from "./Snake";
import Food from "./Food";
import ScorePanel from "./ScorePanel";
//游戏控制器,控制其他的所有类
class GameControl {snake: Snake;food: Food;scorePanel: ScorePanel;//创建一个属性来存储蛇的移动方向(也就是按键的方向),默认值是空串direction: string = '';//创建一个属性用来记录游戏是否结束,false代表游戏结束isLive = true;constructor() {this.snake = new Snake();this.food = new Food();this.scorePanel = new ScorePanel(10,2);this.init();}//游戏的初始化方法,调用后游戏即开始init() {//绑定键盘按键按下的事件document.addEventListener('keydown', this.keydownHandler.bind(this))//调用run方法,使蛇移动this.run();}//创建一个键盘按下的响应函数  //  ArrowUp ArrowDown ArrowLeft ArrowRight  keydownHandler(event: KeyboardEvent) {//需要检查event.key的值是否合法(用户是否按了正确的按钮,也就是方向键)//修改direction属性this.direction = event.key}//创建一个控制蛇移动的方法run() {//根据方向(this.direction)来使蛇的位置改变 向上 top 减少 向下top 增加 向左left 减少 向右left 增加//获取蛇现在的坐标let X = this.snake.X;let Y = this.snake.Y;// ArrowUp Up ArrowDown Down ArrowLeft Left ArrowRight Right //根据按键的方向修改X值和Y值switch (this.direction) {case "ArrowUp":case "up"://向上移动Y -= 10;break;case "ArrowDown":case "Down"://向下移动 top值增加Y += 10;break;case "ArrowLeft":case "Left"://向左移动 left 值减少X -= 10break;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) {//进入到catch,说明出现了异常,游戏结束,弹出了一个提示信息alert(e.message + 'GAME OVER!')//将isLive设置为falsethis.isLive = false}//开启一个定时调用,每隔300毫秒去调用一下,随着等级的提高速度变慢;当isLive是true的时候开启定时器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;

记分牌的类

//定义表示记分牌的类
class ScorePanel{//score和level用来代表分数和等级score=0;level=1;//分数和等级所在的元素,在构造函数中进行初始化scoreEle:HTMLElement;levelEle:HTMLElement;//设置一个变量限制等级maxLevel:number;//设置一个变量表示多少分时升级upScore:number;//传参100就使用100,不传参就使用默认值是10constructor(maxLevel:number=10, upScore:number=10){//! 代表不可能为空this.scoreEle=document.getElementById('score')!this.levelEle=document.getElementById('level')!this.maxLevel=maxLevel;this.upScore=upScore;}//设置一个加分的方法addScore(){//使分数自增this.score++;this.scoreEle.innerHTML=this.score+''//判断分数是多少if(this.score%this.upScore===0){this.levelUp()}}//提升等级的方法levelUp(){if (this.level< this.maxLevel){this.levelEle.innerHTML=++this.level+''}}
}
// const scorePanel=new ScorePanel()// for(let i=0;i<200;i++){
//     scorePanel.addScore()
// }
export default ScorePanel;

class Snake {//表示蛇头的元素head: HTMLElement;//蛇的身体(包括蛇头)bodies: HTMLCollection;//获取蛇的容器element: HTMLElement;constructor() {this.element = document.getElementById('snake')// querySelector 匹配指定 CSS 选择器的第一个元素。this.head = document.querySelector('#snake>div') as HTMLElement;//	document.querySelectorAll() 是 HTML5中引入的新方法,返回文档中匹配的CSS选择器的所有元素节点列表 是静态的this.bodies = this.element!.getElementsByTagName('div')}//获取蛇的坐标(蛇头坐标)get X() {return this.head.offsetLeft;}//获取蛇的Y轴坐标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) {console.log('水平方向发生了掉头')//如果发生了掉头,让蛇向反方向继续移动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大于旧值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() {// 将后边的身体设置为前边身体的位置 举例子 第4节=第3节的位置  第3节等于第2节的位置 第2节等于蛇头的位置// 遍历获取所有的身体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;console.log(this.bodies[i]);//将值设置到当前身体上(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;

样式


@bg-color:#b7d4a8;
// 清除默认的样式
*{margin:0;padding:0;//改变盒子模型的计算方式box-sizing: border-box;
}
body{font:bold 20px "Courier";//禁用滚动条overflow-x: hidden;overflow-y: hidden;
}
//设置主窗口的样式
#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: #000; border: 1px solid @bg-color;position: absolute;}  }&>#food{width:10px;height:10px;position: absolute;left:40px;top:100px;//开启弹性盒display:flex;//设置横轴为主轴,wrap表示会自动换行flex-flow:row wrap;//设置主轴和侧轴的空白空间分配到元素之间justify-content: space-between;align-content: space-around;div{width:4px;height:4px;background-color: black;//使四个div 旋转45度transform: rotate(45deg);}}
}
//记分牌
#score-panel{width:300px;display:flex;//设置株洲的对齐方式justify-content: space-between;
}

html

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>贪吃蛇</title></head><body><!-- 创建游戏的主窗口 --><div id="main"><!-- 设置游戏的舞台 --><div id="stage"><!-- 设置蛇 --><div id="snake"><!-- snake内部的div表示蛇的各部分 --><div></div></div><!-- 设置食物 --><div id="food"><!-- 添加4个小div来设置食物的样式 --><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'
const gc=new GameControl();

在这里插入图片描述

尚硅谷TypeScript教程(李立超老师TS新课) https://www.bilibili.com/video/BV1Xy4y1v7S2?p=1&vd_source=c2279a533bc837e2d5b9ca3570c0a841

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

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

相关文章

(六)activiti-modeler 设计器属性编辑弹窗bug修复

BUG重现 在使用流程设计器时&#xff0c;经常碰到弹窗不小心关闭&#xff0c;比如不小心点击了灰色背景上&#xff0c;此时BUG就出现了。弹窗被关闭了&#xff0c;分配用户属性被置空了&#xff0c;以前有数据也被清空了&#xff0c;还无法再次点击弹窗编辑。 不仅仅是分配用…

【Vue3】组件通信之v-model

【Vue3】组件通信之v-model 背景简介开发环境开发步骤及源码总结 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗的…

LDR6020快充线,科技与便捷的新宠

在快节奏的现代生活中&#xff0c;充电效率成为了我们不可忽视的一个重要因素。随着智能手机、平板电脑等电子设备的普及&#xff0c;快充线以其独特的优势逐渐成为充电设备市场的新宠。 快充线&#xff0c;相比于传统的普通充电线&#xff0c;快充线在充电速度上有着显著的提升…

五、一个quad同时支持pcie和sfp两种高速接口的ref时钟配置

项目描述 上位机将截图数据通过 XDMA 写入到 FPGA 侧的 DDR 内存区域 1 中通过 axi_lite 接口给 axi_read_start 信号&#xff0c;通知 AXI_read 模块启动读取数据&#xff0c;然后通过 GTP TX 模块发送出去。经过光纤回环&#xff0c;GTP RX 端接收到数据&#xff0c;送给 AX…

微分方程的数值解法——Runge-Kutta (RK4)

Runge-Kutta (RK4)   The Runge-Kutta (RK4) methods are used to solve the solution of the non-liner ordinary differential equation. Here, we will simply summary this method.   Assume the Intial Value Piont (IVP) is satisfied: y ′ f ( t , y ) , y ( t 0 )…

python-查找元素3(赛氪OJ)

[题目描述] 有n个不同的数&#xff0c;从小到大排成一列。现在告诉你其中的一个数x&#xff0c;x不一定是原先数列中的数。你需要输出最后一个<x的数在此数组中的下标。输入&#xff1a; 输入共两行第一行为两个整数n、x。第二行为n个整数&#xff0c;代表a[i]。输出&#x…

椭圆曲线加法运算

1. 定义 椭圆曲线 (Elliptic Curve) 不是函数&#xff0c;而是一条平面曲线&#xff0c;其方程是定义如下&#xff1a; y 2 x 3 a x b y^2x^3axb y2x3axb 其中&#xff0c;判别式 Δ − 16 ( 4 a 3 27 b 2 ) ≠ 0 \Delta -16(4a^327b^2)\neq 0 Δ−16(4a327b2)0。判别…

Java 并发编程:一文了解 synchronized 的使用

大家好&#xff0c;我是栗筝i&#xff0c;这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 027 篇文章&#xff0c;在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验&#xff0c;并希望进…

keil编译报错error:#8:missing closing quote 处理

MDK5采用UTF-8&#xff0c;提示很多个这样的error:#8&#xff1a;missing closing quote 的错误信息。提供以下几种方式解决&#xff1a; 在KEIL中Options for Target Flash -> C/C -> Misc Controls添加“--localeenglish”。

49 序列解包的多种形式和用法

序列解包&#xff08;Sequence Unpacking&#xff09;是 Python 中非常重要和常用的一个功能&#xff0c;可以使用非常简洁的形式完成复杂的功能&#xff0c;提高了代码的可读性&#xff0c;减少了程序员的代码输入量。 x, y, z 1, 2, 3 # 多个变量同时赋值 v_tuple (False…

【课程系列07】某乎AI大模型全栈工程师-第7期

网盘链接 链接&#xff1a;百度网盘 请输入提取码 --来自百度网盘超级会员v6的分享 课程目标 学习完毕咱们可以收获什么种能力&#xff1a; 1、传统前端 后端 数据分析 产品 绘图 算法工程等工作&#xff0c;一个人都可以实现&#xff0c;实现超级个体的能力 2、可以解决…

【C语言】Top K问题【建小堆】

前言 TopK问题&#xff1a;从n个数中&#xff0c;找出最大&#xff08;或最小&#xff09;的前k个数。 在我们生活中&#xff0c;经常会遇到TopK问题 比如外卖的必吃榜&#xff1b;成单的前K名&#xff1b;各种数据的最值筛选 问题分析 显然想开出40G的空间是不现实的&#…

基于STM32的温湿度监控系统

目录 引言环境准备工作 硬件准备软件安装与配置系统设计 系统架构硬件连接代码实现 初始化代码主循环代码应用场景 家居环境监控工业环境监控常见问题及解决方案 常见问题解决方案结论 1. 引言 在智能家居和工业自动化中&#xff0c;温湿度监控系统是一个非常重要的组成部分…

Java企业微信服务商代开发获取AccessToken示例

这里主要针对的是企业微信服务商代开发模式 文档地址 可以看到里面大致有三种token&#xff0c;一个是服务商的token&#xff0c;一个是企业授权token&#xff0c;还有一个是应用的token 这里面主要有下面几个参数 首先是服务商的 corpid 和 provider_secret &#xff0c;这个可…

使用GCC编译Notepad++的插件

Notepad的本体1是支持使用MSVC和GCC编译的2&#xff0c;但是Notepad插件的官方文档3里却只给出了MSVC的编译指南4。 网上也没有找到相关的讨论&#xff0c;所以我尝试在 Windows 上使用 MinGW&#xff0c;基于 GCC-8.1.0 的 posix-sjlj 线程版本5&#xff0c;研究一下怎么编译…

快手商业化 Java后端 二面|面试官很nice

面试总结&#xff1a;没有那种纯八股问题&#xff0c;都是偏向于情景题。看到面试官最后出了一道多叉树的题目&#xff0c;我以为是想直接刷人&#xff0c;但还是尽力去尝试了一下&#xff0c;最后也没做出来&#xff0c;面试官很nice&#xff0c;在答不上来的时候会引导我去思…

JVM—垃圾收集算法和HotSpot算法实现细节

参考资料&#xff1a;深入理解Java虚拟机&#xff1a;JVM高级特性与最佳实践&#xff08;第3版&#xff09;周志明 1、分代回收策略 分代的垃圾回收策略&#xff0c;是基于这样一个事实&#xff1a;不同的对象的生命周期是不一样的。因此&#xff0c;不同生命周期的对象可以采取…

python实现小游戏——植物大战僵尸(魔改版本)

制作一款DIY的‘植物大战僵尸’游戏引起了很多人的兴趣。在这里&#xff0c;我将分享一个使用Python语言在PyCharm环境中开发的初始状态版本。这个版本主要应用了pygame库来完成&#xff0c;是一个充满创意和趣味的魔改版本。 文章目录 前言一、开发环境准备二、代码1.main方法…

Linux小组件:gcc

gcc 是C语言的编译器&#xff0c;在Linux下我们也用这个编译C语言 安装gcc sudo apt install build-essential 查看gcc版本信息 gcc --version 有时候会出现代码编译不过去的问题&#xff0c;通常可能是gcc的编译标准太低&#xff0c;不支持某些写法 比如在很多旧的编译标…

SQL注入实例(sqli-labs/less-4)

0、初始页面 1、确定闭合符号 前两条判断是否为数值型注入&#xff0c;后两条判断字符型注入的闭合符号 ?id1 and 11 ?id1 and 12 ?id1" ?id1") 2、确定表的列数 ?id1") order by 3 -- 3、确定回显位置 ?id-1") union select 1,2,3 -- 4、爆库…