【パラパラアニメ等、描画に速度を必要とする場合(スプライトの使用)】



●全 般
 ゲームを起動してから最初に描画する際、表示するピクチャを保存場所から読み込むため、多少時間が必要となる。
 このため、パラパラアニメの各マスを連結した画像(※)を1枚用意しておき、これを読み込んだ後、表示する部分のみ切り出して描画すると、遅延なく表示できる。
 (※)VX以前の戦闘アニメの素材ファイルのようなもの。というか、そのもの。
 PCにダウンロードしてプレイしていれば、イベントのピクチャ表示や$gameScreen.showPictureで遅延はないが、アツマール等のデータ保存先がPCにない場合には、スプライトを使用した方がよい。


●基本的な描画の処理

○記述の前提等
元のピクチャファイル名 testpic.png
元のピクチャの保存先 img/pictures
tPicData 「元のピクチャ」を読み込んだもの
sx 「元のピクチャ」から切り取る部分の左上座標のうち、X座標 
sy 「元のピクチャ」から切り取る部分の左上座標のうち、Y座標 
sw 「元のピクチャ」から切り取る部分の横幅 
sh 「元のピクチャ」から切り取る部分の縦幅 
dx 「絵を描くスペース」内のX座標
dy 「絵を描くスペース」内のY座標
tX 画面における「絵を描くスペース」の左上座標のうち、X座標 
tY 画面における「絵を描くスペース」の左上座標のうち、Y座標 
tZ 「絵を描くスペース」を描画するレイヤ(Z座標) 


○描画するための関数
 JTest = async function(){
  // 画像データの読み込み
  var tPicData = ImageManager.loadPicture("testpic");

  // 画像データ読み込み完了までウェイト
  while(tPicData._loadingState === "loading"){
   await JWait(1);
  }

  // 「絵を描くスペース」の設定(ビットマップの設定)
  var tDrawSpace = new Bitmap(bw, bh);

  // 「絵を描くスペース」に、画像データを書き込み
  tDrawSpace.blt(tPicData, sx, sy, sw, sh, dx, dy);

  // 「絵を描くスペース」をスプライトに設定
  var tPicture = new Sprite(tDrawSpace);

  // スプライトの「画面上の位置座標」を設定
  tPicture.move(tX, tY);

  // スプライトの表示レイヤ設定
  tPicture.z = tZ; // 絵のレイヤの位置を設定
  
  // スプライトの表示
  SceneManager._scene.addChild(tPicture);
  
  // スプライトの移動
  // 10ms毎に1ドットX座標を増加→180ドット右へ移動
  for(let i = 1; i <= 180; i++){
   tPicture.move(tX + i, tY);
   await JWait(10);
  }

  // 「絵を描くスペース」の指定範囲の削除
  // (0, 0)〜(100, 100)の範囲に書かれている絵を消す。
  tDrawSpace.clearRect(0,0, 100, 100);

  // スプライトの移動
  // 10ms毎に1ドットX座標を減少→180ドット左へ移動
  for(let i = 1; i <= 180; i++){
   tPicture.move(tX - i, tY);
   await JWait(10);
  }

  // スプライトの消去
  SceneManager._scene.removeChild(tPicture);
  
  // 「絵を描くスペース」の消去
  tDrawSpace.clear();
  var tDrawSpace = null;

 }



