TypeScript 学习笔记 第三部分 贪吃蛇游戏

尚硅谷TypeScript教程(李立超老师TS新课)

1. 创建开发环境

  1. 创建工程,使用学习笔记的第二部分
  2. 安装css部分
npm i -D less less-loader css-loader style-loader
  1. 对css部分处理,能够运行在低版本浏览器
npm i -D postcss postcss-loader postcss-preset-env
  1. 修改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']}
}

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

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

相关文章

音色逼真、韵律自然的AI人声克隆限时福利!

声音&#xff0c;为数字人注入灵魂。 2023云栖大会上&#xff0c;阿里云视频云接受了CCTV-2财经频道的采访&#xff0c;分享并演示了如何利用云端智能剪辑&#xff0c;一站式完成数字人渲染及视频精编二创。 正如视频开头所呈现的AI重现演员“原声”&#xff0c;近年来&#x…

基于SpringBoot的图书管理系统

基于SpringBoot的图书管理系统 图书管理系统开发技术功能模块代码结构数据库设计运行截图源码获取 图书管理系统 开发技术 技术&#xff1a;SpringBoot、MyBatis-Plus、MySQL、Beetl、Layui。 框架&#xff1a;基于开源框架Snowy-Layui开发。 工具&#xff1a;IDEA、Navicat等…

【Linux】进程间通信——进程间通信的介绍和分类、管道、匿名管道、命名管道、匿名管道与命名管道的区别

文章目录 进程间通信1.进程间通信的介绍1.1目的和发展 2.进程间通信分类3.管道3.1匿名管道3.1.1匿名管道的原理&#xff08;文件角度&#xff09;3.1.2匿名管道的原理&#xff08;内核角度&#xff09;3.1.3管道读写规则3.1.4管道特点 3.2命名管道3.2.1创建命名管道3.2.2命名管…

谈思生物医疗直播 | 利用类器官模型研究肺的发育与稳态

类器官是一种三维细胞培养物&#xff0c;其在细胞类型&#xff0c;空间结构及生理功能上能够模拟对应器官&#xff0c;从而提供一个高度生理相关的系统。自2009年小肠类器官首次建立至今&#xff0c;类器官研究已经延伸到多个组织系统&#xff0c;并成为当下生命科学领域最热门…

美创获IDC数据库安全市场代表厂商推荐,一路引领数据库安全

近日&#xff0c;全球领先的IT市场研究和咨询公司IDC发布《IDC Persepctive&#xff1a;中国数据库安全市场洞察&#xff0c;2023》报告。 凭借多年的技术积累和丰富的产品体系与行业实践&#xff0c;美创科技获「代表厂商」推荐&#xff0c;再次彰显专业领先能力&#xff01; …

Mybatis一级缓存和二级缓存原理剖析与源码详解

Mybatis一级缓存和二级缓存原理剖析与源码详解 在本篇文章中&#xff0c;将结合示例与源码&#xff0c;对MyBatis中的一级缓存和二级缓存进行说明。 MyBatis版本&#xff1a;3.5.2 文章目录 Mybatis一级缓存和二级缓存原理剖析与源码详解⼀级缓存场景一场景二⼀级缓存原理探究…

部署项目时常用的 Linux 命令

目录 1 前言2 SSH登录命令3 SCP传输命令4 CP拷贝命令5 MV移动命令6 TAR解压命令7 DU查看文件夹/文件大小8 TAIL查看日志9 NOHUP后台运行10 结语 1 前言 在应用部署过程中&#xff0c;Linux命令是必不可少的工具。它们能够帮助我们管理文件、连接服务器、拷贝文件、查看日志以及…

vite项目配置vite.config.ts在打包过程中去除日志

在生产环境上&#xff0c;务必要将日志清除干净&#xff0c;其因有二&#xff0c;在webgis系统中&#xff0c;有很多几何数据&#xff0c;体积大、数量多&#xff0c;很容易引起系统卡顿&#xff1b;清除log后&#xff0c;系统看着舒服&#xff0c;协同开发有很多无聊的日志&am…

一款非常优秀的项目管理工具:进度猫(推荐)

在项目管理中&#xff0c;一个好的工具可以极大地提高效率。 进度猫是一款非常优秀的项目管理工具。它具有非常强大的功能&#xff0c;可以帮助团队更好地管理项目进度。 通过可视化的方式&#xff0c;将项目进度、任务分配、需求变更等全面呈现给团队成员&#xff0c;让团队…

