自己写一个简单的游戏对象基类

我希望所有的游戏对象都保存在一个集合中,这里我简单使用一个数组保存,即GAME_OBJECT ,在这之后,所有GameObject类的对象在创建后,都会被保存在GAME_OBJECT数组中。

为了做到上述这一点,在GameObjectconstructor中,加入这一行代码GAME_OBJECT.push(this)
为了不让游戏对象过多,要记得在对象被销毁时将对象在GAME_OBJECT 中删除,即以下代码:

destroy() {
    this.beforeDestroy()
    GAME_OBJECT.splice(GAME_OBJECT.indexOf(this), 1)
}

要想在浏览器中使对象按每秒60帧的帧率执行对象中的函数,我们需要利用requestAnimationFrame 这个函数。它可以接收一个函数,我们在这个函数中递归调用requestAnimationFrame 就可以持续执行下去。

let last_timestamp

const step = (timestamp) => {
  for (let obj of GAME_OBJECT) {
    if (obj.has_called_start === false) {
      obj.has_called_start = true
      obj.start()
    } else {
      obj.timedelta = timestamp - last_timestamp
      obj.update()
    }
  }
  last_timestamp = timestamp
  requestAnimationFrame(step)
}

requestAnimationFrame(step)

这里我们需要记录一下当前帧与上一帧之间的时间间隔,单位为毫秒,即timedelta
我们有时还需要在对象创建的第一时间做些初始化工作,所以可以实现一个start() 函数,为了实现start 函数只执行一次,可以定义一个变量has_called_start ,用于判断是否执行了start函数。

总的函数实现

const GAME_OBJECT = []

class GameObject {
  constructor() {
    GAME_OBJECT.push(this)
    this.timedelta = 0
    this.has_called_start = false
  }

  start() {}

  update() {}

  beforeDestroy() {}

  destroy() {
    this.beforeDestroy()
    GAME_OBJECT.splice(GAME_OBJECT.indexOf(this), 1)
  }
}

let last_timestamp

const step = (timestamp) => {
  for (let obj of GAME_OBJECT) {
    if (obj.has_called_start === false) {
      obj.has_called_start = true
      obj.start()
    } else {
      obj.timedelta = timestamp - last_timestamp
      obj.update()
    }
  }
  last_timestamp = timestamp
  requestAnimationFrame(step)
}

requestAnimationFrame(step)

export default GameObject