用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语言的方便和特点,如果大家对此游戏有问题的话,欢迎大家发私信给我,我会给大家一一解答。

目录
相关文章
|
10月前
|
前端开发
防抖和节流的区别,实现和用处。
防抖和节流是优化高频事件处理的两种技术。防抖确保在一系列连续事件后仅执行最后一次操作,如搜索输入完成后再发送请求;节流则保证在设定时间内仅执行一次操作,适用于滚动加载等场景。两者通过限制回调函数的执行频率,有效提升前端性能。示例代码展示了如何实现这两种技术。
316 2
|
10月前
|
移动开发 前端开发 JavaScript
前端H5使用canvas画爱心以及笑脸
本文介绍了HTML5中的canvas元素及其基本用法,通过JavaScript在canvas上绘制图形。首先简述了canvas的功能,接着详细展示了如何使用`bezierCurveTo`方法绘制爱心和`arc`方法绘制笑脸,并附有示例代码及效果说明。最后总结了canvas在网页图形绘制上的应用潜力。
286 2
|
10月前
|
前端开发
CSS transition过渡属性详解
本文介绍了CSS中`transition`属性的作用、用法及实例。`transition`用于在元素属性变化时添加平滑过渡动画,通过设置`transition-property`、`transition-duration`、`transition-timing-function`和`transition-delay`等属性值,可以精细控制过渡效果。文末提供了HTML示例代码,展示了如何使用`transition`实现鼠标悬停时背景颜色的平滑变化。
454 1
|
10月前
|
JavaScript 前端开发
js中的bind,call,apply方法的区别以及用法
JavaScript中,`bind`、`call`和`apply`均可改变函数的`this`指向并传递参数。其中,`bind`返回一个新函数,不立即执行;`call`和`apply`则立即执行,且`apply`的参数以数组形式传递。三者在改变`this`指向及传参上功能相似,但在执行时机和参数传递方式上有所区别。
162 1
|
10月前
|
JavaScript 前端开发
vue2的响应式数据原理
`Object.defineProperty` 是 Vue 2 实现响应式数据的核心方法,通过定义 getter 和 setter 来追踪属性的变化。当访问或修改属性时,会触发相应的函数,从而实现数据的动态更新。本文介绍了该方法的基本用法、响应式原理及其简单实现,展示了如何通过监听属性变化来自动更新视图,体现了前端框架设计中的巧妙之处。
212 1
|
10月前
|
JavaScript
使用node.js搭建一个express后端服务器
Express 是 Node.js 的一个库,用于搭建后端服务器。本文将指导你从零开始构建一个简易的 Express 服务器,包括项目初始化、代码编写、服务启动与项目结构优化。通过创建 handler 和 router 文件夹分离路由和处理逻辑,使项目更清晰易维护。最后,通过 Postman 测试确保服务正常运行。
634 1
|
10月前
|
JavaScript 编译器
用TS从零开始制作贪吃蛇游戏--1
本项目使用VSCode、Less、TypeScript及Webpack构建“贪吃蛇”游戏。首先初始化项目结构,创建Gluttonous snake文件夹并用VSCode打开,通过npm初始化package.json。接着配置Webpack,包括安装相关插件(如html-webpack-plugin、clean-webpack-plugin、webpack-dev-server)、设置TS编译环境及Less编译规则。最终实现自动打包、热更新及样式文件的正确处理。
218 52
|
10月前
|
人工智能 安全 物联网
区块链技术的未来展望:去中心化金融(DeFi)与Web 3.0的融合
区块链技术的未来展望:去中心化金融(DeFi)与Web 3.0的融合
|
10月前
|
运维 监控 持续交付
云计算环境下的运维自动化实践
本文探讨了在云计算环境下实施运维自动化的必要性、挑战及解决方案,重点介绍了如何利用现代技术工具实现高效的云资源管理和监控。通过具体案例分析,展示了自动化运维在提升系统稳定性、降低人力成本方面的优势。
|
10月前
|
JavaScript 前端开发 Java
java中的this关键字
欢迎来到我的博客,我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。自学前端2年半,正向全栈进发。若我的文章对你有帮助,欢迎关注,持续更新中!🎉🎉🎉
149 9

热门文章

最新文章