需求分析BSA法

&#x1f449;BSA法&#xff08;Basic–Satisfier–Attractor&#xff09;是对客户需求进行优先级划分的需求分析方法。该模型体现了需求满足度和客户满意度之间的非线性关系。BSA法将客户需求分为3种类型&#xff0c;分别是基本型需求、满意型需求和兴奋型需求。下面将对每种需…

ABB机 器 人 操 作 培 训

目 录 1 培训手册介绍 ---------------------------------------------2 2 系统安全与环境保护 ---------------------------------------------3 3 机器人综述 ---------------------------------------------5 4 机器人示教 --------------------------------------------12…

FSCTF2023-Reverse方向题解WP。学习贴

文章目录 [FSCTF 2023]signin[FSCTF 2023]MINE SWEEPER[FSCTF 2023]Xor[FSCTF 2023]EZRC4[FSCTF 2023]ez_pycxor[FSCTF 2023]Tea_apk[FSCTF 2023]ezcode[FSCTF 2023]ezbroke[FSCTF 2023]rrrrust!!![FSCTF2023]ezrev&#xff08;未解决&#xff09; [FSCTF 2023]signin UPX壳&am…

redis-cluster集群模式

Redis-cluster集群 1 Redis3.0引入的分布式存储方案 2集群由多个node节点组成,redis数据分布在节点之中,在集群之中分为主节点和从节点3集群模式当中,主从一一对应,数据写入和读取与主从模式一样&#xff0c;主负责写&#xff0c;从只能读4集群模式自带哨兵模式&#xff0c;可…

自然资源土地管理法律法规知识竞赛这么办才高端

近些年&#xff0c;全国各地自然资源厅举办了土地管理法律法规知识竞赛&#xff0c;从我公司承办的这些赛事来看&#xff0c;传统的必答题、抢答题、风险题的方式已无法激起现场比赛气氛&#xff0c;需要更加复杂有趣的环节设置及高端竞赛软件及其配套设备加持才可以让知识竞赛…

什么是交易量价差分析法?anzo Capital一分钟讲明白

交易量价差分析法是一种深入的市场分析方法&#xff0c;它主要探讨了价格、价差和交易量之间的相互关系。在此过程中&#xff0c;交易量主要揭示了市场上的交易活动情况&#xff0c;而价差则反映了这些交易的价格变动。 为了更准确地理解这种关系&#xff0c;定义了交易量价差…

单元测试-java.lang.NullPointerException

报错信息 java.lang.NullPointerException 空指针异常 空对象引用 来源 对Controller层进行单元测试&#xff0c;解决完Spring上下文报错后继续报错。 解决 在测试方法执行前要为字段完成对象的注入&#xff0c;否则就报空指针异常。 测试例子 public class SysUserContr…

前端css粘性布局,顶部吸附效果(position: sticky)

sticky属性设置 /* 设置粘性布局 */ position: sticky; /* 拖动滚动条&#xff0c;当前元素超出文档0的位置时&#xff0c;触发定位效果&#xff08;同级元素位置不会受影响&#xff09; */ top: 0;页面初始效果 设置前&#xff08;滚动页面时&#xff0c;标签栏随页面滚动&a…

【深度学习】六大聚类算法快速了解

在机器学习中&#xff0c;无监督学习一直是我们追求的方向&#xff0c;而其中的聚类算法更是发现隐藏数据结构与知识的有效手段。目前如谷歌新闻等很多应用都将聚类算法作为主要的实现手段&#xff0c;它们能利用大量的未标注数据构建强大的主题聚类。本文从最基础的 K 均值聚类…

【二叉树进阶题目】236. 二叉树的最近公共祖先,JZ36 二叉搜索树与双向链表

二叉树进阶题目 236. 二叉树的最近公共祖先解题思路及实现思路一思路二 JZ36 二叉搜索树与双向链表描述解题思路及实现 236. 二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个…

Axios 拦截器 请求拦截器 响应拦截器

请求拦截器 相当于一个关卡&#xff0c;如果满足条件就放行请求&#xff0c;不满足就拦截 响应拦截器 在处理结果之前&#xff0c;先对结果进行预处理&#xff0c;比如&#xff1a;对数据进行一下格式化的处理 全局请求拦截器 axios.interceptors.request.use(config > { /…