○簡単な補足説明
JTest = async function(){
 // 画像データの読み込み
 // 画像データ読み込み完了までウェイト

 画像データの読み込みは「ImageManager.loadPicture("testpicture")」で行うが、この関数はJavascriptの仕様上、並列処理されてしまう。このため、「画像データ読み込み完了までウェイト」において読み込みが完了するまで、次の処理実行を一時的に停止させる処理が必要となる。この一時停止の処理がないと、読み込みが終わる前に次の処理に進んでしまい、ピクチャデータが空の状態で各処理が行われるため、何も表示されない。
 この一時停止の処理で使っている「JWait」は「ウェイトさせる関数(自作)」だが、この関数も並列処理されないように、「await」を頭につけて呼び出さなければならない。そのためには、元の関数である「JTest」を「async function」と定義しなければならない。
 「JWait」については、「プラグイン内でウェイトをする処理【成功版】」を参照


// 「絵を描くスペース」の設定(ビットマップの設定)
 // 「絵を描くスペース」に、画像データを書き込み

 ビットマップは「絵を描くスペース」のことで、スプライトは「画面上で動かす(表示するを含む。)もの」のイメージ。
 「絵」を書いたり消したりするのは、あくまで「絵を描くスペース」を操作する。
 ここでは、「絵を描くスペース」を「メモリ上」に作成し、その後、元のピクチャファイルから指定する範囲をコピーして、「絵を描くスペース」に貼り付ける。
 なお、「tDrawSpace.blt(tPicData, sx, sy, sw, sh, dx, dy);」は実行する度に「絵を描くスペース」に絵を重ねていく。


// 「絵を描くスペース」をスプライトに設定
 // スプライトの「画面上の位置座標」を設定
 // スプライトの表示レイヤ設定
 // スプライトの表示

 「絵を描く場所」を「メモリ上」に作った後で、それをスプライト(画面上で動かす(表示するを含む。)もの)だと指定し、表示する。
 画面上で動かすものは、あくまでスプライトとなる。
 座標やレイヤの指定は、「SceneManager._scene.addChild(tPicture);」で表示した後でも設定可能だが、フレーム更新より前に実行されないと、初期状態で一瞬表示されてしまうことがあるので、事前に設定した方がよい。


// スプライトの移動
 イベントコマンド($gameScreen.showPicture)で表示したピクチャと違い、勝手に移動させてくれる処理はないので、1回1回座標を設定して表示していく必要がある。
 キャラクターの歩行グラのように足踏みしながら移動させたい場合に有効な処理。
 ただし、「パラパラアニメ」が作りたいだけであれば、大きな「絵を描くスペース」(ビットマップ)上に描画・削除を繰り返せばよいので、わざわざスプライトを動かす必要はあまりない。(細部後述)


// 「絵を描くスペース」の指定範囲の削除
 スプライトとして表示した後でも、「絵を描くスペース」に書かれた絵を書いたり消したりすることができる。
 「tDrawSpace.clearRect(0,0, 100, 100);」は、「絵を描くスペース」内の指定された範囲(相対座標)の絵を単純に消去する処理。「絵を描くスペース」そのものは消えない。
 「絵を描くスペース」にはレイヤがないので、何度か書き込んでいたとしても、消去すればその範囲の絵は全て消える。


// スプライトの消去
 // 「絵を描くスペース」の消去

 スプライト自体を消去して画面から消す。
 「絵を描くスペース」の消去においてわざわざ絵を消しているが、特にやらなくてもよさげ。文法上は単純に最後の「nullを代入」だけでなくなるはず。



●パラパラアニメ(戦闘アニメのようなもの)を作る場合


○パラパラアニメ(戦闘アニメのようなもの)を作る場合、ピクチャを1枚1枚読み込んで表示していては遅延が生じるため、初めに全てのコマを組み合わせた画像ファイルを読み込み、必要な時に必要なコマをコピーして、「絵を描くスペース」(ビットマップ)に貼り付けていく。
○画面いっぱいに作成した「絵を描くスペース」に、必要なコマを表示したい座標に貼り付け表示する。その後一度消去し、次のフレームに表示するコマを貼り付ける、を繰り返す。
○要するにツクールVX以前の戦闘アニメの編集とほぼ同じなので、それを少しいじってみればイメージがわく。
○そもそも同じ仕組みなので、アニメの表示前から絵を描画していたり、アニメ終了後も絵を残しておく必要がないなら、イベントのアニメーションの表示を使えばよい。(アニメを表示させるダミーイベントの設置は必要)

元のピクチャ
左上の数字はコマID
「絵を描くスペース」
各コマを時系列に応じて配置・消去していく


○描画するための関数
 JTest2 = async function(){
  // 画像データの読み込み
  var tPicData = ImageManager.loadPicture("MotionJob1W");

  // 画像データ読み込み完了までウェイト
  while(tPicData._loadingState === "loading"){
   await JWait(1);
  }

  // 「絵を描くスペース」の設定(ビットマップの設定)
  var tDrawSpace = new Bitmap(816, 624);

  // 「絵を描くスペース」をスプライトに設定
  var tPicture = new Sprite(tDrawSpace);
  tPicture.z = 20; // 絵のレイヤの位置を設定

  // 絵の「画面上の位置座標」を設定
  var tX = 0;
  var tY = 0;
  tPicture.move(tX, tY);

  // パラパラアニメ事前計算
  // 各コマの左上座標リスト作成
  var tSquareWidth = 336; // 1コマの幅
  var tSquareHeight = 336; // 1コマの高さ
  var tXSquareNum = tPicData.width / tSquareWidth; // 横マスの個数
  var tYSquareNum = tPicData.height / tSquareHeight; // 縦マスの個数
  var tMaxSquareNum = tXSquareNum * tYSquareNum; // 総マス数
  var tSquareCoordinateArray = [0]; // 各コマの左上座標リスト初期設定
  for(let i = 0; i <= tMaxSquareNum - 1; i++){
   var tTmpX = tSquareWidth * (i % tXSquareNum);
   var tTmpY = tSquareHeight * Math.floor(i / tXSquareNum); // ここは「X」(横マスの個数)でよい
   tSquareCoordinateArray[i] = [tTmpX, tTmpY]; // リストへの書き込み
  }

  // 初期コマの描画
  var tSquareID = 0; // マスのID 左上が0
  var tDX = 0; // 画像を表示するビットマップ上のX座標
  var tDY = 0; // 画像を表示するビットマップ上のY座標
  tDrawSpace.blt(tPicData, tSquareCoordinateArray[tSquareID][0], tSquareCoordinateArray[tSquareID][1],
          tSquareWidth, tSquareHeight, tDX, tDY);

  // スプライトの表示
  SceneManager._scene.addChild(tPicture);

  // 更新までの待機及び描画消去
  await JWait(1000);
  tDrawSpace.clear();

  // 2コマ目の表示
  var tSquareID = 1;
  var tDX = 48; // 画像を表示するビットマップ上のX座標
  var tDY = 48; // 画像を表示するビットマップ上のY座標
  tDrawSpace.blt(tPicData, tSquareCoordinateArray[tSquareID][0], tSquareCoordinateArray[tSquareID][1],
          tSquareWidth, tSquareHeight, tDX, tDY);

  // 更新までの待機及び描画消去
  await JWait(1000);
  tDrawSpace.clear();

  // 3コマ目の表示
  var tSquareID = 2;
  var tDX = 96; // 画像を表示するビットマップ上のX座標
  var tDY = 96; // 画像を表示するビットマップ上のY座標
  tDrawSpace.blt(tPicData, tSquareCoordinateArray[tSquareID][0], tSquareCoordinateArray[tSquareID][1],
          tSquareWidth, tSquareHeight, tDX, tDY);

  // 更新までの待機及び描画消去
  await JWait(1000);
  tDrawSpace.clear();

  // 4コマ目の表示
  var tSquareID = 4;
  var tDX = 128; // 画像を表示するビットマップ上のX座標
  var tDY = 128; // 画像を表示するビットマップ上のY座標
  tDrawSpace.blt(tPicData, tSquareCoordinateArray[tSquareID][0], tSquareCoordinateArray[tSquareID][1],
          tSquareWidth, tSquareHeight, tDX, tDY);

  // スプライトの消去
  SceneManager._scene.removeChild(tPicture);
  // ビットマップの消去
  tDrawSpace.clear();
  var tDrawSpace = null;
 }



○簡単な補足説明
// 画像データの読み込み
 // 画像データ読み込み完了までウェイト
 // 「絵を描くスペース」の設定(ビットマップの設定)
 // 「絵を描くスペース」をスプライトに設定
 // 絵の「画面上の位置座標」を設定

 「絵を描くスペース」内で各コマを表示させるため、画面全体を覆う大きさの「絵を描くスペース」を設定
 この例では画面全体を覆っているので、座標は(0, 0)で設定している。
 描画範囲が特定の部分に限られるのであれば、その大きさで作り、適切な座標を指定すればよい。


// パラパラアニメ事前計算
 // 各コマの左上座標リスト作成

 必須ではないが、後のコマ座標の指定がわかりやすくなるように、元のピクチャ内の各コマを切り抜く時に使う座標を計算し、配列にしておく処理。
 元のピクチャは上にある図を参照
 各コマのIDは、上にある図が示すように、左上から0で始まり、右にいくにつれ+1となる。
 元ピクチャのサイズは、各コマの縦・横サイズが統一されていれば、縦横どちらに何枚並べてもよい。


// 初期コマの描画
 // スプライトの表示

 「絵を描くスペース」内の最初のコマを書く座標を指定し、その後スプライトを表示して画面に表示


// 更新までの待機及び描画消去
 次のコマに切り替えるまで、一定時間ウェイトをする処理。
 ここでは100ms(1秒)に指定しているが、好きな時間を設定すればよい。
 ちなみに、30fpsならウェイトは約33ms、60fpsならウェイトは約17msとなる。
 「tDrawSpace.clear();」は、「絵を描くスペース」に書かれた絵を全て消去する処理。
 複数のコマを表示していて、そのうちの1つだけを消去したい場合は、「●基本的な描画の処理」で説明した「tDrawSpace.clearRect(0,0, 100, 100);」を使う。


// 2コマ目の表示」以降
 表示するコマのIDと「絵を描くスペース」内の座標を設定したのちに書き込む。
 IDを指定しているのは「各コマの左上座標リスト作成」で作成したリストから呼び出すための処理なので、必須ではない。
 面倒でなければ「tDrawSpace.blt」内に直接数値や別の変数を書き込んでもよい。



戻る