网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
控制模块需求
- 按下方向键开始游戏
- 只能通过四个方向键改变蛇前进的方向
- 判断游戏是否结束,蛇是否吃到食物
- 控制分数和等级是否相应增长,食物是否刷新
项目搭建
ts转译为js代码
我们需要创建tsconfig.json
文件,文件代码如下:
{
"compilerOptions": {
"module": "es6",
"target": "es6",
"strict": true,
"noEmitOnError": true
}
}
package.json包配置文件
- 在这个小项目中我们需要webpack打包工具,所以我们要对
package.json
文件进行一些配置。 - 选择该项目在集成终端中打开并输入代码
npm init -y
进行项目初始化,这个时候会在你的项目中生成一个初步的package.json文件,然后我们进一步完善 - 在集成终端中输入指令
npm i -D webpack webpack-cli typescript ts-loader
用来下载相关依赖(如果可以看见package.json的depDependencies中更新了你下载的依赖表示下载成功)。i表示install下载的意思,-D意思是下载的作为依赖使用 - 继续输入指令npm i -D css-loader 等依赖,这些后面都有用
- 请注意上述代码中scripts中的"build": "webpack"键值对,这个设置说明我们可以用npm run build的代码来启用webpack打包工具
{
"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.18.9",
"@babel/preset-env": "^7.18.9",
"babel-loader": "^8.2.5",
"clean-webpack-plugin": "^4.0.0",
"core-js": "^3.24.0",
"css-loader": "^6.7.1",
"html-webpack-plugin": "^5.5.0",
"less": "^4.1.3",
"less-loader": "^11.0.0",
"postcss": "^8.4.14",
"postcss-loader": "^7.0.1",
"postcss-preset-env": "^7.7.2",
"style-loader": "^3.3.1",
"ts-loader": "^9.3.1",
"typescript": "^4.7.4",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.9.3"
}
}
webpack.config.js打包工具配置
webpack打包文件配置中,代码注释非常清楚,代码如下:
//引入一个包
const path = require('path');
//引入html插件
const HTMLWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
// webpack 中所有的配置信息都写道吗module.exports中
module.exports = {
//指定入口文件
entry: './src/index.ts',
//指定打包文件所在的目录
output: {
//指定打包文件的目录
path: path.resolve(__dirname,'dist'),
//打包后文件的名字
filename: "bundle.js",
//告诉webpack不使用箭头函数
environment: {
arrowFunction: false
}
},
mode: 'development',
//指定webpack打包时要使用的模块
module: {
//指定要加载的规则
rules: [
{
//test指定规则生成的文件
test: /\.ts$/,
//要使用的loader
use : [
//配置babel
{
// 指定加载器
loader: "babel-loader",
//设置babel
options: {
//设置预定义的环境
presets:[
[
//指定环境的插件
"@babel/preset-env",
//配置信息
{
//要兼容的目标浏览器
targets : {
"chrome" : "101"
},
//指定core.js的版本
"corejs":"3",
//使用core.js的方式 usage 按需加载
"useBuiltIns": "usage"
}
]
]
}
}
,
'ts-loader'
],
//要排除的文件
exclude: /node-modules/
},
//设置less文件的处理
{
test : /\.less$/,
use : [
"style-loader",
"css-loader",
//引入postcss
{
loader: "postcss-loader",
options: {
postcssOptions : {
plugins: [
[
"postcss-preset-env",
{
browsers:'last 2 versions'
}
]
]
}
}
},
"less-loader"
]
}
]
},
//配置webpack插件
plugins: [
new CleanWebpackPlugin(),
new HTMLWebpackPlugin({
// title: "自定义的title"
template: "./src/index.html"
}),
],
//用来设置引用模块
resolve: {
extensions: ['.ts', '.js']
}
}
到这里,我们要配置的文件都已经配置结束,接下来正式进入项目的开发
项目结构搭建
首先要进行我们的html和css样式搭建,搭建出来项目的页面!
html文件
<!DOCTYPE html>
<html lang="en">
<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">
<!--添加四个小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>
css文件(这里使用的是less)
// 设置变量
@bg-color: #b7d4a8;
//清除默认样式
\* {
margin: 0;
padding: 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;
// 设置侧轴的对齐方式
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-between;
&>div{
width: 4px;
height: 4px;
background-color: black;
// 使四个div旋转45度
transform: rotate(45deg);
}
}
}
// 记分牌
#score-panel{
width: 300px;
display: flex;
// 设置主轴的对齐方式
justify-content: space-between;
}
}
项目页面
多模块搭建
在项目开发中我们不可能把所有的代码写到一个文件中,所以项目开发必须会灵活运用模块化
开发思想,把实现的功能细化成一个个模块。
完成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 最大是290
let left = Math.round(Math.random() \* 29) \* 10
let top = Math.round(Math.random() \* 29) \* 10
this.element.style.left = left + 'px';
this.element.style.top = top + 'px';
}
}
export default Food
代码分析:
- 由于在配置typescript时我们设置了strict(严格)模式,因此
this.element = document.getElementById('food')!
中如果我们不加!
会让编译器不确定我们是否会获取到food的dom元素而发生报错 - 准备了
get()
方法可以在控制模块中随时获取food的具体定位 change()
方法为随机刷新一次food的位置export default Food
代码加在最后。为的是把food成为全局模块暴露出去,这样的话其他的模块可以调用这个food模块
完成ScorePanel(记分牌)类
//定义表示记分牌的类
class ScorePanel {
score : number = 0;
level : number = 1;
scoreSpan :HTMLElement;
levelEle : HTMLElement;
//设置变量限制等级
maxLevel : number;
//设置一个变量多少分升级
upScore : number;
constructor(maxLevel : number = 10,Score : number = 10) {
this.scoreSpan = document.getElementById('score')!;
this.levelEle = document.getElementById('level')!;
this.maxLevel = maxLevel
this.upScore = Score
}
//设置加分的方法
AddScore() {
this.score++;
this.scoreSpan.innerHTML = this.score + ''
if (this.score % this.upScore === 0 ) {
this.AddLevel()
}
}
//提升等级
AddLevel() {
if (this.level < this.maxLevel) {
this.levelEle.innerHTML = ++this.level +''
}
}
}
export default ScorePanel
代码分析:
在记分牌模块主要是两种方法AddScore()
和AddLevel()
,分别用来控制分数增加和等级提升,重点也有设置一个变量来限制等级和设置变量来判断多少分上升一个等级
完成Snake(蛇)类
class Snake {
//表示蛇头的元素
head : HTMLElement;
bodies : HTMLCollectionOf<HTMLElement>;
//获取蛇的容器
element : HTMLElement;
constructor() {
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) {
if(this.X === value) {
![img](https://img-blog.csdnimg.cn/img_convert/4fc9a4023babb8246199f0195fae4d8b.png)
![img](https://img-blog.csdnimg.cn/img_convert/35b4135a01e5002b6210f8b97d183ce9.png)
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
X() {
return this.head.offsetLeft;
}
get Y() {
return this.head.offsetTop;
}
set X(value) {
if(this.X === value) {
[外链图片转存中...(img-HQKwve2Z-1715262211969)]
[外链图片转存中...(img-7mQGqFvB-1715262211970)]
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**