[15- Pixi教學] 載入素材

用PIXI.Sprite來載入圖檔

在PIXI.Sprite裡有一個fromImage(‘URL’)的方法可以直接讓我們將某個圖檔載入Sprite裡面,如:

var bunny = PIXI.Sprite.fromImage('required/assets/basics/bunny.png')

但這只能針對單張圖檔,而不能處理SpriteSheet的狀況。

並且當我們在做一個遊戲專案時,通常會需要先載完所有的遊戲素材,這樣才不會在進遊戲時看到未載完圖檔的空白而產生錯誤或破圖。
因此較多的時候,我們都會使用PIXI.loaders去下載並監聽下載進度,製作一個loading bar。
並在素材載入完成後才進入遊戲。


PIXI.loaders

下面為一個PIXI.loaders的簡單使用範例

const loader = new PIXI.loaders.Loader();
loader.add('bunny', 'data/bunny.png')
      .add('spaceship', 'assets/spritesheet.json');
loader.load((loader, resources) => {
   // resources.bunny
   // resources.spaceship
});

PIXI.loaders是從resource-loader擴展的。
下面為resource-loader的GitHub上的一個簡單使用範例:

// ctor
const loader = new Loader();

loader
    // Chainable `add` to enqueue a resource
    .add(name, url, options)

    // Chainable `pre` to add a middleware that runs for each resource, *before* loading that resource.
    // This is useful to implement custom caching modules (using filesystem, indexeddb, memory, etc).
    .pre(cachingMiddleware)

    // Chainable `use` to add a middleware that runs for each resource, *after* loading that resource.
    // This is useful to implement custom parsing modules (like spritesheet parsers, spine parser, etc).
    .use(parsingMiddleware)

    // The `load` method loads the queue of resources, and calls the passed in callback called once all
    // resources have loaded.
    .load((loader, resources) => {
        // resources is an object where the key is the name of the resource loaded and the value is the resource object.
        // They have a couple default properties:
        // - `url`: The URL that the resource was loaded from
        // - `error`: The error that happened when trying to load (if any)
        // - `data`: The raw data that was loaded
        // also may contain other properties based on the middleware that runs.
    });

// throughout the process multiple signals can be dispatched.
loader.onProgress.add((event) => {}); // called once per loaded/errored file
loader.onError.add((target,event,error) => {}); // called once per errored file
loader.onLoad.add((target) => {}); // called once per loaded file
loader.onComplete.add(() => {}); // called once when the queued resources all load.

從範例可以看出,我們可以用onProgressonErroronLoadonComplete
來取得現在的下載進度,並且根據所傳入的參數來更新loading page要顯示的資訊。



開始載入連連看圖檔

新增一個檔案名為ResourcesList.ts,用來設定要載入的圖片並設定一個識別id給它。
其內容如下:

class Resources{
    public id:string;
    public path:string;

    constructor(id, path) {
        this.id = id;
        this.path = path;
    }
}
export class ResourcesList{
    public static img = [
        new Resources('bunny','assets/bunny.png'),
        new Resources('background','assets/background.png'),
        new Resources('Button','assets/Button.json'),
        new Resources('Character_Idle','assets/Character_Idle.json'),
        new Resources('Character_Jump','assets/Character_Jump.json'),
        new Resources('Character_Laugh','assets/Character_Laugh.json'),
        new Resources('Icon','assets/Icon.json')
    ];
}

接著新增Loader.ts檔案,用來載入並監控下載進度。

import { ResourcesList } from "./ResourcesList";
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((event) => {
            console.log("onProgress: ",event);
        });
        //載入檔案錯誤時
        this.loader.onError.add((target, event, error) => {
            this.failedFiles.push(error.name);
            console.log("onError: ",error);
        });
        //每個檔案載入時都會呼叫
        this.loader.onLoad.add((event, target) => {
            this.completedFiles.push(target.name);
            console.log("onLoad: ",target);
        });
        //全部下載完成後
        this.loader.onComplete.add(() => {
            if (this.failedFiles.length == 0){
                console.log("all file completed");
            } else{
                console.log("Loading...failed: could not load "+ this.failedFiles);
            }
        });
    }
}

並在Main.ts裡加上

        //載入素材
        Loader.load();



觀察事件觸發時機

從console視窗可以看到我們在Loader內所下的log被觸發的時機

從上圖可知:

  • onProgress:每一段時間都會更新現在下載的進度
  • onError:有載入失敗的圖檔會呼叫這個func,然後繼續執行後面的圖檔的載入動作
  • onLoad:每一個檔案下載完成都會呼叫這個function,載入一個spritesheet的json檔案,會呼叫兩次onLoad,一次是json載入,一次是載入這個json裡所指定要使用到的png檔案
  • onComplete:全部載入完成後會呼叫,要注意即使中間有檔案載入失敗也會呼叫此function



今日成果

線上展示:http://claire-chang.com/ironman2018/1030/
今日檔案下載:ironman20181030


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

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