教你打飞机vue3 + ts + vite

850 阅读3分钟

我正在参加掘金社区游戏创意投稿大赛团队赛,详情请看:游戏创意投稿大赛

大帅 带队,鹏飞 参与开发《1945年柏林的夜空》史诗型飞机游戏。正值刚学习vue3,又赶上了掘金的游戏创意大赛,因为不太熟悉游戏引擎,所以就使用 uni-app 的 vue3-vite-ts 脚手架通过在canvas上自由画图的方式撸了这版游戏。本文为代码实现篇,主要讲解项目各个模块是怎么运行起来的。

说实话参加项目是偶然的,而且最近公司项目比较紧急,已经连续4天加班到转钟了,不过还是坚持下来了,同时也感谢大帅鹏飞两位大佬的支持。废话不多说,show code

因为我们是飞机大战,所以我从--战斗机、子弹、碰撞几个方面说下: 因为使用的是ts,我们先来先创建基础飞机类、我方、敌方、子弹包括定位、宽高、开火方法、移动方法:

interface planeIf {
  x: number
  y: number
  index: number
  life: number
  width: number
  height: number
}

interface heroIf extends planeIf {
  count: number
  hCount: number
  eCount: number
  n: number
  draw: (ctx: any, changeState: (arg0: StateEnum) => void,  hullets: hulletIf[], score: number, liveEnemy: enemyIf[]) => void
  hit: (liveEnemy: enemyIf[]) => void
  
}

interface enemyIf extends planeIf {
  speed: number
  n: number
  enemy: null | {}
  removable: boolean
  die: boolean
  draw: (ctx: any, canvasHeight: number, canvasWidth: number,hullets: hulletIf[],gameScore:number ,changeScore:  (arg0: number) => void) => void
  hit: (ullets: hulletIf[],gameScore:number ,changeScore:  (arg0: number) => void) => void
}

interface hulletIf {
  n: number
  mx: number
  my: number
  width: number
  height: number
  removable: boolean
  draw: (ctx: any) => void
}

好的,现在所有类型都定义好了,还要完善基类的方法,例如:1.我方战斗机的飞行、子弹逻辑、开火逻辑、碰撞逻辑;2.敌方战斗机的飞行、开火逻辑、碰撞逻辑;3.子弹位置、轨迹。下面就写一个我方战斗机的逻辑示例:

 class Hero implements heroIf {
  x: number
  y: number
  index: number
  count: number
  hCount: number
  eCount: number
  n: number
  life: number
  width: number
  height: number
  constructor(width: number, height: number) {
    // this.x = (width - heroImg[0].width) / 2 // hero的坐标
    // this.y = height - heroImg[0].height
    this.x = (width - 100) / 2 // hero的坐标
    this.y = height - 200
    this.index = 0 // 用于切换hero的图片
    this.count = 0 // 用于控制hero图片切换的频率
    this.hCount = 0 // 用于控制子弹发射的频率
    this.eCount = 0 // 用于控制敌机出现的频率
    this.n = 0
    this.life = 3
    this.width = 0
    this.height = 0
    uni.getImageInfo({
      src: `/static/img/${heroArr[this.index]}`,
      success: (res)=>{
        this.width = res.width;  // 子弹的宽和高
        this.height = res.height;
        this.x =(width - res.width) / 2 // hero的坐标
        this.y = height - res.height
      }
    })
  }

  draw(ctx: any, changePhase: (arg0: StateEnum) => void, hullets: hulletIf[], score: number, liveEnemy: enemyIf[]) {
    this.count++
    this.hit(liveEnemy)
    if (this.index > 4) {
      changePhase(StateEnum.OVER)
      this.index = 5
    }
    if (this.count % 3 == 0 && this.index <= 1) {
      // 切换hero的图片
      this.index = this.index == 0 ? 1 : 0
      this.count = 0
    }
    
    ctx.drawImage(`/static/img/${heroArr[this.index]}`, this.x, this.y)
    ctx.draw(true)

    

    this.hCount++
    if (this.hCount % 3 == 0) {
      // 同时生成三颗子弹
      this.n == 32 && (this.n = 0)
      hullets.push(new Hullet(this.n, this.x, this.y, this.width))
      this.n == 0 && (this.n = -32)
      hullets.push(new Hullet(this.n, this.x, this.y, this.width))
      this.n == -32 && (this.n = 32)
      hullets.push(new Hullet(this.n, this.x, this.y, this.width))
      this.hCount = 0
    }
    this.eCount++
    if (this.eCount % 8 == 0) {
      //生成敌机
      liveEnemy.push(new Enemy())
      this.eCount = 0
    }
  }
  hit(liveEnemy: enemyIf[]) {
    // 判断是自己是否被击中
    for (var i = 0; i < liveEnemy.length; i++) {
      var d = liveEnemy[i]
      // 敌机与自己的碰撞检测
      var px, py
      px = this.x <= d.x ? d.x : this.x
      py = this.y <= d.y ? d.y : this.y
      // 判断点
      if (
        px >= this.x &&
        px <= this.x + this.width &&
        py >= this.y &&
        py <= this.y + this.height &&
        px >= d.x &&
        px <= d.x + d.width &&
        py >= d.y &&
        py <= d.y + d.height
      ) {
        this.life--
        if (this.life < 2) {
          if (this.index <= 2) {
            this.index = 3
          }
          this.index++
        }
      }
    }
  }
 
}

现在一切就绪,准备 setup 画背景、画敌机、画我方战斗机、操作逻辑、开始、暂停、结束、主引擎等代码的完善,感兴趣可以去git上提点提点。

通过参加这次比赛,学习巩固了uniapp + vue3 + ts + vite的实战,在我看来vue3不论是现在还是未来都有很大的前景,在国内认可度,普及度都是极高的,不光是vue3的composition-api,Reactivity、还是proxy双向数据绑定,对ts都高度支持,配合vite,谁用谁酸爽。

飞机动起来传送门-上篇


好了,本文就给大家介绍到这里,感觉有帮助的,留下个赞或评论再走吧!谢啦~ 💐