TS项目《贪吃蛇》
本文最后更新于:2023年7月19日 晚上
一、项目简介
在Web端,利用Html、CSS、Typescript语言,实现贪吃蛇游戏的功能
界面的搭建 HTML、CSS
系统功能的完成
- 类型:蛇的实现
- 蛇(头)的坐标
- 移动功能
- 转向功能
- 蛇身体变长功能
- 检测蛇是否撞到墙的功能
- 检测蛇是否撞到自己的功能
- 类型:记分板的实现
- 分数增加功能
- 等级(难度)增加功能
- 类型:食物的实现
- 随机生成食物坐标功能
- 类型:游戏控制的实现(核心类)
- 游戏初始化功能
- 键盘按下的响应功能
- 根据键盘响应改变蛇的方向功能
- 检测是否吃到食物功能
- 类型:蛇的实现
二、界面搭建
1 | |
问题:div下嵌套div,下面的DOM的获取方式没见过
1 | |
三、系统功能的完成
1. 蛇类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96class Snake {
//表示蛇头的元素
head: HTMLElement
//蛇的身体,包括蛇头
bodies: HTMLCollection
//获取蛇的容器
element: HTMLElement
constructor() {
this.element = document.getElementById('snake')! //获取蛇在html中的容器标签
this.head = document.querySelector('#snake > div') as HTMLElement //获取蛇头 #snake下的div标签
// <div id="snake">
// <div></div> //‘#snake > div 获取的就是这个,id是snake,子元素 div标签
//</div>
this.bodies = this.element.getElementsByTagName('div')! //获取所有的div蛇身 //获取蛇下的所有div
}
//获取蛇头的坐标
get X() {
return this.head.offsetLeft //距离左边的距离
}
get Y() {
return this.head.offsetTop //距离上边的距离
}
//设置蛇头坐标 构造函数
set X(value: number) {
if (this.X === value) {
return
}
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>")
//在结束标签之前的位置插入一个HTML 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++) {
let bd = this.bodies[i] as HTMLElement
if (this.X === bd.offsetLeft && this.Y === bd.offsetTop) {
throw new Error('撞到自己了')
}
}
}
}
export default Snake; //最后记得把类暴露出去 后面就可以import
补充:get和set (C#都忘光了。。。)
1
2
3
4
5
6
7
8
9
10
11
12class person{
private _name:string = '' //私有属性,外部访问不到
constructor(){}
public get name(){ //get 使得该类具有了访问name属性的方法 ,后面就可以直接 person.name
return this._name //实现的对私有属性的“访问”
}
public set name(inputName:string){
this._name = inputName //实现对私有属性赋值
}
}
2.得分窗口类
1 | |
3.食物类
1 | |
4.游戏控制类
```typescript //控制其他的所有类 //引入其他类 import Snake from "./snake"; import Food from "./food"; import ScorePanel from "./scorePanel";
class GameControl { //定义三个属性 snake: Snake; food: Food; scorePanel: ScorePanel; //创建属性 存储蛇的移动方向(按键方向) direction: string = ""; //创建属性 记录游戏是否结束 isLive = true; constructor() { this.snake = new Snake(); this.food = new Food(); this.scorePanel = new ScorePanel(); this.init(); }
//游戏的初始化方法,调用后游戏开始 init() { document.addEventListener("keydown", this.keyDownloadHandler.bind(this)); this.run();
} //创建一个键盘按下的响应函数 keyDownloadHandler(event: KeyboardEvent) { //赋值之前需要检查方向 event.key 用户是否按了正确的按键 this.direction = event.key; //用户按下按键的时候,方向值存到direction中
}
run() { //根据方向,使得蛇的位置改变 //向上 top值减小 向下 top值增加 左left减少 右 left增加 //获取蛇现在的坐标 let X = this.snake.X; let Y = this.snake.Y; //根据按键的方向修改 X Y switch (this.direction) { case "ArrowUp": case "Up": Y -= 10; break; case "ArrowDown": case "Down": Y += 10; break; case "ArrowLeft": case "Left": X -= 10; break; case "ArrowRight": case "Right": X += 10; break; }
this.checkEat(X, Y)
try {
this.snake.X = X;
this.snake.Y = Y;
} catch (error) {
alert(error)
this.isLive = false
}
//开启定时调用
this.isLive && setTimeout(this.run.bind(this), 100 - (this.scorePanel.level - 1) * 10);
}
//检查蛇是否吃到了食物 checkEat(X: number, Y: number) { if (X === this.food.X && Y === this.food.Y) { console.log('吃到食物') //食物的位置要重置 this.food.change() this.scorePanel.addScore() this.snake.addBody() }
} }
export default GameControl;