用 typescript 做一个贪吃蛇小游戏
Posted 新时代农民工Top
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用 typescript 做一个贪吃蛇小游戏相关的知识,希望对你有一定的参考价值。
typescript 做一个贪吃蛇小游戏
搭建环境
创建 tscofig.json 文件
配置如下
"compilerOptions":
"target": "es2015",
"module": "es2015",
"strict": true,
"outDir": "./dist",
"noEmitOnError": true
创建 webpack.config.js 文件
-
安装 webpack
npm i webpack webpack-cli -D
-
配置
配置 webpack 项目工程化,配置项目运行打包,兼容,处理 .ts .css .less html 文件 -
安装插件
npm i html-webpack-plugin webpack-dev-server -D
webpack-dev-server 作用
webpack 内部服务器,可以在开发阶段项目自动运行,比如修改了代码,会检测到改动并且自动运行,不需要每次都手动运行查看,利于开发效率
html-webpack-plugin
html 插件,可用来提供 html 模板,打包后的 dist 文件中的 html 会根据这个模板生成
配置如下
const path = require('path')
// html 插件
const HtmlWebpackPlugin = require('html-webpack-plugin')
const htmlPlugin = new HtmlWebpackPlugin(
template: './src/index.html',
filename: './index.html'
)
module.exports =
mode: 'development',
entry: './src/index.ts',
output:
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
environment:
// 兼容 IE ,禁止使用箭头函数
arrowFunction: false,
// 兼容 IE ,禁止使用es6语法
const: false
,
module:
rules: [
test: /\\.ts$/,
use: [
// 配置babel
// 指定加载器
loader: 'babel-loader',
// 设置 babel
options:
// 设置预定义环境
presets: [
[
// 指定环境插件
"@babel/preset-env",
// 配置信息
// 要兼容的目标浏览器
targets:
"chrome": "58"
,
// 指定 corejs 版本
"corejs": "3",
// 使用 corejs 的方式"usage"表示按需加载
"useBuiltIns": "usage"
]
]
, 'ts-loader'
],
exclude: /node_modules/
,
test: /\\.less$/,
use: [
"style-loader",
"css-loader",
// 引入 postcss
loader: "postcss-loader",
options:
postcssOptions:
plugins: [
[
"postcss-preset-env",
browsers: 'last 2 versions'
]
]
,
"less-loader"
]
]
,
plugins: [htmlPlugin],
resolve:
extensions: ['.ts', '.js']
创建 package.json 文件
在项目名称是英文的情况下使用
npm init -y
如果项目名称不是英文,使用如下命令,给它设置一个英文名称
npm init
安装项目所需的全部开发依赖,如下
配置就说这么多,下面开始项目代码
采用的是结构与数据分离
先布局基本样式
在项目根目录下创建 src 文件夹,在src 文件夹下创建 index.html 和 index.ts 文件
./src/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>贪吃蛇</title>
</head>
<body>
<div class="box">
<div class="top">
// 蛇
<div id="snake">
// 蛇的每一节
<div></div>
</div>
// 食物
<div id="food"></div>
</div>
// 记分牌
<div class="bottom">
<div>SCORE:<span id="score">3</span></div>
<div>LEVEL:<span id="level">1</span></div>
</div>
</div>
</body>
</html>
在 src 目录下创建 style 文件夹存放样式文件 index.less
*
margin: 0;
padding: 0;
box-sizing: border-box;
body
font: bold 20px "Courier";
.box
width: 360px;
height: 420px;
background-color: #b7d4a8;
border: 10px solid #000;
margin: 100px auto;
border-radius: 20px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;
.top
width: 304px;
height: 304px;
border: 2px solid #000;
position: relative;
.bottom
width: 304px;
display: flex;
justify-content: space-between;
#snake
position: relative;
#snake div
width: 10px;
height: 10px;
background-color: black;
border: 1px solid #b7d4a8;
position: absolute;
top: 0;
left: 0;
#food
width: 10px;
height: 10px;
background-color: black;
position: absolute;
border: 1px solid #b7d4a8;
在 index.ts 文件中引入样式
import './style/index.less'
- 不要忘记安装 less
开始业务逻辑代码
在 src 文件下创建 modules 文件夹,存放每个类
Food.ts , 控制食物随机出现的位置
class Food
// 定义一个属性表示事物所对应的元素
element: HTMLElement
constructor()
// !感叹号的意思是不用管
this.element = document.getElementById('food')!
// 定义一个获取食物X轴坐标的方法
get X()
return this.element.offsetLeft
// 定义一个获取食物Y轴坐标的方法
get Y()
return this.element.offsetTop
// 修改十五位置的方法
change()
// 生成一个随机数
// 食物的位置最小时0,最大是290
// Math.round(Math.random() * 29) * 10
this.element.style.top = Math.round(Math.random() * 29) * 10 + 'px'
this.element.style.left = Math.round(Math.random() * 29) * 10 + 'px'
// let food = new Food()
// food.change()
// console.log(food.X, food.Y)
export default Food
创建 ScorePanel.ts,控制记分牌的变化
// 定义记分牌
class ScorePanel
// score, level 记录分数和等级
score = 0
level = 1
// 分数和等级初始化
scoreEle: HTMLElement
levelEle: HTMLElement
// shezhibianliang
maxLevel: number
maxScore: number
constructor(maxLevel: number = 10, maxScore: number = 10)
this.scoreEle = document.getElementById('score')!
this.levelEle = document.getElementById('level')!
this.maxLevel = maxLevel
this.maxScore = maxScore
// 设置加分的方法
addScore()
this.score++
this.scoreEle.innerHTML = this.score + ''
if (this.score % this.maxScore === 0)
this.levelUp()
// 提升等级的方法
levelUp()
if (this.level < this.maxLevel)
this.level++
this.levelEle.innerHTML = this.level + ''
export default ScorePanel
创建 Snake.ts,控制蛇的长度/位置/是否撞墙或者撞到自己
class Snake
// 表示蛇头的元素
head: HTMLElement
// 蛇的身体
bodies: HTMLCollection
element: HTMLElement
constructor()
this.element = document.getElementById('snake')!
this.head = document.querySelector('#snake > div')!
this.bodies = this.element.getElementsByTagName('div')
// 获取蛇的坐标
get X()
return this.head.offsetLeft
get Y()
return this.head.offsetTop
// 设置蛇头的坐标
set X(value: number)
if (this.X === value) return
// 判断是否撞墙 X值的合法范围
if (value < 0 || value > 290)
// 蛇撞墙了抛出异常
throw new Error("蛇撞墙了");
// 修改水平座标蛇向右走不能往左走
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'
// 检查有没有撞到自己
this.checkHeadBody()
set Y(value: number)
if (this.Y === value) return
if (value < 0 || value > 290)
throw new Error("蛇撞墙了");
// 修改水平座标蛇向右走不能往左走
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'
// 检查有没有撞到自己
this.checkHeadBody()
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';
checkHeadBody()
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)
throw new Error("撞到自己了");
export default Snake
创建 GameControl.ts,控制蛇的移动,把蛇、食物、记分牌联系到一块
import Snake from "./snake";
import Food from "./food";
import ScorePanel from "./ScorePanel";
class GameControl
// 定义三个属性
// 蛇
snake: Snake
food: Food
scorePanel: ScorePanel
// c创建一个属性来存储蛇的移动方向
direction: string = 'Right'
// 创建一个属性用来记录游戏是否结束
isLive: boolean = true
constructor()
this.snake = new Snake()
this.food = new Food()
this.scorePanel = new ScorePanel()
this.init()
// 游戏初始化方法
init()
// 绑定键盘事件
// 修改this指向
document.addEventListener('keydown', this.keydownHandler.bind(this))
// 调用 run 方法
this.run()
// 创建键盘按下的函数
keydownHandler(e: KeyboardEvent)
// 修改 dirention 的值
this.direction = e.key
// 创建控制蛇移动的方法
run()
// 根据方向来改变蛇的位置
// 获取蛇现在的坐标
let X = this.snake.X
let Y = this.snake.Y
switch (this.direction)
case "ArrowUp":
case "Up":
Y -= 10
break;
case "ArrowDown":
case "Down":
Y += 10
break;
case "ArrowRight":
case "Right":
X += 10
break;
case "ArrowLeft":
case "Left":
X -= 10
break;
default:
break;
this.checkEat(X, Y)
try 以上是关于用 typescript 做一个贪吃蛇小游戏的主要内容,如果未能解决你的问题,请参考以下文章