Aseprite製スプライトシートを使うためのphina.jsのプラグイン作った

はじめに

ゲーム用ドット絵を描く際の個人的推しドローツールであるAsepriteで制作したスプライトシートを、 同様に推しゲームフレームワークのphina.jsで使うにあたって、 多少の拡張が必要だったのでプラグインを作った。

phina-aseprite-loader

以下、使い方です。

想定しているバージョン

  • Aseprite v1.2.9
  • phina.js v0.2.3

Asepriteでのスプライトシート作成

とにもかくにもまずはAsepriteで出力したスプライトシートが無いと何も始まりません。

なので適当なアニメーションを描きます。

f:id:pentamania:20181127213932g:plain

作成手順

  1. 頑張ってアニメーションのためのフレーム(コマ)を数枚描く
  2. タイムライン上で各フレームを指定してtagをつける(上で”walk”とある名札。walk?🤔)
  3. Fileの「Export Sprite Sheet」で出力。
  4. Output FileとJSON DataにチェックしてExport
  5. またFrame Tagsオプションにチェックを入っていることも確認

f:id:pentamania:20181127221101p:plain

スプライトシートの画像とjsonファイル(それぞれneko-larva.png, neko-larva.json)が用意できたら実際に使い方に進みます。

f:id:pentamania:20181127215935p:plain

プラグインのインストール

プラグインをnpmモジュールとして使う場合は

npm install -S phina-aseprite-loader

でインストール。

そして

import * as phina 'phina.js';
import 'phina-aseprite-loader';

とすれば準備完了。

ブラウザで直接読み込む

もしくはライブラリをダウンロードなどした後に、 ブラウザのscriptタグで読み込む伝統的スタイルも使えます。

<script src='path/to/phina.js'></script>
<script src='path/to/phina-aseprite-loader.js'></script>

CDNもあります。

<script src='https://cdn.jsdelivr.net/npm/phina-aseprite-loader@0.2.0/dist/phina-aseprite-loader.min.js'></script>

これでLoaderとFrameAnimationクラスが拡張され、 Asepriteの出力したスプライトシートjsonファイルを読み込んで使うことができるようになります。

使い方

phina.main(function() {
  var app = phina.game.GameApp({
    startLabel: 'main',
    backgroundColor: "#7496E4",
    // ロード
    assets: {
      image: {
        neko: "assets/neko-larva.png", // exported sprite sheet image
      },
      aseprite: {
        neko_ss: "assets/neko-larva.json",  // exported json
      },
    },
  });

  app.run();
});

phina.define('MainScene', {
  superClass: 'phina.display.DisplayScene',

  init: function(options) {
    this.superInit(options);

    var sprite = this.sprite = phina.display.Sprite('neko')
      .setScale(4)
      .setPosition(this.width, this.height*0.5)
      .addChildTo(this)
    ;
    var animation = phina.accessory.FrameAnimation("neko_ss")
      .attachTo(sprite);
    animation.setNext("walk", "walk"); // walkの次にwalkをセットして無限ループ
    animation.gotoAndPlay("walk");
  },

  update: function() {
    this.sprite.x--; // 左に向かって進む
  },

});

f:id:pentamania:20181127215442g:plain

ビルトインのスプライトシート機能ではjsonを読み込む際は"spritesheet"というプロパティでしたが、そこをasepriteとします。

またnextプロパティが指定できないので、苦肉の策としてsetNextというメソッドを用意していますが、 その他は基本的に「phina.jsでフレームアニメーションを使う」手順と一緒です。

ちなみにフレームプロパティにはdurationというフレーム表示時間を設定する項目がありますが、それもphina.js側でもちゃんと反映されるようになってます。

sliceとpivot機能(実験的)

AsepriteにはSliceというツールがあります。

本来は画像の一部分を切り出した範囲を指定するための機能(多分)ですが、 ある程度メタデータをもたせることもできるので、これを利用してpivot指定機能を入れました。

Asepriteのsliceツールで適当に範囲を選択した後、 右クリックでslice propertyを開き、名前を「pivot」にして、 pivot項目を指定しておくと、 プログラム側でssオブジェクトを通して、その値を取得することができます。

f:id:pentamania:20181127214429p:plain

var animation = phina.accessory.FrameAnimation("tomapiko_ss")
console.log(animation.ss.pivot); // => {x:33 , y:37}

これでスプライトの中心点をマークして、setOriginで原点指定したりすることが可能です。

ただslice機能自体が結構新しく、挙動が若干怪しい・そのうち仕様変更があるかもしれないということで、 試験的な機能になります。

個人的にはslice以外にメタデータ受け渡し手段があるとうれしいけど…。

課題とか

フレーム順指定が限定的

アニメーションのフレーム順は[4,5,6]みたいな連番指定しかできず、 例えば[4,5,4,1,2]のような変則的な設定は(Aseprite上)ではできません。

これはAsepriteの仕様上、仕方なさそう。ただ個人的にはあまり不便は感じていない。

nextも指定できない

アニメーション後に別のアニメーションを実行するnextプロパティも指定できない。 これもAsepriteの仕様上(ry

干渉することもあるかも?

プラグインはFrameAnimationクラスを拡張しています。 あまり無いとは思いますが、自前もしくは他の拡張と干渉しないように注意が必要です。 これについては専用の派生クラスを用意すべきかが迷いどころ…