Chapter 13

LoadingSceneを途中で入れる

alkn203
alkn203
2021.09.12に更新

insert-loadingscene

任意のタイミングでロードシーンを入れる方法

ゲーム冒頭ロードではなく、任意のタイミングでロードシーンを入れてアセットを読み込む方法について説明します。

LoadingSceneクラスを使ったアセットのロード

デフォルトでは、ゲーム開始直後のLoadingSceneでアセットの読み込みが行われますが、今回は、ボタンが押された後にLoadingSceneを追加して、アセットが読み込まれるようにします。

// アセット
var ASSETS_PREV = {
  // 画像
  image: {
    'tomapiko': 'https://rawgit.com/phinajs/phina.js/develop/assets/images/tomapiko_ss.png',
  },
};

var ASSETS_AFTER = {
  // 画像
  image: {
    'nasupiko': 'https://cdn.jsdelivr.net/gh/phinajs/phina.js@develop/assets/images/character/nasupiyo.png',
    'buropiko': 'https://cdn.jsdelivr.net/gh/phinajs/phina.js@develop/assets/images/character/buropiyo.png',
    'meropiko': 'https://cdn.jsdelivr.net/gh/phinajs/phina.js@develop/assets/images/character/meropiyo.png',
    'mikapiko': 'https://cdn.jsdelivr.net/gh/phinajs/phina.js@develop/assets/images/character/mikapiyo.png',
    'takepiko': 'https://cdn.jsdelivr.net/gh/phinajs/phina.js@develop/assets/images/character/takepiyo.png',
  },
};
  • 開始時に読み込まれるアセットと追加で読み込むアセットを分けて定義します。

LoadingSceneを自作する

// 自作ローディングシーン
phina.define('MyLoadingScene', {
  // デフォルトのLoadingSceneを継承
  superClass: 'phina.game.LoadingScene',
  // コンストラクタ
  init: function(options) {
    this.superInit(options);
    // メソッド上書き
    this.gauge.onfull = function() {
      // 次のシーンへ
      this.exit();
    }.bind(this);
  },
});
  • phina.game.LoadingSceneクラスを継承したMyLoadingSceneを作成します。
  • ゲージが満タンになった時に発火するthis.gauge.onfullの処理を上書きします。
  • これは最低限のカスタマイズですので、自分でロード中の文字などを表示することもできます。

main関数にシーンのリストを渡す

/*
 * メイン処理
 */
phina.main(function() {
  // アプリケーションを生成
  var app = GameApp({
    // 開始シーン指定
    startLabel: 'scene01',
    // アセット読み込み
    assets: ASSETS_PREV,
    // シーン登録
    scenes: [
      {
        className: 'Scene01',
        label: 'scene01',
        nextLabel: 'myloading',
      },
      {
        className: 'MyLoadingScene',
        label: 'myloading',
        arguments: { assets: ASSETS_AFTER },
        nextLabel: 'scene02',
      },
      {
        className: 'Scene02',
        label: 'scene02',
      },
    ]
  });
});
  • main関数には独自のシーンのリストを引数で与えることができます。
  • 今回は、最初のシーンと次のシーンの間にローディングシーンを挿入しています。
  • ポイントは、ローディングシーンのコンストラクタに arguments: { assets: ASSETS_AFTER }として、アセットを引数で与えるところです。

サンプルコード

コードを見る
// グローバルに展開
phina.globalize();
// アセット
var ASSETS_PREV = {
  // 画像
  image: {
    'tomapiko': 'https://rawgit.com/phinajs/phina.js/develop/assets/images/tomapiko_ss.png',
  },
};

