我的新書AI 職場超神助手:ChatGPT 與生成式 AI 一鍵搞定工作難題的教材投影片已製作完成
歡迎各位有需要的教師和博碩文化索取教材

[16- Pixi教學] 與網頁互動-控制loading page



加入loading page

上一篇的成果在載入檔案時畫面就會停在那邊,一般的遊戲通常會有一個下載中的畫面,告知使用者現在下載了幾%,還差幾%還未下載完成。
因此今日我們就要來製作這個loading page

首先,在index.html裡加上一個div

<div id="gameContainer">
  <canvas id="gameCanvas"></canvas>
  <div id="loadingPage">Loading...</div>
</div>

並在style.css裡設定

#gameCanvas{
    position:absolute;
}
#loadingPage{
    min-width: 100%;
    min-height: 100%;
    position:absolute;
    left:0px;
    top: 0px;
    z-index:1;
    background-color: #000000;
    color: #fff;
    text-align: center;
    vertical-align: middle;
    line-height: 100vh;
}
#loadingPercent{
    position:absolute;
    min-width: 100%;
    min-height: 100%;
    top:calc(50%);
}

這樣我們就會有一個很簡單的loading畫面如下圖

更新loading進度

直接用jquery去操控剛剛所設定的div裡面的文字顯示,來更新現在的下載進度:

this.loader.onProgress.add((e) => {
    jQuery("#loadingPage").html("Loading..." + Math.floor(e.progress) + "%");
});

整個Loader.ts修改後的程式碼如下:

import { ResourcesList } from "./ResourcesList";
import {eventEmitter} from "../Main";
import {CoreEvent} from "./Event";
import math = PIXI.core.math;

export class Loader{
    private static loader:PIXI.loaders.Loader;
    private static failedFiles:Array<string> = [];
    private static completedFiles:Array<string> = [];
    public static resources:PIXI.loaders.Resource;

    public static load(){
        this.loader = new PIXI.loaders.Loader();
        ResourcesList.img.forEach(element => {
            this.loader.add(element.id, element.path);
        });
        this.loader.load((loader, resources) => {
            this.resources = resources;
        });
        //可取得下載進度
        this.loader.onProgress.add((e) => {
            jQuery("#loadingPage").html("Loading..." + Math.floor(e.progress) + "%");
        });
        //載入檔案錯誤時
        this.loader.onError.add((t, e, r) => {
            this.failedFiles.push(r.name);//載入失敗的檔案列表
        });
        //每個檔案載入時都會呼叫
        this.loader.onLoad.add((e, t) => {
            this.completedFiles.push(t.name);//載入成功的檔案列表
        });
        //全部下載完成後
        this.loader.onComplete.add(() => {
            if (this.failedFiles.length == 0){
                //全部的檔案都下載成功
            } else{
                jQuery("#loadingPage").html("Loading...failed: could not load "+ this.failedFiles);
            }
        });
    }
}

EventEmitter介紹

PIXI.utils.EventEmitter使用EventEmitter3,在pixiJSv4之後已直接被整理到pixi裡了。
這個套件可以讓我們在js裡很方便的使用事件,在動畫處理上,事件的監聽與發送可以讓我們在處理動畫上更加輕鬆,也可以降低這些元件間的相依性。

下面是EventEmitter3上的一個簡單使用範例

var EE = new EventEmitter()
  , context = { foo: 'bar' };

function emitted() {
  console.log(this === context); // true
}

EE.once('event-name', emitted, context);//context為傳入函數的參數
EE.on('another-event', emitted, context);
EE.removeListener('another-event', emitted, context);

如果我們希望整個遊戲共用一個EventEmitter,可以將產生的EventEmitter做export:

export let eventEmitter:EventEmitter;

要使用這個物件可以直接import進來

import {eventEmitter} from "../Main";

發送下載完成事件

Loader.ts加入下面的程式碼:

 //全部下載完成後
        this.loader.onComplete.add(() => {
            if (this.failedFiles.length == 0){
                eventEmitter.emit(CoreEvent.AssetsLoadComplete);
            } else{
                jQuery("#loadingPage").html("Loading...failed: could not load "+ this.failedFiles);
            }
        });

接著在Main.ts裡設定下載完後要做的事情:

//設定共用的事件傳遞元件
        eventEmitter = new EventEmitter();
        eventEmitter.on(CoreEvent.AssetsLoadComplete,()=>{
            //隱藏loading page
            jQuery("#loadingPage").hide();
            //加入背景
            var background = PIXI.Sprite.from(Loader.resources["background"].texture);
            application.stage.addChild(background);
        });

上面需要注意,因為我們在Loader.loader.load()裡將下載後的resource存在一個變數裡,所以我們可以直接使用

Loader.resources["background"].texture

來取得某一個resource id下的texture。

今日成果

線上展示:http://claire-chang.com/ironman2018/1031/
成果檔案下載:ironman20181031


17年資歷女工程師,專精於動畫、影像辨識以及即時串流程式開發。經常組織活動,邀請優秀的女性分享她們的技術專長,並在眾多場合分享自己的技術知識,也活躍於非營利組織,辦理活動來支持特殊兒及其家庭。期待用技術改變世界。

如果你認同我或想支持我的努力,歡迎請我喝一杯咖啡!讓我更有動力分享知識!