关于小游戏:21天徒手撸一个游戏引擎7整合一些变量到Game对象

7次阅读

共计 4792 个字符,预计需要花费 12 分钟才能阅读完成。

因为间接在 game.js 中写了很多逻辑,因而须要提取一些性能到 Game 对象中。

新建 codetyphon/game.js

把之前在./game.js 中的代码移过去

const context = canvas.getContext('2d')
const {
  windowWidth,
  windowHeight
} = wx.getSystemInfoSync()

类对象 Game,具备一些属性。

export default class Game {constructor(res_gameover) {
    this.score = 0
    this.life = 1
    this.gameover = false
    this.time = 0
    this.on_times = []
    this.on_update = () => {}
    this.player = null
    this.enemys = []
    this.bullets = []
    this.foods = []
    this.res_gameover = res_gameover
  }
}

如果从新开始游戏,须要从新初始化

restart() {this.enemys = []
  this.bullets = []
  this.foods = []
  this.score = 0
  this.life = 1
  this.gameover = false
  this.time = 0
}

它得有 update、render、start 等办法

update(){}
render(){}
start(){}

把 step 移过去

start() {const step = (timestamp) => {context.clearRect(0, 0, windowWidth, windowHeight)
      if (!this.gameover) {this.update()
      }
      this.render()
      if (this.gameover) {this.render_gameover()
      }
      window.requestAnimationFrame(step);
    }
    window.requestAnimationFrame(step);
  }

设置增加不同品种的精灵

set_player(player) {this.player = player}
add_enemy(enemy) {this.enemys.push(enemy)
}
add_bullet(bullet) {this.bullets.push(bullet)
}
add_food(food) {this.foods.push(food)
}

对工夫距离的解决:

this.on_times = []

增加一个间隔时间的函数

on_time(time = 100, fn = () => {}) {
  this.on_times.push({
    time: time,
    fn: fn
  })
}

在 update 中,解决工夫距离

this.time += 1
this.on_times.map(item => {if (this.time % item.time == 0) {item.fn()
  }
})

全副代码如下:

export default class Game {constructor(res_gameover) {
    this.score = 0
    this.life = 1
    this.gameover = false
    this.time = 0
    this.on_times = []
    this.on_update = () => {}
    this.player = null
    this.enemys = []
    this.bullets = []
    this.foods = []
    this.res_gameover = res_gameover
  }
  restart() {this.enemys = []
    this.bullets = []
    this.foods = []
    this.score = 0
    this.life = 1
    this.gameover = false
    this.time = 0
  }
  set_player(player) {this.player = player}
  add_enemy(enemy) {this.enemys.push(enemy)
  }
  // remove_enemy(enemy) {//}
  // remove_bullet(bullet) {//}
  // remove_food(food) {//}
  add_bullet(bullet) {this.bullets.push(bullet)
  }
  add_food(food) {this.foods.push(food)
  }

  on_time(time = 100, fn = () => {}) {
    this.on_times.push({
      time: time,
      fn: fn
    })
  }
  update() {if (this.player) {this.player.update()
    }
    this.enemys.map(item => item.update())
    this.bullets.map(item => item.update())
    this.foods.map(item => item.update())
  }
  render_life(x = 8, y = 30, fontSize = 20) {context.font = `normal ${fontSize}px serif`
    context.fillStyle = '#fff'
    context.fillText(`🧡 x ${this.life}`, x, y)
  }
  render_score(x = 10, y = 60, fontSize = 20) {context.font = `normal ${fontSize}px sans-serif`
    context.fillStyle = '#fff'
    context.fillText(`score: ${this.score}`, x, y)
  }
  render() {if (this.player) {this.player.draw(context)
    }
    this.enemys.map(item => item.draw(context))
    this.bullets.map(item => item.draw(context))
    this.foods.map(item => item.draw(context))
    this.render_life()
    this.render_score()}
  render_gameover() {context.drawImage(this.res_gameover, windowWidth / 2 - this.res_gameover.width / 4, windowHeight / 2 - this.res_gameover.height / 4, this.res_gameover.width / 2, this.res_gameover.height / 2)
  }
  start() {const step = (timestamp) => {context.clearRect(0, 0, windowWidth, windowHeight)
      if (!this.gameover) {
        this.time += 1
        this.on_times.map(item => {if (this.time % item.time == 0) {item.fn()
          }
        })
        this.update()
        this.on_update()}
      this.render()

      if (this.gameover) {this.render_gameover()
      }
      window.requestAnimationFrame(step);
    }
    window.requestAnimationFrame(step);
  }
}

这样,./game.js 就变为:

import './libs/weapp-adapter'
import './libs/symbol'
import {
  ResLoader,
  Sprite,
  Game
} from './codetyphon/index'

const {
  windowWidth,
  windowHeight
} = wx.getSystemInfoSync()

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

let click = 0

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) => {let game = new Game(res['gameover'])
  game.life = 3
  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(game.enemys)
    if (arr.length > 0) {
      game.life -= 1
      if (game.life <= 0) {game.gameover = true} else {
        arr.map(item => {item.remove_from(game.enemys)
          game.score += 1
        })
      }
    }
  }
  game.set_player(player)
  game.on_time(200, () => {//add food})
  game.on_time(80, () => {const enemy = new Sprite(0, 0, res['enemy'], 0.5)
    enemy.setPosition(rand(0, windowWidth - enemy.width), 0)
    enemy.vy = rand(3, 10)
    enemy.on_update = () => {if (enemy.y > windowHeight) {enemy.remove_from(game.enemys)
      }
    }
    game.add_enemy(enemy)
  })
  game.on_update = () => {}
  game.start()
  wx.onTouchMove(function (res) {if (!game.gameover) {const x = res.changedTouches[0].clientX
      const y = res.changedTouches[0].clientY
      player.setPosition(x, y)
    }
  })
  wx.onTouchEnd((result) => {if (!game.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(game.bullets)
        } else {const collisioned = bullet.collision_with(game.enemys)
          collisioned.map(item => {
            game.score += 1
            item.remove_from(game.enemys)
          })
          if (collisioned.length > 0) {bullet.remove_from(game.bullets)
          }
        }
      }
      game.add_bullet(bullet)
    }
    if (game.gameover) {
      click++
      if (click >= 2) {game.restart()
        click = 0
      }
    }
  })
})
正文完
 0