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

本文详细介绍了如何使用TypeScript、Less和Webpack构建一个贪吃蛇游戏,涵盖食物类、蛇类、控制类和分数类的实现,展示了TS的便捷与特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本内容学习来自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<HTMLDivElement>
  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', '<div></div>')
  }

  // 移动蛇的身体
  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个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瑞雨溪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值