spine-haxeランタイム ドキュメント
ライセンスについて
Spineランタイムをアプリケーションに組み込む前に、必ずSpine Runtimes Licenseを確認してください。
はじめに
spine-haxeランタイムは、レンダラーに依存しないSpineランタイム コアAPIのHaxe実装であるコア モジュールと、starling フレームワークを使用した特定のレンダラー実装で構成されています。spine-haxeはターゲットとしてHTML5を使用してテストされており、現在のところWebGLと互換性があります。
spine-haxeランタイムは、乗算済みアルファを使用しているアトラスと2色ティントを除くSpineのすべての機能をサポートしています。
インストール方法
spine-haxeのコアモジュールの依存関係はゼロです。Starlingを使ったレンダリング実装には openflとstarlingの2つの依存関係があります。spine-haxeを使うには、まず必要な依存関係をすべてインストールする必要があります:
haxelib install starling
依存関係をインストールしたら、spine-haxeの最新版をダウンロードしてインストールしてください:
spine-haxeライブラリはlib.haxe.orgからは利用できないことに注意してください。このため、ライブラリをダウンロードしてzipアーカイブからインストールする必要があります。
サンプル
spine-haxeランタイムには、利用できる機能セットを実演しているいくつかのサンプルが含まれています。
ローカルでサンプルを実行するには:
- あなたのオペレーティングシステム用にGitとHaxeをインストールします。
- haxelibを設定し、必要な依存関係をすべてインストールします。
haxelib install openfl
haxelib run openfl setup
haxelib install starling
- spine-runtimes リポジトリをクローンし、
spine-runtimes/spine-haxe
フォルダに移動して、testコマンドでlimeを実行します:
cd spine-runtimes/spine-haxe
haxelib dev spine-haxe .
lime test html5
これにより、spine-haxeランタイムがビルドされ、ブラウザが開いてウェブページにサンプルが表示されます。 フレームをクリックしてすべてのサンプルを見て、spine-runtimes/spine-haxe/example/src
フォルダにあるコードをチェックしてみてください。
spine-haxeランタイムのアップデート
プロジェクトのspine-haxeランタイムをアップデートする前に、Spineエディターとランタイムのバージョン管理に関するガイドをよく確認してください。
spine-haxeランタイムをアップデートするには、https://esotericsoftware.com/files/spine-haxe/4.2/spine-haxe-x.y.z.zip
から希望のバージョンをダウンロードしてください(x.y.z
の部分は実際に使用したいバージョンに従って変更してください)。それから haxelib install spine-haxe:x.y.z.zip
を実行してください。
注意: spine-haxeパッケージの
major.minor
バージョンを変更した場合、Spineスケルトンを同じmajor.minor
バージョンのSpineエディターで再エクスポートする必要があります。詳しくは「バージョンの同期」を参照してください。
spine-haxeを使用する
spine-haxeランタイムは、乗算済みアルファを使用しているアトラスと2色ティントを除くSpineのすべての機能をサポートしています。
spine-haxeはstarlingをフレームワークとして使用しています。HTML5をターゲットとしてテストされており、現在のところ WebGL でのレンダリングに対応しています。Canvas API によるレンダリングはサポートされていません。
アセットのマネージメント
spine-haxe用にエクスポートする
以下の実行方法については、Spineユーザーガイド内で紹介されています :
スケルトンのデータとテクスチャアトラスをエクスポートすると、以下のファイルが得られます:
skeleton-name.json
またはskeleton-name.skel
: これはスケルトンとアニメーションのデータを含んでいます。skeleton-name.atlas
: これはテクスチャアトラスの情報を含んでいます。- 1つまたは複数の
.png
ファイル: これはテクスチャアトラスの各ページで、スケルトンが使用するイメージを含んでいます。
補足: JSONエクスポートよりもバイナリ形式でのスケルトンエクスポートの方がサイズが小さく、読み込みが速いので、基本的にはそちらを選択したほうが良いでしょう。
これらのファイルを提供する際には、サーバーが正しいMIMEタイプを出力することを確認してください。
Spineアセットの更新
開発中にスケルトンデータやテクスチャアトラスファイルを更新したい時は、単純にSpineエディターから再エクスポートを行なって、Haxeプロジェクト内の既存のファイル(.json
、.skel
、.atlas
、.png
)を置き換えるだけで簡単にこれらのソースファイルを更新できます。
その際、spine-haxeの major.minor
バージョンとエクスポートを行ったSpineエディターの major.minor
が一致していることを確認してください。詳しくは「バージョンの同期」を参照してください。
コアクラス
spine-haxeのAPIはstarlingやopenflに依存しない汎用Haxeランタイムの上に構築されています。プラットフォームに依存しないコアクラスと、Spineスケルトンのロード、クエリ、修正、アニメーションを行うアルゴリズムを提供します。
ここではspine-haxeを使用する際によく見ることになる最も重要なコアクラスについてのみ簡単に説明しています。Spineランタイムのアーキテクチャ、コアクラス、APIの使用法の詳細については、Spineランタイムガイドを参照してください。
TextureAtlas
クラスは、.atlas
ファイルとそれに対応する .png
画像ファイルからロードしたデータを保管します。
SkeletonData
クラスは、.json
または .skel
ファイルからロードされたデータを保管します。このスケルトンデータには、ボーン階層、スロット、アタッチメント、コンストレイント、スキン、アニメーションに関する情報が含まれます。SkeletonData
インスタンスは、通常、それが表すスケルトンで使用されるイメージをソースとする Atlas
(アトラス) も一緒に提供することによってロードされます。これは、Skeleton
インスタンスを作成するための設計図として機能します。複数のスケルトンを同じアトラスとスケルトンデータからインスタンス化し、ロードされたデータを共有することで、ロード時間と実行時のメモリ消費を最小限に抑えることができます。
Skeleton
クラスは、SkeletonData
インスタンスから作成されたスケルトンのインスタンスを格納します。スケルトンは現在のポーズを保管します。つまり、ボーンの位置、スロット、アタッチメント、アクティブなスキンの現在の構成を保管します。現在のポーズは、手動でボーンのトランスフォームを変更するか、より一般的には、AnimationState
を介してアニメーションを適用することで計算されます。
AnimationState
クラスは、スケルトンに適用する(単数または複数の)アニメーションを追跡し、最後のレンダリングフレームと現在のレンダリングフレームの間の経過時間に基づいてそれらのアニメーションを進め、ミックスを行い、スケルトンインスタンスにアニメーションを適用して現在のポーズを設定します。AnimationState
は AnimationStateData
インスタンスに問い合わせ(処理要求)をして、アニメーション間のミキシング時間を取得します。特定のアニメーション間に使用するミキシング時間が無ければデフォルトミックスタイムを取得します。
spine-haxeランタイムはこれらのコアクラスの上に構築されています。
starling用のSpine Haxeランタイム
starling用のspine-haxeでは2つのクラスを公開しています: StarlingTextureLoader
と SkeletonSprite
です。
StarlingTextureLoader
は、starlingで画像を作成および破棄するための、spine TextureLoader
の実装です。
SkeletonSprite
は starling DisplayObject
の拡張で、Spineのアニメーションを再生します。
Spineアセットのロード
スケルトンデータファイル(.json
/.skel
) や .atlas
ファイルのようなSpineアセットは、openfl Assets
クラスを通じてロードされます。
SkeletonSprite
のインスタンスを作成する前に、それぞれのスケルトンファイルやアトラスファイルをロードする必要があります。具体的には以下を使用することができます:
Assets.getText(string)
: は、.json
や.atlas
ファイルのようなテキストベースのアセットをロードします。Assets.getBytes(string)
: は、.skel
ファイルのようなバイナリベースのアセットをロードします。
スケルトンデータを skeleton.skel
というバイナリのスケルトンファイルにエクスポートし、アトラスを skeleton.atlas
というファイルに、対応する1つの skeleton.png
ファイルと一緒にエクスポートしたと仮定すると、次のようにアセットをロードすることができます:
var skeletonFile = Assets.getBytes("skeleton.skel");
アセットがロードされたら、TextureAtlas
と SkeletonData
のインスタンスを取得する必要があります:
var skeletondata = SkeletonData.from(skeletonFile, atlas);
TextureAtlas
コンストラクタが StarlingTextureLoader
のインスタンスを必要とすることに注意してください。StarlingTextureLoader
にアトラスファイルの名前を提供する必要があります。個々のテクスチャアトラスページ画像は、明示的にロードする必要なく、透過的にロードされます。
スケルトンのraw(生の)データとアトラスは、それだけではアニメーションやレンダリングができません。その代わりに、SkeletonSprite
がそれらから構築されます。同じアセットでインスタンス化された SkeletonSprite
は、同じスケルトンデータとアトラスを共有します。
SkeletonSpriteインスタンスの作成
スケルトンのrawデータと対応するアトラスが読み込まれたら、SkeletonSprite
をインスタンス化する前に、AnimationStateData
をインスタンス化する必要があります:
これで SkeletonSprite
をインスタンス化することができます:
var skeletonSprite = new SkeletonSprite(skeletondata, animationStateData);
// SkeletonSpriteをステージのDisplayObjectの子として追加
addChild(spineboy);
SkeletonSprite
コンストラクタは、SkeletonData
と AnimationStateData
を受け取ってインスタンスを生成します。
スケルトンの境界を取得するには、スケルトンで getBounds()
関数を呼び出します。また、SkeletonSprite
で getAnimationBounds(string, bool)
関数を呼び出すと、最初のパラメータとして指定された名前のアニメーションを含む Rectangle
を取得できます。2番目のパラメータは、境界の計算中にクリッピング・アタッチメントを考慮するためのブール値です。SkeletonSprite
の getBounds(DisplayObject)
は常にサイズ0, 0の Rectangle
を返すので、使わないでください。
SkeletonSprite
SkeletonSprite
は、Starling DisplayObjectの拡張で、Skeleton
とそれに関連する AnimationState
の保存、更新、レンダリングをバンドルしています。SkeletonSprite
インスタンスは、前のセクションで説明したように、スケルトンデータとアトラスから作成されます。Skeleton
と AnimationState
には、それぞれ skeleton
フィールドと state
フィールドからアクセスできます。
毎フレーム、SkeletonSprite
コンテナは以下を行います:
AnimationState
の更新AnimationState
をSkeleton
に適用します。Skeleton
のワールド変換を更新し、新しいポーズを生成します。Skeleton
を現在のポーズでレンダリングします。
アニメーションの適用
Spine
コンテナで表示されるスケルトンにアニメーションを適用するには、AnimationState
を使用します。
注意: アニメーショントラックやアニメーションのキューイングなど、より詳しい情報については、Spineランタイムガイドの「アニメーションの適用」を参照してください。
トラック0に特定のアニメーションを設定するには、AnimationState setAnimation
を呼び出します:
最初のパラメーターはトラック、2番目のパラメーターはアニメーションの名前、3番目のパラメーターはアニメーションをループさせるかどうかを指定します。
addAnimation
を使って複数のアニメーションをキューに入れることもできます:
spineObject.state.addAnimation(0, "jump", 2, false);
spineObject.state.addAnimation(0, "run", 0, true);
addAnimation
の最初のパラメーターはトラックです。2番目のパラメーターはアニメーションの名前です。3番目のパラメーターは、このアニメーションが同じトラック上の前のアニメーションと置き換わるまでの時間(ディレイ)を秒単位で指定します。最後のパラメーターはアニメーションをループさせるかどうかを指定します。
上の例では、まず "walk"
アニメーションが再生されます。その2秒後に "jump"
アニメーションが一度再生され、続いて "run"
アニメーションに切り替わり、ループします。
あるアニメーションから別のアニメーションに遷移するとき、 AnimationState
は特定の時間(デュレーション)だけアニメーションをミックス(クロスフェード)します。これらのミックスデュレーションは AnimationStateData
インスタンスで定義され、 AnimationState
はそこからミックスデュレーションを取得します。
AnimationStateData
インスタンスは AnimationState.data
プロパティからも利用できます。以下のようにしてデフォルトのミックスデュレーションや、特定のアニメーションのペアのミックスデュレーションを設定することができます:
spineObject.state.data.setMixByName("walk", "jump", 0.1);
アニメーションを設定または追加すると、TrackEntry
オブジェクトが返されます。これによりアニメーションの再生をさらに変更できます。例えば、アニメーションを逆再生するようにTrackEntryを設定することができます:
entry.reverse = true;
利用できるオプションについて詳しくは TrackEntry
クラスのドキュメントをご覧ください。
注意:
TrackEntry
インスタンスを使用している関数の外部で保持する場合には注意医してください。TrackEntryは内部で再利用されるため、TrackEntryがdisposeイベントを発生させた後は無効になります。
スケルトンをスムーズにセットアップポーズに戻したい場合は、アニメーショントラックに空のアニメーションをセットまたはキューに追加します:
spineObject.state.addAnimation(0, "walk", 0).mixDuration = 0.5;
spineObject.state.addEmptyAnimation(0, 0.5, 6);
setAnimation
と同様に、setEmptyAnimation()
の最初のパラメーターはトラックを指定します。2番目のパラメーターは、前のアニメーションをミックスアウトし、"空の"アニメーションをミックスするために使用するミックスデュレーションを秒単位で指定します。
addAnimation
と同様に、addEmptyAnimation()
の最初のパラメーターはトラックを指定します。2番目のパラメーターはミックスデュレーションを指定します。3番目のパラメーターはディレイ(秒単位)で、このディレイの後に空のアニメーションがミキシングされてトラック上の前のアニメーションと置き換わります。
AnimationState.clearTrack()
を使えばトラック上のすべてのアニメーションを即座にクリアすることができます。すべてのトラックを一度にクリアするには AnimationState.clearTracks()
を使います。しかしこれはスケルトンを最後に適用されたポーズのままにする点に注意してください。通常はこれを使うよりも空のアニメーションを使ってセットアップポーズにスムーズに戻す方が良いでしょう。
スケルトンのポーズをセットアップポーズに戻すには、Skeleton.setToSetupPose()
を使います:
これはボーンとスロットの両方をセットアップポーズの設定にリセットします。ボーンだけをリセットしたい場合はSkeleton.setBonesToSetupPose()
を、スロットだけをリセットしたい場合は Skeleton.setSlotsToSetupPose()
を使用してください。
AnimationStateイベント
AnimationState
は、再生中のアニメーションのライフサイクル中に様々なイベントを発行します。必要に応じてこのイベントをリッスンすることで、それらに反応させることができます。SpineランタイムのAPIでは、以下のイベントタイプを定義しています:
start
: アニメーションが開始された時に発されます。interrupt
: アニメーションのトラックがクリアされた、または新しいアニメーションが設定されたなどにより中断された時に発されます。end
: アニメーションが二度と適用されない時に発されます。dispose
: アニメーションのTrackEntryが破棄された時に発されます。complete
: アニメーションが1ループを完了するごとに発されます。event
: ユーザーが定義したイベントが発生した時に発されます。
イベントを受け取るには、AnimationStateListener
コールバックを、すべてのアニメーションでイベントを受信するAnimationState
か、キューされた特定のアニメーションの TrackEntry
に登録します:
spineObject.state.onStart.add(entry -> trace('Started animation ${entry.animation.name}'));
spineObject.state.onInterrupt.add(entry -> trace('Interrupted animation ${entry.animation.name}'));
spineObject.state.onEnd.add(entry -> trace('Ended animation ${entry.animation.name}'));
spineObject.state.onDispose.add(entry -> trace('Disposed animation ${entry.animation.name}'));
spineObject.state.onComplete.add(entry -> trace('Completed animation ${entry.animation.name}'));
spineObject.state.onEvent.add((event entry) -> trace('Custom event for ${entry.animation.name}: ${event.data.name}'));
// コールバックをTrackEntryに追加する
var trackEntry = spineObject.state.setAnimationByName(0, "walk", true);
trackEntry.onEvent.add((entry, event) => trace('Custom event for ${entry.animation.name}: ${event.data.name}'));
詳しくは EventsExample.hx
をご覧ください。
スキン
多くのアプリケーションやゲームでは、髪や目、ズボン、イヤリングやバッグなどのアクセサリーなど、さまざまなアイテムを組み合わせてカスタムアバターを作ることができます。Spineでは、複数スキンを組み合わせることでこれを実現することができます。
以下のようにして、他のスキンからカスタムスキンを作成することができます:
const skin = new spine.Skin("custom");
skin.addSkin(skeletonData.findSkin("skin-base"));
skin.addSkin(skeletonData.findSkin("nose/short"));
skin.addSkin(skeletonData.findSkin("eyelids/girly"));
skin.addSkin(skeletonData.findSkin("eyes/violet"));
skin.addSkin(skeletonData.findSkin("hair/brown"));
skin.addSkin(skeletonData.findSkin("clothes/hoodie-orange"));
skin.addSkin(skeletonData.findSkin("legs/pants-jeans"));
skin.addSkin(skeletonData.findSkin("accessories/bag"));
skin.addSkin(skeletonData.findSkin("accessories/hat-red-yellow"));
spineObject.skeletonskin = skin;
spineObject.skeleton.setToSetupPose();
まず、コンストラクタ Skin()
で新しい空のスキンを作成します。
次に、スケルトンから SkeletonData
を取得します。これは SkeletonData.findSkin()
でスキンを名前から探すのに使用します。
Skin.addSkin()
で新しいスキンにまとめたいスキンをすべて追加します。
最後に、Skeleton
に出来上がった新しいスキンをセットし、Skeleton.setSlotsToSetupPose()
を呼び出して、以前のスキンやアニメーションのアタッチメントが残らないようにします。
完全なコード例は MixAndMatchExample.hx
で確認できます。
ボーンのトランスフォームの設定
Spineエディター内でスケルトンを構築する際、スケルトンは、スケルトンのワールド座標系または「スケルトン座標系」と呼ばれるもので定義されます。この座標系は、Haxeの座標系と一致しない場合があります。そのため、例えば、ユーザーがタッチでボーンを動かせるようにする場合などは SkeletonSprite
に相対するマウス座標やタッチ座標をスケルトン座標系に変換する必要があります。
SkeletonSprite
は haxeWorldCoordinatesToBone(point, bone)
というメソッドを提供しています。このメソッドは SkeletonSprite
からの相対点を受け取り、指定されたボーンからの相対点をスケルトンの座標系に変換します。
逆にスケルトン座標系からHaxe座標系へ変換したい場合は、SkeletonSprite.skeletonToHaxeWorldCoordinates(point)
で実現できます。
完全なコード例は ControlBonesExample.hx
で確認できます。
SpineランタイムのAPI呼び出し
starling用のspine-haxeは、SkeletonSprite
プロパティの skeleton
、state
、state.data
を通してコアAPI全体を公開しています。一般的なSpineランタイムガイドと同様に、これらのクラスのJSドキュメントを参照してください。
最小限のプロジェクトセットアップ
Starlingを使用してHaxeでSpineアニメーションを実行したいだけの場合や、Spineアニメーションを含むプロジェクトを開始したい場合は、以下の手順に従ってください。
必要な依存関係をすべてインストールしたら、以下のようにして新しいプロジェクトを作成します:
これで MySpineProject
という名前のフォルダが作成され、OpenFLで空のプロジェクトを実行するのに必要なすべてのファイルが格納されるので、MySpineProject
をお好みのhaxe IDEで開いてください。Assets
フォルダにアセットをコピーします。project.xml
ファイルを編集し、以下のように依存関係としてspine-haxeを追加します:
もし .skel
バイナリスケルトンをロードしたい場合は、以下の行を:
以下に置換してください。(そうしないとopenflは skel
ファイルをテキストとしてロードしてしまい、ファイルが壊れてしまいます):
<assets path="Assets" rename="assets" include="*.skel" type="binary" />
次に Source/Game.hx
ファイルを開き、コンストラクタを以下のものに変更してください:
super ();
var atlas = new TextureAtlas(
Assets.getText("assets/raptor.atlas"),
new StarlingTextureLoader("assets/raptor-pro.atlas"));
var skeletondata = SkeletonData.from(Assets.getText("assets/raptor-pro.json"), atlas, .5);
var animationStateData = new AnimationStateData(skeletondata);
var skeletonSprite = new SkeletonSprite(skeletondata, animationStateData);
skeletonSprite.x = Starling.current.stage.stageWidth / 2;
skeletonSprite.y = Starling.current.stage.stageHeight * .75;
skeletonSprite.state.setAnimationByName(0, "walk", true);
addChild(skeletonSprite);
Starling.current.juggler.add(skeletonSprite);
}
必要なクラスをインポートすることを忘れないように注意してください。IDEからコードを実行するか、プロジェクトフォルダでターミナルから以下のコマンドを実行してください:
VS Code セットアップ
IDEとしては、以下の拡張機能を持つVisual Studio Codeを使用することをお勧めします:
これらの拡張機能は、自動補完、デバッグ、ビルドサポートなどのIDE機能を提供します。
ビルドをデバッグするには、VS Codeの下部にあるステータスバーの対応するLimeターゲットを HTML5 / Debug
などに設定します。F5
キーを押して、lime
の実行設定を実行します。