TypeScript 学习笔记 第三部分 贪吃蛇游戏
尚硅谷TypeScript教程(李立超老师TS新课)
1. 创建开发环境
- 创建工程,使用学习笔记的第二部分
- 安装css部分
npm i -D less less-loader css-loader style-loader
- 对css部分处理,能够运行在低版本浏览器
npm i -D postcss postcss-loader postcss-preset-env
- 修改webpack.config.json文件

// 设置less文件的处理{test: /\.less$/,use: ["style-loader","css-loader",{loader: "postcss-loader",options: {postcssOptions:{plugins: [["postcss-preset-env",{browsers:"last 2 versions"}]]}}},"less-loader"]}
2. 工程目录结构

3. 代码部分
- index.js
import './style/index.less'import GameControl from "./modules/GameControl";new GameControl()
- index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><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>
- /style/index.less
// 设置变量
@bg-color:#b7d4a8;*{margin: 0;padding: 0;caret-color: transparent;// 改变盒子模型的计算方式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: #000;border:1px solid @bg-color;// 开启绝对定位position: absolute;}}#food{width: 10px;height: 10px;border:1px solid @bg-color;// 开启绝对定位position: absolute;display: flex;flex-wrap: wrap;align-content: space-between;justify-content: space-between;&>div{width: 4px;height: 4px;background-color: black;transform: rotate(45deg);}}}#score-panel{width: 300px;display: flex;justify-content: space-between;}
}
- /modules/snake.ts
export default class Snake{// 蛇头head:HTMLElement// 蛇身体,包括蛇头bodies:HTMLCollection// 蛇的父容器element:HTMLElementconstructor() {this.element = document.getElementById("snake")!this.bodies = this.element.childrenthis.head = this.element.firstElementChild as HTMLElement}// 蛇头的坐标get X(){return this.head.offsetLeft}get Y(){return this.head.offsetTop}// 设置蛇头的坐标set X(value){// 当蛇的第二节与蛇头的x轴坐标重合,说明发生了水平方向的掉头if(this.bodies[1] && (this.bodies[1] as HTMLElement).offsetLeft === value) {if(value > this.X){value = this.X - 10}else{value = this.X + 10}}this.moveBody()// 设置蛇头坐标this.head.style.left = value + 'px'}set Y(value){// 当蛇的第二节与蛇头的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'}// 蛇增加身体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';}}checkHandBody():boolean{for (let i = 1; i < this.bodies.length; i++) {if (this.X === (this.bodies[i] as HTMLElement).offsetLeft &&this.Y === (this.bodies[i] as HTMLElement).offsetTop){return false}}return true}
}
- /modules/ScorePanel.ts
export default class ScorePanel{score = 0level = 1scoreElement : HTMLElementlevelElement : HTMLElementmaxLevel : numberupScore : numberconstructor(maxLevel = 10,upScore = 10) {this.scoreElement = document.getElementById('score')!this.levelElement = document.getElementById('level')!this.maxLevel = maxLevel // 最大等级this.upScore = upScore // 多少分升一级}// 增加积分,每吃一个食物增加1分,在此处设置等级的增加addScore(){this.score ++this.scoreElement.innerText = this.score.toString()if (this.score % this.upScore === 0){this.addLevel()}}// 增加等级addLevel(){if ( ++this.level <= this.maxLevel) {this.levelElement.innerText = this.level.toString()}}
}// const a = new ScorePanel()
// for (let i = 0; i < 200; i++) {
// a.addScore()
// }
- /modules/Gamecontrol.ts
import Snake from "./snake";
import Food from "./Food";
import ScorePanel from "./ScorePanel";export default class GameControl {snake: Snakefood: FoodscorePanel: ScorePaneldircter = '' // 保存按键的值constructor() {this.snake = new Snake()this.food = new Food()this.scorePanel = new ScorePanel()this.init()}// 初始化操作,监听按键事件init() {// 第二个参数如果不写bind(this),那调用的函数中的this就是document,而不是类的实例化对象document.addEventListener("keydown", this.keydownHandler.bind(this))this.run()}// 按键的回调函数keydownHandler(event: KeyboardEvent) {this.dircter = event.key}run() {// 蛇头的原坐标let x = this.snake.Xlet y = this.snake.Y// 按下按键后,4个方向中某一个方向的坐标需要修改switch (this.dircter) {case 'ArrowUp':case 'Up':y = y - 10break;case 'ArrowDown':case 'Down':y = y + 10breakcase 'ArrowLeft':case 'Left':x = x - 10breakcase 'ArrowRight':case 'Right':x = x + 10break}// 蛇头下一步是不是撞墙了if (x < 0 || x > 290 || y < 0 || y > 290) {alert("蛇撞墙了")return// 检测蛇头是否撞到自己} else if (!this.snake.checkHandBody()) {alert('你咬到自己尾巴了')return} else {this.eachFood()// 同一时间只可能有一个轴的位置发生改变if (this.snake.Y === y) {this.snake.X = x}else if (this.snake.X === x) {this.snake.Y = y}// 开启定时器,随着等级的升高,蛇的移动速度越来越快let time = this.scorePanel.level * 50setTimeout(this.run.bind(this), 250 - time)}}// 检测蛇是否吃到食物,吃到食物后:新增食物,增加积分,增加蛇的身体eachFood() {if (this.snake.X === this.food.X && this.snake.Y === this.food.Y) {this.food.change()this.scorePanel.addScore()this.snake.addBody()}}}
- /modules/Food.ts
class Food{element:HTMLElementconstructor() {this.element = document.getElementById('food')!this.change()}// 获取食物坐标get X(){return this.element.offsetLeft}get Y(){return this.element.offsetTop}// 设置食物坐标set X(value ){this.element.style.left = value + 'px'}set Y(value){this.element.style.top = value + 'px'}// 随机在地图上新增食物change(){let top = Math.round(Math.random()*29) *10let left = Math.round(Math.random()*29) *10this.X = leftthis.Y = top}
}export default Food// const a = new Food()
// console.log(a.X,a.Y);
// a.change()
// console.log(a.X,a.Y);
4. 配置文件
- package.json
{"name": "part2","version": "1.0.0","description": "","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1","build": "webpack","start": "webpack serve --open"},"keywords": [],"author": "","license": "ISC","devDependencies": {"@babel/core": "^7.23.3","@babel/preset-env": "^7.23.3","babel-loader": "^9.1.3","clean-webpack-plugin": "^4.0.0","core-js": "^3.33.3","css-loader": "^6.8.1","html-webpack-plugin": "^5.5.3","less": "^4.2.0","less-loader": "^11.1.3","postcss": "^8.4.31","postcss-loader": "^7.3.3","postcss-preset-env": "^9.3.0","style-loader": "^3.3.3","ts-loader": "^9.5.1","typescript": "^5.3.2","webpack": "^5.89.0","webpack-cli": "^5.1.4","webpack-dev-server": "^4.15.1"}
}
- tsconfig.json
{"compilerOptions": {"module": "ES6","target": "ES6","strict": true,"noEmitOnError": true},
}
- webpack.config.js
// 引入一个包
const path = require('path')
const HTMlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
// webpack中的所有的配置信息都应该写在moudle.exports中
module.exports = {// 当前为开发模式mode: 'development',// 指定入口文件entry: "./src/index.ts",// 打包文件的设置项output: {// 打包后文件的目录path: path.resolve(__dirname,'dist'),// 打包后文件的名字filename: "bundle.js",// 打包后文件不使用箭头函数,不使用constenvironment: {arrowFunction: false,const:false},},// 指定webpack打包时要使用的模块module: {// 指定要加载的规则rules: [{// test指定的是规则生效的文件test: /\.ts$/,// 要使用的loaderuse: [// 将新版本的js转换为旧版本的js,提高代码的兼容性{// 指定加载器loader:'babel-loader',// 设置上面这个加载器的配置项options: {// 设置预定义的环境(代码要在那些浏览器中运行)presets: [['@babel/preset-env',{// 要兼容的目标浏览器targets:{// 'chrome':'88','ie':'10'},// 指定corejs的版本'corejs':'3',// 使用corejs的方式:usage 按需加载'useBuiltIns':'usage'}]]}},'ts-loader', // 将ts转换为js],// 要排除的文件exclude: /node_moudles/},// 设置less文件的处理{test: /\.less$/,use: ["style-loader","css-loader",{loader: "postcss-loader",options: {postcssOptions:{plugins: [["postcss-preset-env",{browsers:"last 2 versions"}]]}}},"less-loader"]}]},// 插件plugins: [// 自动生成html文件,并且引入相关资源new HTMlWebpackPlugin({// 自动生成的网页以路径中的网页为模板template: "./src/index.html"}),// 自动清除上次编译后的文件new CleanWebpackPlugin(),],// 设置那些文件可以作为模块可以被引用resolve: {extensions: ['.ts','.js']}
}
相关文章:
TypeScript 学习笔记 第三部分 贪吃蛇游戏
尚硅谷TypeScript教程(李立超老师TS新课) 1. 创建开发环境 创建工程,使用学习笔记的第二部分安装css部分 npm i -D less less-loader css-loader style-loader对css部分处理,能够运行在低版本浏览器 npm i -D postcss postcss…...
【spring(一)】核心容器总结
🌈键盘敲烂,年薪30万🌈 目录 IOC 配置bean对象: DI 注入bean对象 ①.setter方法注入 ②.构造器注入 Bean的实例化 1.setter方法注入(重点) 2.静态工厂(了解) 3.实例工厂(了解࿰…...
易点易动固定资产管理系统:实现全面的固定资产采购管理
在现代企业中,固定资产采购管理是一项关键的任务。为了确保企业的正常运营和发展,有效管理和控制固定资产采购过程至关重要。易点易动固定资产管理系统为企业提供了一种全面的解决方案,整合了从采购需求、采购计划、询比价、采购合同到采购执…...
力扣:178. 分数排名(Python3)
题目: 表: Scores ---------------------- | Column Name | Type | ---------------------- | id | int | | score | decimal | ---------------------- 在 SQL 中,id 是该表的主键。 该表的每一行都包含了一场比赛的分数。Score …...
raid磁盘阵列
在单机时代,采用单块磁盘进行数据存储和读写的方式,由于寻址和读写的时间消耗,导致I/O性能非常低,且存储容量还会受到限制。另外,单块磁盘极其容易出现物理故障,经常导致数据的丢失。此时,RAID技…...
SpringBoot学习笔记-实现微服务:匹配系统(上)
笔记内容转载自 AcWing 的 SpringBoot 框架课讲义,课程链接:AcWing SpringBoot 框架课。 CONTENTS 1. 配置WebSocket2. 前后端WebSocket通信2.1 WS通信的建立2.2 加入JWT验证 3. 前后端匹配业务3.1 实现前端页面3.2 实现前后端交互逻辑3.3 同步游戏地图 …...
重磅!全球首个“绿色黑灯工厂”落户中国,竟然是这家企业……
作者:叶蓁 “52”、“白加黑”、“无人看守作业”,这是九牧“绿色黑灯工厂”的几大关键词。 九牧绿色黑灯工厂不仅是单体产量最大的工厂,也是全球首个入选的“绿色黑灯工厂”。 11月17日,中国节能协会授予九牧5G智能马桶工厂全球…...
go语言学习-异常处理
1、异常场景 网络故障硬件故障组件故障输入错误逻辑错误链路调度错误 2、异常处理方式 # python或者java异常处理 try 可能出现的错误 catch对错误进行处理 xxx,err : 代码 if err ! nil {代码出现错误,需要做处理 }3、自定义错误 有两种方法:1、通过…...
如何使用 JavaScript 实现图片上传并转换为 LaTeX 公式
在本教程中,我们将学习如何使用 JavaScript 创建一个上传图片的功能,并将所选图片转换为 LaTeX 公式。我们将使用 FileReader 对象来读取图片并将其转换为 Base64 格式,然后利用 img2latex API 将其转换为 LaTeX 公式。 1. HTML 结构 首先&…...
深刻理解MySQL8游标处理中not found
深刻理解MySQL8游标处理中not found 最近使用MySQL的游标,在fetch循环过程中,程序总是提前退出 ,百思不得其解,经过测试,原来是对于游标处理中not found的定义理解有误,默认是视同Oracle的游标not found定…...
甄知燕千云与SAP、EBS、TC、NS等应用深度集成,智能提单一键畅通,效能一键提升
当今全球化时代下,全球商业环境面临前所未有的机遇和挑战,企业需要持续的业务变革、组织优化来进行降本增效,企业管理软件已成为中小企业、大型企业数字化转型不可或缺的管理工具,企业内管理软件系统也越来越多。 为了适应当前企业…...
第99步 深度学习图像目标检测:SSDlite建模
基于WIN10的64位系统演示 一、写在前面 本期,我们继续学习深度学习图像目标检测系列,SSD(Single Shot MultiBox Detector)模型的后续版本,SSDlite模型。 二、SSDlite简介 SSDLite 是 SSD 模型的一个变种,…...
用EasyAVFilter将网络文件或者本地文件推送RTMP出去的时候发现CPU占用好高,用的也是vcodec copy呀,什么原因?
最近同事在用EasyAVFilter集成在EasyDarwin中做视频拉流转推RTMP流的功能的时候,发现怎么做CPU占用都会很高,但是视频没有调用转码,vcodec用的就是copy,这是什么原因呢? 我们用在线的RTSP流就不会出现这种情况&#x…...
Vatee万腾科技的独特力量:Vatee数字时代创新的新视野
在数字化时代的浪潮中,Vatee万腾科技以其独特而强大的创新力量,为整个行业描绘了一幅崭新的视野。这不仅是一场科技创新的冒险,更是对未来数字时代发展方向的领先探索。 Vatee万腾将创新视为数字时代发展的引擎,成为推动行业向前的…...
【JavaSE】基础笔记 - 异常(Exception)
目录 1、异常的概念和体系结构 1.1、异常的概念 1.2、 异常的体系结构 1.3 异常的分类 2、异常的处理 2.1、防御式编程 2.2、异常的抛出 2.3、异常的捕获 2.3.1、异常声明throws 2.3.2、try-catch捕获并处理 3、自定义异常类 1、异常的概念和体系结构 1.1、异常的…...
QTableWidget——编辑单元格
文章目录 前言熟悉QTableWiget,通过实现单元格的合并、拆分、通过编辑界面实现表格内容及属性的配置、实现表格的粘贴复制功能熟悉QTableWiget的属性 一、[单元格的合并、拆分](https://blog.csdn.net/qq_15672897/article/details/134476530?spm1001.2014.3001.55…...
编译QT Mysql库并集成使用
安装MSVC编译器与Windows 10 SDK 打开Visual Studio Installer,如果已经安装过内容了可能是如下页面,点击修改(头一回打开的话不需要这一步): 然后在工作负荷中勾选使用C的桌面开发,它会帮我们勾选好一些…...
利用企业被执行人信息查询API保障商业交易安全
前言 在当今竞争激烈的商业环境中,企业为了保障商业交易的安全性不断寻求新的手段。随着技术的发展,利用企业被执行人信息查询API已经成为了一种强有力的工具,能够帮助企业在商业交易中降低风险,提高合作的信任度。 企业被执行人…...
【深度学习】P1 深度学习基础框架 - 张量 Tensor
深度学习基础框架 张量 Tensor 张量数据操作导入创建张量获取张量信息改变张量张量运算 张量与内存 张量 Pytorch 是一个深度学习框架,用于开发和训练神经网络模型。 而其核心数据结构,则是张量 Tensor,类似于 Numpy 数组,但是可…...
vue2 识别页面参数中的html
在Vue 2中,你可以使用v-html指令来识别页面参数中的HTML内容。v-html指令允许你将HTML代码作为Vue模板的一部分进行渲染。 以下是一个示例,演示了如何在Vue 2中使用v-html指令来识别页面参数中的HTML内容: <template><div v-html&…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
