用TS从零开始制作贪吃蛇游戏--3

简介: 本教程基于B站李立超老师的教学,使用VSCode、Less、TypeScript和Webpack开发了一个经典的贪吃蛇游戏。项目包括食物、贪吃蛇、游戏控制和分数管理四个主要类的实现,详细展示了类的定义、属性和方法的使用,以及游戏逻辑的处理。适合初学者学习TypeScript面向对象编程。

本内容学习来自B站李立超老师 原文链接

本项目软件使用vscode,样式文件使用less,面对对象的TS,打包通过webpack进行制作

目录

编写食物类代码

编写贪吃蛇类代码

编写游戏控制类

编写游戏分数类

效果

结语

编写食物类代码

在src文件夹下新建js文件夹,在js文件夹中新建一个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(){
let top = Math.round(Math.random() 29) 10
let left = Math.round(Math.random() 29) 10

this.element.style.top = top + 'px'
this.element.style.left = left + 'px'

}
}

export default Food

编写贪吃蛇类代码

在js文件夹中新建一个snake.ts文件,编写如下代码

class Snake {
head: HTMLElement
bodies: HTMLCollectionOf
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: number) {
if (this.X === value) return
if (value < 0 || value >= 290) {
throw new Error('111')
}
// 判断是否发生了调头
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 (this.Y < 0 || this.Y >= 290) {
throw new Error('111')
}
// 判断是否发生了调头
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', '

')
}

// 移动蛇的身体
moveBody() {
for (let i = this.bodies.length - 1; i > 0; i--) {
// 获取前面身体的位置
console.log(111)
let X = this.bodies[i - 1].offsetLeft
let Y = this.bodies[i - 1].offsetTop

  // 将这个值设置到当前身体上
  this.bodies[i].style.left = X + 'px'
  this.bodies[i].style.top = Y + 'px'
}

}
checkHeadBody() {
// 获取所有的身体 检查是否和蛇头位置重叠
for (let i = 1; i < this.bodies.length; i++) {
if (this.X === this.bodies[i].offsetLeft && this.Y === this.bodies[i].offsetTop) {
// 相撞
throw new Error('蛇身体相撞了')
}
}
}
}

export default Snake

编写游戏控制类

在js文件夹中新建一个GameControl.ts文件,编写如下代码

import Snake from './snake'
import Food from './food'
import ScorePanel from './scorePanel'

class GameControl {
snake: Snake
food: Food
scorePanel: ScorePanel
direction: string = ''
// 游戏是否结束
isLive: boolean = true

constructor() {
this.snake = new Snake()
this.food = new Food()
this.scorePanel = new ScorePanel()
this.init()
}

init() {
document.addEventListener<'keydown'>('keydown', this.keydownHandler.bind(this))
this.run()
this.food.change()
}

keydownHandler(event: KeyboardEvent): void {
this.direction = event.key
}
// 蛇移动
run(): void {
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 '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 (e: any) {
alert(e.message)
this.isLive = false
}
this.isLive &&
setTimeout(() => {
this.run()
}, 100 - (this.scorePanel.level - 1) * 30)
}

// 检查蛇是否吃到食物
checkEat(x: number, y: number): void {
if (x === 0 && y === 0 && this.food.X === 0 && this.food.Y === 0) {
return
}
if (x === this.food.X && y === this.food.Y) {
this.food.change()
this.scorePanel.addScore()
this.snake.addBody()
}
}
}

export default GameControl

编写游戏分数类

在js文件夹中新建一个ScorePanel.ts文件,编写如下代码

class ScorePanel{
score: number = 0
level:number = 1
private maxLevel:number;
private upScore:number;
scoreEle: HTMLElement;
levelEle: HTMLElement;

constructor(maxLevel:number = 10,upScore:number = 10){
this.scoreEle = document.getElementById('score')!
this.levelEle = document.getElementById('level')!
this.maxLevel = maxLevel
this.upScore = upScore
}

// 设置一个加分的方法
addScore(){
this.scoreEle.innerHTML = ++this.score + ''
if(this.score % this.upScore === 0){
this.levelUp( )
}
}
levelUp(){
if(this.level >this.maxLevel) return
this.levelEle.innerHTML = ++this.level + ''
}
}

