今天來做載入頁面以及基本場景吧!
我們昨天做了一次載入多張圖,但遊戲在真實環境時,也許網路速度相當的慢,造成LOADING期時會有一段時間,那我們得顯示一些載入動畫舒緩緊張情緒,於是得要有一載入頁面。
以下為目前結構,我新增了groups資料夾以及Loading.ts載入頁面,我定義groups是群組的物件,裡面包含許多objects,而本身groups並不是一個實際的物件,感覺像是組合物的容器。
還有新增config/loadingPath.ts,用意載入畫面先把自己要用到的圖片載完,才開始載遊戲內的其他畫面,不然空空的看著%數挺無趣的!
└──src
│ App.ts
│ Game.ts
│
├─components
│ ├─elements
│ │ Animation.ts
│ │ Sprite.ts
│ │ Texture.ts
│ │ Wrapper.ts
│ │ WrapperContainer.ts
│ │ WrapperContainerCenter.ts
│ │ WrapperType.ts
│ │
│ ├─groups
│ │ Loading.ts
│ │
│ └─objects
│ Chip.ts
│
├─config
│ chipType.ts
│ imagePath.ts
│ loadingPath.ts
│
└─loaders
Loader.ts
loadingPath.ts內容就是兩個路徑而已
loadingPath.ts
/**
* 這邊是放loading頁面要的圖 因為要分開載入
*/
export default {
'logo': './assets/scene/loading-logo.png',
'bg': './assets/scene/loading-bg.jpg'
}
以下一長串就是我們的Loading頁面!
大致就是由兩張圖片,一張底圖以及一張LOGO,那載入進度是由數字顯示。
Loading.ts
import loadingPath from '@/config/loadingPath'
import Wrapper from '@/components/elements/Wrapper'
import Texture from '@/components/elements/Texture'
import WrapperContainerCenter from '@/components/elements/WrapperContainerCenter'
import * as PIXI from "pixi.js"
export default class Loading extends WrapperContainerCenter {
private _loadingText: Wrapper
private _loadLogo: Wrapper
private _loadBg: Wrapper
private _status: boolean = false
constructor() {
super()
let rect = new PIXI.Graphics() // 畫一個區間撐開容器用以方便置中定位
rect.beginFill(0xff0000)
rect.drawRect(0, 0, 1650, 900)
rect.endFill()
rect.alpha = 0 // 不需要被看見只要能撐開就好
this._centerContainer.addContainer(rect)
// 這邊宣告三個容器像是圖層
this._loadingText = new WrapperContainerCenter()
this._loadLogo = new WrapperContainerCenter()
this._loadBg = new WrapperContainerCenter()
// 這是背景
this._centerContainer.addChild(this._loadBg)
this._loadBg.addChild(new Texture(loadingPath.bg))
this._loadBg.setSize(false, 1950, 900)
this._loadBg.setAlpha(false, 0)
this._loadBg.setAlpha(true, 1)
this._loadBg.setPosition({ animation: false }, -162.5, 0)
// 這是LOGO
this._centerContainer.addChild(this._loadLogo)
this._loadLogo.addChild(new Texture(loadingPath.logo))
this._loadLogo.setAlpha(false, 0)
this._loadLogo.setAlpha(true, 1)
this._loadLogo.setPosition({ animation: false }, 1650 / 2 - this._loadLogo.width / 2, 900 / 2 - this._loadLogo.width / 2)
// 這是載入進度
this._centerContainer.addChild(this._loadingText)
// 置中用途
this._loadingText.setPosition({ animation: false }, 1650 / 2 - this._loadingText.width / 2, 900 - 200)
// 讓LOGO動起來
this.animation()
}
// 如果載入完了Logo會放大消失
public done(delay?: number) {
return new Promise((resolve, reject) => {
setTimeout(() => {
this._status = true
this._loadLogo.setScale(true, 2, 2)
this._loadLogo.setAlpha(true, 0)
setTimeout(() => {
resolve()
}, 0)
}, delay ? delay : 0)
})
}
// update是給外部操控現在%數多少
public update(process: number) {
this._loadingText.removeChildren()
this._loadingText.addContainer(new PIXI.Text(`Loading: ${process} %`, { fontFamily: 'Arial', fontSize: 24, fill: 0xff1010, align: 'center' }))
this._loadingText.setPosition({ animation: false }, 1650 / 2 - this._loadingText.width / 2, 900 - 200)
}
// 持續的動畫
private animation() {
let _reverse = false
let timeout = setInterval(() => {
_reverse ? this._loadLogo.setPosition({ animation: true, during: 3 }, this._loadLogo.x, this._loadLogo.y - 50) : this._loadLogo.setPosition({ animation: true, during: 3 }, this._loadLogo.x, this._loadLogo.y + 50)
_reverse = !_reverse
if (this._status) { clearInterval(timeout) }
}, 700)
}
}
現在我們回到我們的Game.ts,裡面有載入的方法,我們新增了甚麼呢?
import Loader from '@/loaders/Loader'
import imagePath from '@/config/imagePath'
import Wrapper from '@/components/elements/Wrapper'
import WrapperContainer from '@/components/elements/WrapperContainer'
// 我們需要loadingPath、Loading畫面,所以引入。
import loadingPath from '@/config/loadingPath'
import Loading from '@/components/groups/Loading'
export default class Game {
private _app: PIXI.Application
private _game: Wrapper
// 增加一個容器裝我們的loading頁面比較方便。
private _loading: Wrapper
constructor() {
this._app = new PIXI.Application({ width: 1625, height: 900 })
this._game = new WrapperContainer()
// 新增一個容器給他
this._loading = new WrapperContainer()
// 加進去我們的game讓他可以被渲染
this._game.addChild(this._loading)
this._app.stage.addChild(this._game.getContainer())
document.body.appendChild(this._app.view)
// 調用下方我們的loadimage方法,先載我們loading畫面
this.loadimage(loadingPath)
.then(() => {
// 再load所有圖片
return this.loadimage(imagePath, 9000)
})
.then(() => {
// load完呼叫stepup
this.setup()
})
}
private setup(): void {
console.log('SETUP!')
}
// 我們的loadimage方法可以設定load完之後的維持秒數,本地端測試太快速,都看不到。
private loadimage(imagePath: any, delay?: number): Promise<any> {
return new Promise((resolve, reject) => {
try {
// 新增loading畫面
let loading = new Loading()
// 把他加進去我們上面的容器
this._loading.addChild(loading)
// 呼叫Loader需要幫我們載入的圖片
Loader.load(imagePath)
.on((e: number) => {
// 載的進度可以透過on,得到我們載入的進度
loading.update(e * 100)
})
.then(() => {
// 完成之後就是跟loading說好了!不過要delay欣賞一下哦!
return loading.done(delay)
})
// 真的好了之後就把圖層內的Sprite、Texture全部清空
.then(() => {
this._loading.removeChildren()
resolve()
})
} catch (err) {
reject(err)
}
})
}
}
載入完之後就是這畫面,再來就會消失變一片黑。
緊接著我們來載入我們的場景吧!
我們要來載入我們的賭桌跟賭場被景。但我們先新增大部分的區塊圖層。
└─src
│ App.ts
│ Game.ts
│
├─components
│ ├─elements
│ │ ...省略
│ │
│ ├─groups
│ │ Body.ts
│ │ Casino.ts
│ │ Loading.ts
│ │ Navbottom.ts
│ │ Navtop.ts
│ │ Table.ts
│ │
│ └─objects
│ Chip.ts
│ Desk.ts
│ Bg.ts
...省略
我在groups內新增了Body、Casino、Navbottom、Navtop、Table,這幾部分,Casino為主要的,他的內部有Body、Navbottom,Navtop,而Table是在body內。還新增了一Desk的物件就是那張桌子的圖片,Bg的物件就是簡單的背景圖片!
Desk.ts很簡單,就是顯示desk圖片而已
Desk.ts
import Texture from '@/components/elements/Texture'
import imagePath from '@/config/imagePath'
export default class Desk extends Texture {
constructor (){
super(imagePath.deskPath)
}
}
當Desk建好了之後,我們再到groups/Table.ts看看吧!
Table.ts
import Wrapper from '@/components/elements/Wrapper'
import WrapperContainerCenter from '@/components/elements/WrapperContainerCenter'
import Desk from '@/components/objects/Desk'
export default class Table extends WrapperContainerCenter {
private _desk: Wrapper
constructor() {
super()
this._desk = new Desk()
this.addChild(this._desk)
}
}
就是很簡單的把desk掛到Table的容器上而已。Table又掛在Body上!
Body.ts
import Wrapper from '@/components/elements/Wrapper'
import WrapperContainerCenter from '@/components/elements/WrapperContainerCenter'
import Table from '@/components/groups/Table'
export default class Body extends WrapperContainerCenter {
private _table: Wrapper
constructor() {
super()
let rect = new PIXI.Graphics()
rect.drawRect(0, 0, 1650, 900)
rect.alpha = 0
this._centerContainer.addContainer(rect)
this._table = new Table()
this._table.setPosition({animation: false}, this.width / 2 - 10, this.height / 2 + 60)
// 因為桌子圖片大小緣故,透過調整比例撐滿整個寬
this._table.setScale(false, 1.2, 1.2)
this._centerContainer.addChild(this._table)
}
}
Body是掛在groups/Casino上!
Casino.ts
import Wrapper from '@/components/elements/Wrapper'
import WrapperContainerCenter from '@/components/elements/WrapperContainerCenter'
import Bg from '@/components/objects/Bg'
import Body from '@/components/groups/Body'
import Navtop from '@/components/groups/Navtop'
import Navbottom from '@/components/groups/Navbottom'
export default class Casino extends WrapperContainerCenter {
private _Body: Wrapper
private _Navtop: Wrapper
private _Navbottom: Wrapper
private _bg: Wrapper
constructor() {
super()
this._bg = new WrapperContainerCenter()
this._Body = new WrapperContainerCenter()
this._Navtop = new WrapperContainerCenter()
this._Navbottom = new WrapperContainerCenter()
this._bg.addChild(new Bg())
this._Body.addChild(new Body())
this._Body.addChild(new Navtop())
this._Body.addChild(new Navbottom())
this._centerContainer.addChild(this._bg)
this._centerContainer.addChild(this._Body)
this._centerContainer.addChild(this._Navtop)
this._centerContainer.addChild(this._Navbottom)
}
}
那當我們全部掛好掛滿之後,我們要到我們的Game.ts把我們setup的完成改成導入到Casino裡面!
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 loadingPath from '@/config/loadingPath'
import Casino from '@/components/groups/Casino'
import Loading from '@/components/groups/Loading'
export default class Game {
private _app: PIXI.Application
private _game: Wrapper
private _loading: Wrapper
constructor() {
this._app = new PIXI.Application({ width: 1625, height: 900 })
this._game = new WrapperContainer()
this._loading = new WrapperContainer()
this._game.addChild(this._loading)
this._app.stage.addChild(this._game.getContainer())
document.body.appendChild(this._app.view)
// 先load載入頁面
this.loadimage(loadingPath)
.then(() => {
// 再load所有圖片
return this.loadimage(imagePath, 0)
})
.then(() => {
this.setup()
})
}
private setup(): void {
// 引入並加進去我們的_game畫面!
let casino = new Casino()
this._game.addContainer(casino.getContainer())
}
private loadimage(imagePath: any, delay?: number): Promise<any> {
return new Promise((resolve, reject) => {
try {
let loading = new Loading()
this._loading.addChild(loading)
Loader.load(imagePath)
.on((e: number) => {
loading.update(e * 100)
})
.then(() => {
return loading.done(delay)
})
.then(() => {
this._loading.removeChildren()
resolve()
})
} catch (err) {
reject(err)
}
})
}
}
完成!
其實中間遇到滿多奇怪的地方,因為其實都已經直接參考過往的寫的,結果還是有些狀況是意料之外,看來其中還有不太了解或掌握的pixijs小問題。