21天徒手撸一个游戏引擎(6)自运动,及在Sprite中实现碰撞检测

sprite.js 中的constructor函数中增加:

this.vx = 0
this.vy = 0

sprite.js 中的update函数:

this.x += this.vx
this.y += this.vy

这样,只要设置vx或vy,它就可以自己动了。

在Sprite.js中的constructor函数设置:

this.on_update = () => {}

这是一个空方法,就是为了在实例化sprite时去设置update方法

相应地,Sprite.js中:

  update() {
    this.x += this.vx
    this.y += this.vy
    this.on_update()
  }

则在更新自身坐标后调用了on_update方法。

在Sprite.js中新增:

  remove_from(arr) {
    const index = arr.indexOf(this)
    if (index != -1) {
      arr.splice(index, 1)
    }
  }

这样,就可以从update中写判断来从数组中移除自己。

在 game.js 中:

bullet.vy = -5
bullet.on_update = () => {
    if (bullet.y <= 0 - bullet.height) {
        bullet.remove_from(bullets)
    }
}

即敌机坐标超过屏幕下方,就从敌机数组中移除。

同样,把碰撞检测函数放到Sprite.js里:

collision_with(arr) {
    const self = this
    return arr.filter(item => {
      return item.x + item.width * this.collision_buff > self.x &&
        item.x < self.x + item.width * this.collision_buff && self.y + self.height * this.collision_buff > item.y &&
        self.y < item.y + item.height * this.collision_buff
    })
}

这时,对player而言,如果找到发生碰撞的敌机,则游戏结束:

player.on_update = () => {
    const arr = player.collision_with(enemys)
    if (arr.length > 0) {
      gameover = true
    }
}

对于子弹:

const collisioned = bullet.collision_with(enemys)
collisioned.map(item => {
    score += 1
    item.remove_from(enemys)
})
if (collisioned.length > 0) {
    bullet.remove_from(bullets)
}

现在,game.js 全部代码为:

import './libs/weapp-adapter'
import './libs/symbol'
import {
  ResLoader,
  Sprite
} from './codetyphon/index'
const context = canvas.getContext('2d')
const {
  windowWidth,
  windowHeight
} = wx.getSystemInfoSync()

let time = 0
let enemys = []
let bullets = []
let gameover = false
let score = 0

function rand(min, max) {
  return Math.round(Math.random() * (max - min) + min);
}

const loader = new ResLoader()
loader.add('player', 'images/player.png')
loader.add('enemy', 'images/enemy.png')
loader.add('gameover', 'images/gameover.png')
loader.add('bullet', 'images/bullet.png')
loader.on_load_finish((res) => {
  const player = new Sprite(0, 0, res['player'], 0.5)
  player.setPosition(windowWidth / 2, windowHeight - player.height)
  player.on_update = () => {
    const arr = player.collision_with(enemys)
    if (arr.length > 0) {
      gameover = true
    }
  }
  const update = () => {
    player.update()
    enemys.map((enemy, enemy_index) => {
      enemy.update()
    })
    bullets.map((bullet, bullet_index) => {
      bullet.update()
    })
  }
  const draw = () => {
    player.draw(context)
    enemys.map(enemy => {
      enemy.draw(context)
    })
    bullets.map(bullet => {
      bullet.draw(context)
    })
    context.font = 'normal 20px sans-serif';
    context.fillStyle = '#fff'
    context.fillText(score, 10, 30)
  }
  const step = (timestamp) => {
    context.clearRect(0, 0, windowWidth, windowHeight)
    //update
    if (!gameover) {
      time += 1;
      if (time % 60 == 0) {
        const enemy = new Sprite(0, 0, res['enemy'], 0.5)
        enemy.setPosition(rand(0, windowWidth - enemy.width), 0)
        enemy.vy = 3
        enemy.on_update = () => {
          if (enemy.y > windowHeight) {
            enemy.remove_from(enemys)
          }
        }
        enemys.push(enemy)
      }
      update()
    }
    draw()
    if (gameover) {
      context.drawImage(res['gameover'], windowWidth / 2 - res['gameover'].width / 4, windowHeight / 2 - res['gameover'].height / 4, res['gameover'].width / 2, res['gameover'].height / 2)
    }
    window.requestAnimationFrame(step);
  }
  window.requestAnimationFrame(step);
  wx.onTouchMove(function (res) {
    if (!gameover) {
      const x = res.changedTouches[0].clientX
      const y = res.changedTouches[0].clientY
      player.setPosition(x, y)
    }
  })
  wx.onTouchEnd((result) => {
    if (!gameover) {
      const bullet = new Sprite(0, 0, res['bullet'], 0.1)
      bullet.setPosition(player.x, player.y)
      bullet.vy = -5
      bullet.on_update = () => {
        if (bullet.y <= 0 - bullet.height) {
          bullet.remove_from(bullets)
        } else {
          const collisioned = bullet.collision_with(enemys)
          collisioned.map(item => {
            score += 1
            item.remove_from(enemys)
          })
          if (collisioned.length > 0) {
            bullet.remove_from(bullets)
          }
        }
      }
      bullets.push(bullet)
    }
  })
})

你可能感兴趣的:(小游戏)