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,一经查实,立即删除!

相关文章

oracle rac 19c修改不同网段public ip

客户需求将才搭建的oracle 19.19数据库从192.168.168.0网段调整到192.168.213网段 1.停止两个节点集群 停止之前最好ocrdump一下&#xff0c;防止有问题 crsctl stop crs 2.修改public ip地址和/etc/hosts 3. 启动crs 这时集群可以启动&#xff0c;但是上面的一些资源启动会…

音色逼真、韵律自然的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命名管…

PTA-列出所有祖先结点

对于给定的二叉树&#xff0c;本题要求你按从上到下顺序输出指定结点的所有祖先结点。 输入格式: 首先第一行给出一个正整数 N&#xff08;≤10&#xff09;&#xff0c;为树中结点总数。树中的结点从 0 到 N−1 编号。 随后 N 行&#xff0c;每行给出一个对应结点左右孩子的…

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

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

element plus 使用细节

菜鸟一直在纠结这个写不写&#xff0c;因为不难&#xff0c;但是菜鸟老是容易忘记&#xff0c;虽然想想或者搜搜就可以马上写出来&#xff0c;但是感觉每次那样就太麻烦了&#xff0c;不如一股做气写了算了&#xff0c;后面遇见别的就再来补充&#xff01; 文章目录 table 表格…

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

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

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

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

责任链模式 (Chain of Responsibility Pattern)

定义 责任链模式是一种行为型设计模式&#xff0c;用于在对象间建立一条处理请求的链。它允许多个对象有机会处理请求&#xff0c;从而减少请求的发送者和接收者之间的耦合。在责任链模式中&#xff0c;每个接收者包含对另一个接收者的引用&#xff0c;形成一条链。如果一个对…

tcp和 udp区别

相同点&#xff1a;都是传输层协议 不同点 是否面向连接 tcp:面向连接 三次握手&#xff0c;四次挥手端对端连接全双工通信&#xff08;允许双端同时收发数据&#xff09; udp:无连接 无三次握手&#xff0c;四次挥手支持一对一,一对多&#xff0c;多对多 数据传输方式 …

Linux平台下使用.NET Core访问Access数据库

运行环境 操作系统&#xff1a;Ubuntu 22.04.3 LTS (Jammy)开发工具&#xff1a;Visual Studio 2022 (17.8.0)运行时版本&#xff1a;.NET Runtime 8.0依赖库&#xff1a;unixodbc、mdbtools、odbc-mdbtools 依赖库安装 apt-get update sudo apt-get install unixodbc mdbto…

部署项目时常用的 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; 他的预算不超过x元。蛋糕 Cake 和小礼物 gift 都有多种价位的可供选择。 请返回小牛共有多少种购买方案。 输入描述 第一行表示 Cake的单价, 以逗号分隔 …

字符串:leetcode1410. HTML 实体解析器

1410. HTML 实体解析器 「HTML 实体解析器」 是一种特殊的解析器&#xff0c;它将 HTML 代码作为输入&#xff0c;并用字符本身替换掉所有这些特殊的字符实体。 HTML 里这些特殊字符和它们对应的字符实体包括&#xff1a; 双引号&#xff1a;字符实体为 &quot; &#xff…

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

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

5.过滤敏感词 + 发布帖子 + 帖子详情

目录 1.过滤敏感词 1.1 定义前缀树 1.2 根据敏感词,初始化前缀树 1.3 编写过滤敏感词方法

需求分析BSA法

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

ABB机 器 人 操 作 培 训

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