昨天我們已經準備好基本的物件了,今天我們來載入我們圖檔吧!其實圖片載完、基本的動畫反應製作,遊戲介面差不多就好了。
俗稱雪碧圖,就是一張png內含很多圖片,可以用來節省請求資源,或是動畫圖。以下是我們從淘寶買來的一張籌碼圖,沒錯他沒有切好spritesheet,也許cocos有相關功能,但現階段使用pixijs也沒有特別的開發工具,就自己手切囉!
就是這樣,把他切下來後輸出
然後呢把這幾張圖片丟到 Texturepacker
右上角儲存spritesheet.json和spritesheet.png
就會有這些Spritesheet,我們就可以把這些導入到我們的pixijs盡情使用了!其他圖也是這樣切出來的!
首先我們先建立以下結構,新增objects資料夾並新增一ts檔案Chip.ts。config資料夾為chiptype.ts以及imagePath.ts
└─src
│ App.ts
├─components
│ ├─elements
│ │ Animation.ts
│ │ Sprite.ts
│ │ Texture.ts
│ │ Wrapper.ts
│ │ WrapperContainer.ts
│ │ WrapperContainerCenter.ts
│ │ WrapperType.ts
│ └─objects
│ Chip.ts
└─config
chipType.ts
imagePath.ts
chipType.ts 為定義我們籌碼的規範,有那些籌碼且代表的值為多少,
chipType.ts
export default {
'1000': { type: 'chip1000', value: 1000 },
'10000': { type: 'chip1m', value: 10000 },
'100000': { type: 'chip10m', value: 100000 },
'1000000': { type: 'chip100m', value: 1000000 },
'5000000': { type: 'chip500m', value: 5000000 },
'10000000': { type: 'chip1000m', value: 10000000 }
}
imagePath.ts 為我們圖的位置,統整圖檔位置,比較好找圖也比較好輸入。
imagePath.ts
export default {
'chipPath': './assets/chips/spritesheet.json',
}
Chip.ts 為我們籌碼的object,透過extends直接繼承Sprite elements,所以這object可以直接使用super來取得Sprite的constructor。以下為Sprite輸入Sprite圖的方法,透過建構子我們把targetsheet(整個Sprite圖),target(我要的那張圖),透過pixijs loader載進來,不過在使用前期其實還要先把圖片載到快取,不過這在後半段才會提到。
Sprite.ts
...省略
constructor(targetsheet: string, target: string) {
let id: any = PIXI.loader.resources[targetsheet].textures
...省略
以下為Chip.ts檔案
Chip.ts
import Sprite from '@/components/elements/Sprite'
import chipType from '@/config/chipType'
import imagePath from '@/config/imagePath'
export default class Chip extends Sprite {
public value: keyof typeof chipType
constructor (value: keyof typeof chipType){
super(imagePath.chipPath, `${chipType[value].type}`)
this.value = value
}
public setInteractive(interactive: boolean): void{
this._container.interactive = interactive
this._container.buttonMode = interactive
}
}
這樣還不行顯示,為什麼呢?
其實PIXIJS在使用Texture cache有許多載入方法,總之就是要先載進去快取,這樣我們就可以使用PIXI.loader.resources輕鬆取的我們的圖片囉!以下是目前架構。
└─src
│ App.ts // 入口處
│ Game.ts // Game!
│
├─components
│ ├─elements
│ │ Animation.ts
│ │ Sprite.ts
│ │ Texture.ts
│ │ Wrapper.ts
│ │ WrapperContainer.ts
│ │ WrapperContainerCenter.ts
│ │ WrapperType.ts
│ │
│ └─objects
│ Chip.ts
│
├─config
│ chipType.ts
│ imagePath.ts
│
└─loaders
Loader.ts // loader幫我們load所有圖片
我們新增一個Loader.ts協助我們大量load我們要的圖片。
以下程式碼就是我們load的方法,且可透過on的方法得到我們現在載入進度,所以有些遊戲進入很慢,載入場景就是這個部分囉,可能載入還包含同步資料等等。
Loader.ts
import * as PIXI from "pixi.js"
/**
* Loader 把設定檔的srcs傳進來自動全部load
*/
class Loader {
private onChange: Function = () => { }
public load(srcs: any) {
let on = (onChange: Function): Promise<any> => {
this.onChange = onChange
return then()
}
let then = (): Promise<any> => {
return new Promise(async (resolve, reject) => {
try {
let res = []
let totalResource = Object.keys(srcs).length
let loadedResource = 0
for (let i in srcs) {
res.push(await this.loaderAdd(srcs[i]))
loadedResource++
// 這部分就可以把我們的載入進度往外傳遞
this.onChange(loadedResource / totalResource)
}
resolve(res)
} catch (err) {
reject(err)
}
})
}
return {
then: then,
on: on
}
}
private loaderAdd(path: string) {
return new Promise((resolve, reject) => {
// 這邊是主要PIXI.loader載入圖片進cache的地方
PIXI.loader
.add(path)
.load(resolve)
.onError.add(reject)
})
}
}
export default new Loader()
好我們有這個loader之後,我們新增的Game.ts就是我們開始載入的地方!
Game.ts
import Loader from '@/loaders/Loader'
import imagePath from '@/config/imagePath'
import Wrapper from '@/components/elements/Wrapper'
import WrapperContainer from '@/components/elements/WrapperContainer'
import Chip from '@/components/objects/Chip'
export default class Game {
private _app: PIXI.Application // 一定需要PIXI.Application
private _game: Wrapper // game的容器,用來裝我們遊戲內容
constructor() {
this._app = new PIXI.Application({ width: 1625, height: 900 }) // 場景寬高
this._game = new WrapperContainer() // 新增容器
this._app.stage.addChild(this._game.getContainer()) // 這部分就是要取得容器內的container並丟給app state,這部分是pixijs原本就要這麼做的!所以才得做一個getContainer取得pixijs原生方法。
document.body.appendChild(this._app.view) // 掛到document body上!
// 我們要load的是所有圖片路徑
Loader.load(imagePath)
.on((e: number) => {
console.log(e) // 這邊會console.log出我們的進度(百分比)
})
.then(() => {
this.done() // 完成執行done method
})
.catch(err => {
console.warn(err) // 出錯警告
})
}
public done () {
let chip = new Chip('100000') // 新增籌碼
this._game.addChild(chip) // 掛到容器上
}
}
好了!Load圖片可以用了嗎?來確定一下!
沒錯!好了!已經成功顯示出我們要的圖片了!
可以在css針對canvas進行調整把他調成固定寬高比例。直接加在index.html上就好!
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html,
body {
width: 100%;
height: 100%;
background: black;
display: flex;
justify-content: center;
align-items: center;
}
canvas {
margin: 0 auto;
max-width: 100%;
max-height: 100%;
widows: auto;
height: auto;
}
</style>
最後加一點有趣的,讓籌碼亂飛吧!這是Game.ts,done的部分,讓他done之後隨機加入籌碼,而且位置不固定。
...以上省略
public done() {
let _chipType: Array<keyof typeof chipType> = ['1000', '10000', '100000', '1000000', '10000000', '5000000']
// 噴射
setInterval(() => {
let chip = new Chip(_chipType[Math.ceil(Math.random() * 6)])
chip.setPosition({ animation: true, during: Math.ceil(Math.random() * 6) },
Math.ceil(Math.random() * 1625),
Math.ceil(Math.random() * 900))
this._game.addChild(chip)
}, 100)
}
...以下省略
就可以產出一堆籌碼囉!
https://i.imgur.com/ikFypYe.mp4
明天補上載入畫面!另外直接去Github看程式碼也是好選擇哦!按個星星吧!