var ASSETS_AFTER = {
  // 画像
  image: {
    'nasupiko': 'https://cdn.jsdelivr.net/gh/phinajs/phina.js@develop/assets/images/character/nasupiyo.png',
    'buropiko': 'https://cdn.jsdelivr.net/gh/phinajs/phina.js@develop/assets/images/character/buropiyo.png',
    'meropiko': 'https://cdn.jsdelivr.net/gh/phinajs/phina.js@develop/assets/images/character/meropiyo.png',
    'mikapiko': 'https://cdn.jsdelivr.net/gh/phinajs/phina.js@develop/assets/images/character/mikapiyo.png',
    'takepiko': 'https://cdn.jsdelivr.net/gh/phinajs/phina.js@develop/assets/images/character/takepiyo.png',
  },
};

var SIZE = 64;
var INDEX = 7;
/*
 * メインシーン
 */
phina.define("Scene01", {
  // 継承
  superClass: 'DisplayScene',
  // コンストラクタ
  init: function() {
    // 親クラス初期化
    this.superInit();
    // 背景
    this.backgroundColor = 'skyblue';
    // スプライト画像作成
    Sprite('tomapiko', SIZE, SIZE)
      .addChildTo(this)
      .setPosition(this.gridX.center(), this.gridY.center())
      .setFrameIndex(7);

    var self = this;

    // ボタン
    Button({text: 'PUSH'})
      .addChildTo(this)
      .setPosition(this.gridX.center(), this.gridY.center(4))
      .on('push', function() {
        // 次のシーンへ
        self.exit();
      });
  },
});
// 自作ローディングシーン
phina.define('MyLoadingScene', {
  // デフォルトのLoadingSceneを継承
  superClass: 'phina.game.LoadingScene',
  // コンストラクタ
  init: function(options) {
    this.superInit(options);
    // メソッド上書き
    this.gauge.onfull = function() {
      // 次のシーンへ
      this.exit();
    }.bind(this);
  },
});
/*
 * 次のシーン
 */
phina.define("Scene02", {
  // 継承
  superClass: 'DisplayScene',
  // コンストラクタ
  init: function() {
    // 親クラス初期化
    this.superInit();
    // 背景
    this.backgroundColor = 'silver';
    // スプライト画像作成
    Sprite('tomapiko', SIZE, SIZE)
      .addChildTo(this)
      .setPosition(this.gridX.center(1), this.gridY.center())
      .setFrameIndex(INDEX);
    Sprite('mikapiko', SIZE, SIZE)
      .addChildTo(this)
      .setPosition(this.gridX.center(-1), this.gridY.center())
      .setFrameIndex(INDEX);
    Sprite('nasupiko', SIZE, SIZE)
      .addChildTo(this)
      .setPosition(this.gridX.center(-3), this.gridY.center())
      .setFrameIndex(INDEX);
    Sprite('buropiko', SIZE, SIZE)
      .addChildTo(this)
      .setPosition(this.gridX.center(3), this.gridY.center())
      .setFrameIndex(INDEX);
    Sprite('meropiko', SIZE, SIZE)
      .addChildTo(this)
      .setPosition(this.gridX.center(-5), this.gridY.center())
      .setFrameIndex(INDEX);
    Sprite('takepiko', SIZE, SIZE)
      .addChildTo(this)
      .setPosition(this.gridX.center(5), this.gridY.center())
      .setFrameIndex(INDEX);
  },
});
/*
 * メイン処理
 */
phina.main(function() {
  // アプリケーションを生成
  var app = GameApp({
    // 開始シーン指定
    startLabel: 'scene01',
    // アセット読み込み
    assets: ASSETS_PREV,
    // シーン登録
    scenes: [
      {
        className: 'Scene01',
        label: 'scene01',
        nextLabel: 'myloading',
      },
      {
        className: 'MyLoadingScene',
        label: 'myloading',
        arguments: { assets: ASSETS_AFTER },
        nextLabel: 'scene02',
      },
      {
        className: 'Scene02',
        label: 'scene02',
      },
    ]
  });
  // fps表示
  //app.enableStats();
  // 実行
  app.run();
});

runstantプロジェクト

https://runstant.com/alkn203/projects/38176a8e