21天徒手擼一個遊戲引擎(2)圖片資源加載器及精靈設置圖片

上次代碼有問題,只能在IDE上面預覽,不能真機。由於真機小遊戲中缺乏window對象。
解決方法就是,引用用微信的weapp-adapter。canvas

import './libs/weapp-adapter'
import './libs/symbol'

以後:微信

const context = canvas.getContext('2d')

並不須要const canvas = wx.createCanvas()了。app

接下來,須要讓精靈繪製圖片。異步

因此,Sprite的draw方法改變一下:函數

draw(context) {
   // context.fillStyle = '#1aad19'
   // context.fillRect(this.x, this.y, 50, 50)
   context.drawImage(this.img, this.x, this.y)
}

在構建函數中:this

constructor(x = 0, y = 0, img, scale = 1) {
    this.x = x
    this.y = y
    this.img = img
    this.scale = scale
}

考慮到player的img可能會變化,所以,設立一個setImg的方法:spa

setImg(img) {
    this.img = img
    this.width = img.width
    this.height = img.height
}

可見精靈的尺寸是與圖片有關的。不少遊戲引擎能夠經過scale來設置大小。所以,如今構建函數變爲:code

constructor(x = 0, y = 0, img, scale = 1) {
    this.x = x
    this.y = y
    this.scale = scale
    this.setImg(img)
}

相應地,在game.js中,初始化player就變成了:對象

const player = new Sprite(0, 0, player_img, 0.5)

player_img是哪兒來的?遊戲

代碼以下:

const player_img = wx.createImage()
player_img.src = item.src
player_img.onload = function () {
    const player = new Sprite(0, 0, player_img, 0.5)
}

由於是直接用Sprite new出來的,所以以前Player.js沒用了,刪掉就好。

因爲精靈須要改變位置,所以添加一個方法:

setPosition(x, y) {
   this.x = x
   this.y = y
}

因爲加載圖片是異步的,若是圖片不少,那麼一個個寫明顯不合適。所以,寫一個資源載入類/codetyphon/resloader.js:

export default class ResLoader {
  constructor() {
    this.list = []
    this.res = {}
    this.load_num = 0
  }
  add(name, src) {
    this.list.push({
      name: name,
      src: src
    })
  }
  on_load_finish(fun) {
    const _self = this
    this.list.map(item => {
      console.log(item.src)
      const image = wx.createImage()
      image.src = item.src
      image.onload = function () {
        console.log(item.name + ' load')
        _self.res[item.name] = this
        _self.load_num += 1;
      }
    })
    const id = setInterval(() => {
      if(_self.load_num==_self.list.length){
        clearInterval(id)
        fun(_self.res)
      }
    }, 100)
  }
}

在 codetyphon/index.js 中:

import Sprite from './sprite'
import ResLoader from './resloader'
export {
  ResLoader,
  Sprite
}

在 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()
const loader = new ResLoader()
loader.add('player', 'images/player.png')
loader.on_load_finish((res) => {
  const player = new Sprite(0, 0, res['player'], 0.5)
  player.setPosition(windowWidth / 2, windowHeight - player.height)
  const step = (timestamp) => {
    context.clearRect(0, 0, windowWidth, windowHeight)
    player.update()
    player.draw(context)
    window.requestAnimationFrame(step);
  }
  window.requestAnimationFrame(step);
  wx.onTouchMove(function (res) {
    const x = res.changedTouches[0].clientX
    const y = res.changedTouches[0].clientY
    player.setPosition(x, y)
  })
})

這個時候,就能夠經過觸屏去移動player了。
image

可是仔細看能夠發現,觸動時,是精靈的左上角,而不是中間。
所以,Sprite的draw方法改成:

context.drawImage(this.img, this.x - this.width / 2, this.y - this.height / 2, this.width, this.height)

如今,Sprite所有代碼爲:

export default class Sprite {
  constructor(x = 0, y = 0, img, scale = 1) {
    this.x = x
    this.y = y
    this.scale = scale
    this.setImg(img)
  }
  setImg(img) {
    this.img = img
    this.width = img.width * this.scale
    this.height = img.height * this.scale
  }
  setPosition(x, y) {
    this.x = x
    this.y = y
  }
  update() {

  }
  draw(context) {
    context.drawImage(this.img, this.x - this.width / 2, this.y - this.height / 2, this.width, this.height)
  }
}

如今,觸動的位置恰好在精靈的中間。
image

相關文章
相關標籤/搜索