export default ScorePanel

效果

结语

    这个游戏代码逻辑不难但是能让大家更好的理解ts语言的方便和特点,如果大家对此游戏有问题的话,欢迎大家发私信给我,我会给大家一一解答。

目录
相关文章
|
前端开发 JavaScript Java
现代化软件开发中的前后端分离模式
随着互联网技术的快速发展,现代化软件开发中的前后端分离模式逐渐成为主流。本文将介绍前后端分离的概念和优势,以及如何在不同的技术栈中实现这种模式。通过前后端分离,可以提高开发效率、降低耦合性,并且更好地满足用户需求。
848 0
|
负载均衡 Dubbo 应用服务中间件
Docker Overlay网络的一些总结
在早期的docker版本中,是不支持跨主机通信网络驱动的,也就是说如果容器部署在不同的节点上面,只能通过暴露端口到宿主机上,再通过宿主机之间进行通信。随着docker swarm集群的推广,docker也有了自家的跨主机通信网络驱动,名叫overlay,overlay网络模型是swarm集群容器间通信的载体,将服务加入到同一个网段上的Overlay网络上,服务与服务之间就能够通信。
1134 0
Docker Overlay网络的一些总结
|
前端开发 JavaScript 关系型数据库
开发中的前端和后端
开发中的前端和后端
2969 0
|
JavaScript 前端开发 数据库
让你少踩坑的fastadmin教程(3)
让你少踩坑的fastadmin教程
1806 0
让你少踩坑的fastadmin教程(3)
|
7月前
|
传感器 人工智能 算法
《具身智能机器人:自修复材料与智能结构设计的前沿探索》
在具身智能机器人的研发中,自修复材料与智能结构设计是关键领域。自修复材料通过微胶囊或形状记忆效应实现损伤自我修复,提升机器人在极端环境下的生存能力;智能结构设计则赋予机器人灵活可变的形态,使其适应复杂任务需求。然而,当前技术仍面临修复效率、性能平衡及结构控制等挑战。随着多学科融合进步,未来机器人有望实现高效自愈与高度智能化结构变化,推动科技和社会发展。
321 32
|
9月前
|
人工智能 安全 前端开发
github和npm开启2FA双重身份验证无法登陆
随着安全需求提升,许多应用如GitHub和npm已强制启用2FA(双重身份验证)。2FA通过用户名、密码及动态验证码增强账号安全性。若手机丢失或TOTP应用失效,可使用开启2FA时生成的recovery code登录并重新绑定。推荐使用大厂的TOTP工具,如Microsoft Authenticator、Google Authenticator等,避免小应用停服风险。若无备份码,只能通过人工申诉找回账号。
613 15
github和npm开启2FA双重身份验证无法登陆
|
人工智能 安全 物联网
区块链技术的未来展望:去中心化金融(DeFi)与Web 3.0的融合
区块链技术的未来展望:去中心化金融(DeFi)与Web 3.0的融合
|
存储 NoSQL 大数据
【MongoDB 专栏】MongoDB 在大数据场景下的应用
【5月更文挑战第11天】MongoDB,适用于大数据时代,以其灵活数据模型、高可扩展性和快速性能在大数据场景中脱颖而出。它处理海量、多类型数据,支持高并发,并在数据分析、日志处理、内容管理和物联网应用中广泛应用。电商和互联网公司的案例展示了其在扩展性和业务适应性上的优势,但同时也面临数据一致性、资源管理、数据安全和性能优化的挑战。
1200 1
【MongoDB 专栏】MongoDB 在大数据场景下的应用
|
XML 前端开发 JavaScript
Web的三个主要部分
Web的三个主要部分
2436 1
|
机器学习/深度学习 存储 人工智能