Spineの制御と描画


Game Maker Language リファレンス > 組み込み関数 用途別 > 2D グラフィック機能 > Spineの制御と描画

Spineの制御と描画

不具合情報

  • アニメーションのブレンド skeleton_animation_mix() は HTML5 ターゲットで正常に動作しないようです

GameMaker:Studioにおける Spineの制御

Spineの基本的な再生方法

GameMaker:Studioでは、Spineはスプライトとして扱われます。 Spineツール側でエクスポートで出力した *.json ファイルを スプライトエディタから import し、そのスプライトを オプジェクトに登録するだけで再生が可能です。

描画はスプライトと同じように扱われるため、draw_self() で描画が可能です。細かくパラメータを指定したい場合は、draw_skeleton()を使用します。

※注意点
Spineデータの import 後、スプライトの画面を閉じずにプロジェクトを終了すると、次回起動時にSpineスプライトの読み込みエラーが発生する可能性があります。そのため import 後は スプライトの画面を閉じて保存しておくのが安全です

rootボーンに対するアニメーションは動作しない

rootボーンの座標やスケール値などはGameMaker:Studio から直接指定するため、rootボーンに対するアニメーションは無効となります。 rootボーン に別のボーンをぶら下げて、rootボーン以外でアニメーションを実装する必要があります。


コリジョンデータは Spineに定義する

Spineスプライトを使うとGameMaker:Studio側のコリジョンマスクは無効となります。 そのため、コリジョンは Spine側で定義する必要があります。 もしくはボーンの座標を skeleton_bone_state_get() で取得し、それをもとにコリジョンを動的に作って判定します。

GameMaker:Studio 上ではアニメーションデータは編集できない

Spineスプライトのアニメーションデータを GameMaker:Studio 側から書き換えることはできません。 アニメーションの編集は Spine側で行う必要があります。

テクスチャのサイズ制限について

利用可能なSpineデータのテクスチャサイズは、環境によって制限がかかります

  • モバイルデバイス:1024 x 1024 まで
  • デスクトップ・コンソール:2048 x 2048 または 4096 x 4096 まで

Spineスプライトを制御するパラメータ

Spineスプライトは、GameMaker:Studio上のスプライトとほぼ同じものとして扱えるため、以下のインスタンス変数とスプライトプロパティで制御が可能です

  • x:中心座標X
  • y:中心座標Y
  • sprite_index:Spineスプライト番号
  • sprite_width:Spineスプライトの幅
  • sprite_height:Spineスプライトの高さ
  • sprite_xoffset:Spineスプライトの描画オフセットX
  • sprite_yoffset:Spineスプライトの描画オフセットY
  • image_alpha:α値
  • image_angle:回転角度
  • image_blend:色
  • image_xscale:Xスケール値
  • image_yscale:Yスケール値
  • image_speed:アニメーション再生速度 (※1)
  • image_index:再生中のSpineアニメーションフレーム数 (※2)
  • image_number:再生中のSpineアニメーション フレームの総数 (※2)
※1
image_speed に "0" を指定するとアニメーションを停止することができます。また "負の値" を指定すると逆再生します
※2
image_index は Real の数値であることに注意します。またimage_index は image_number の値以上とならないため正確な最終フレーム数を判定することが難しいです。例えば image_number が "30" の場合に、 image_index の1フレームあたりの増加数が "0.25" である場合、image_indexの最大値は "29.75" までしか進みません。

透過部分がグレーになる現象の回避方法

「エクスポート > パック設定」の「乗算済みアルファ」のチェックを外すと回避できます。(もしくは実行時に乗算ブレンドモードで描画? ※未検証)

alpha_darkening.png

GameMaker:Studio2 で動作する Spineの機能

一通りは動いている印象です。以下の機能は問題なく動いていました。

  • アニメーション
  • ボーン制御
  • メッシュ変形
  • IKコンストレイント
  • トランスフォームコンストレイント
  • クリッピング
  • バウンディングボックス

動作バージョンの注意点

GameMaker:Studio2 で動作する Spineのバージョンは最新より古い可能性があります。
(※2020/3/12 現在 [ v2.2.5.481 ] 動作するのは「Ver. 3.7.94」)
(※2021/1/14 現在 [ v2.3.1.542 ] 動作するのは「Ver. 3.7.94」)
(※2021/11/28 現在 [ v2.3.7 ] Spine v4.0に対応 )

最新の対応状況は以下のページから確認可能です

Spineはデータフォーマットのバージョンを上げると、それよりも下のバージョンにできなくなるので、GameMaker:Studio側の対応が完了しない限り、古いバージョンで固定する必要があります。

Trackについて

GameMaker:Studio2 における Spineの制御 (正確には Spineランタイムが提供している機能) では、Trackという概念を使用することができます。
Trackとは、複数のアニメーションを混在して動作させる機能です。 例えば下半身の足の動きと、上半身の銃を構える動き、この2つのアニメーションを Trackに登録することで、アニメーションを組み合わせて動作させることが可能となります。 Track は、skeleton_animation_set_ext() で登録を行い、skeleton_animation_clear() で消去します。

アタッチメントについて

アタッチメントを使用すると、特定のボーンにスプライトを追従させることが可能です。例えば手に剣や盾を装備させたり、頭に帽子をかぶらせたりするなどです。 skeleton_attachment_create() でアタッチメントを生成し、skeleton_attachment_set() でアタッチを行います。

アタッチ後はスロットとして扱われるので、skeleton_slot_* の関数で情報の変更が可能です。

Spineを制御する関数


アニメーション

スキン

スキンを使うとテクスチャを入れ替えてキャラクターの色変えや見栄えの変更をすることができます。

アタッチメント

アタッチメントは特定のボーンに対してスプライトの画像を追従させます。 例えば、剣や盾などの装備品を手に持たせることが可能となります。

ボーン

スロット

  • skeleton_slot_list():指定のSpineスプライトに登録されているスロット名を ds_list で取得します
  • skeleton_slot_data():指定のSpineスプライトに登録されているスロットの詳細情報を ds_list (さらに ds_map が詳細情報が入れ子になる) で取得します
  • skeleton_slot_data_instance():指定のSpineスプライトに登録したアタッチメントのスロット詳細情報を ds_list (さらに ds_map が詳細情報が入れ子になる) で取得します
  • skeleton_find_slot():座標 (x, y) 指定でスロットを検索します
  • skeleton_slot_colour_set():指定のスロットに色とα値を設定します
  • skeleton_slot_colour_get():指定のスロットの色を取得します
  • skeleton_slot_alpha_get():指定のスロットのα値を取得します

その他

  • skeleton_get_minmax():再生中のSpineスプライトのバウンディングボックスの最小値(左上座標)と最大値(右下座標)を取得します
  • skeleton_get_num_bounds():再生中のSpineのバウンディングボックスの数を取得します
  • skeleton_get_bounds():バウディングボックスの情報を取得します

描画

Spine専用のアニメーションイベント

Spineスプライトを使用している場合のみ以下の Objectイベント が発生します

  • Animation Update:ボーンのアニメーションの計算が確定する直前に呼び出されるイベント
  • Animation Event:Spine側のアニメーションで設定したイベントが発生した際に呼び出されるイベント
  • Animation End:アニメーションが終端に達した直後に発生するイベント (※通常のスプライトでも発生するイベント)

Animation Update

This event is designed only for use with the Skeletal Animation Functions. It is a special event that is triggered every step in an instance that uses a skeletal animation sprite, and is designed to "intercept" the bone data after the orientation of the bones has been calculated for the current animation state but before this data is committed to use for drawing. This allows you to make modifications to the bone data using the appropriate functions.

このイベントは Spineスプライト でのみ使用するように設計されています。 Spineスプライトを使用するインスタンスのすべてのステップでトリガーされる特別なイベントであり、 現在のアニメーション状態に対してボーンの方向が計算された後、このデータを描画に使用するためにコミットされる前にボーンデータを「インターセプト」するように設計されています。 これにより、適切な関数 (skeleton_bone_state_set())を使用してボーンデータを変更できます。

Animation Event

Spine側のアニメーションで設定したイベントが発生した際に呼び出されるイベントです。
Spine側の設定方法については以下のページを参照。

これを使用することで、アニメーションの特定のタイミングでSEを再生したり、エフェクトを発生させる、といった制御が可能となります。
このイベントが発生した場合、"event_data" に ds_map データとして、以下のパラメータが設定されます。

  • name:イベント名
  • track:再生中のアニメーションのTrack番号 (デフォルトは "0")
  • integer:イベントに設定した整数値 (アニメーションイベントで設定した値, デフォルトは "0")
  • float:イベントに設定した浮動小数値 (アニメーションイベントで設定した値, デフォルトは "0.0")
  • string:イベントに設定した文字列 (アニメーションイベントで設定した値, デフォルトは空の文字列 "")

例えば "Animation Event" イベントに以下のような記述をすると、イベント発生時に Output に設定したイベント情報が出力されます

show_debug_message("index: " + string(image_index)); // アニメーションフレーム数
show_debug_message("name: " + string(event_data[? "name"])); // イベント名
show_debug_message("track: " + string(event_data[? "track"])); // track数
show_debug_message("integer: " + string(event_data[? "integer"])); // 整数値
show_debug_message("float: " + string(event_data[? "float"])); // 浮動小数値
show_debug_message("string: " + string(event_data[? "string"])); // 文字列

その他 GameMaker:Studio上でのテクニック

ループなしで1回のみ再生したい

GameMaker:StudioでのSpine再生は常にループ再生を行います。 そのため、例えば1回だけ再生を行いたい場合には、以下のような制御が必要です。

// 再生開始時の処理
image_index = 0; // 0フレーム目から再生する
image_speed = 1; // 等速再生.
// 停止判定
if(image_index >= image_number-1) {
  // 最終フレームに達したのでアニメーション停止.
  image_speed = 0;
}

image_indexはimage_numberと同じ値になることはないので、"image_number-1"として近似的に最終フレームかどうかの判定をしています。 上記処理は、正確には最後の1フレーム近くを省略していますので、もし気になる場合は 1フレーム多めにデータを作っておいた方が良いかもしれません。

ループなしで1回のみ再生したい (Animation End イベントを使う方法)

Animation End イベントでアニメーションが終端に達したタイミングを取ることが可能です。

// アニメーション停止
image_speed = 0;

上記コードを Animation Endイベントに記述すると、1回再生が可能となります。 ただ、Animation Endイベントは Spineスプライトが登録されていないときにも有効となっているので、もし1つのオブジェクトで複数の Spineスプライトを切り替える場合は、Createイベントで "sprite_index = noone" と記述し、Animation Endイベントの記述を以下のようにします。

if(sprite_exists(sprite_index)) {
  // Spineスプライトが存在する場合のみ、ループ時に停止する
  image_speed = 0;
}

再生するSpineを動的に割り当てたい

sprite_index に Spineスプライトを指定すると、自動で読み込みが行われます。

sprite_index = spr_spine; // Spineスプライト "spr_spine" を割り当て

上記のように記述すると、1つのオブジェクトで、複数の Spineスプライトを扱うことができます。

Spineとの当たり判定を実装したい

実装方法はいくつかありますが、ここでは簡単に実装できるものを紹介します。

  1. skeleton_find_slot() を使用する
  2. skeleton_get_bounds() を使用する

skeleton_find_slot() は指定したX/Y座標に存在するスロットのリストを取得できる関数です。これにより指定の位置にあるスロット名を取得して判定を行うことができます。ただし問題点として、この関数で取得されるスロットは画像のサイズとなり画像の透過部分も衝突範囲とみなされます

より細かな判定をしたい場合は、skeleton_get_bounds() を使用します。この関数は Spine側で指定したバウンディングボックスの頂点情報を取得します。これにより取得した頂点情報を使って point_in_triangle()rectangle_in_triangle() などで衝突判定を行うことができます。


ボーンの座標を直接書き換える

ボーンの座標を書き換える場合は "Animation Update" イベントで座標を変更する必要があります。
以下はマウスの座標に向かってボーンを移動させる例です。 ("xofs" と "yofs" は Createイベントであらかじめ 0 に初期化しておいたものです)

// "hand" ボーンの座標を移動させる
var name = "hand";

// 基本ポーズの情報を取得する
skeleton_bone_data_get(name, bone_map);
var lx = bone_map[? "x"]; // ボーンのローカル座標(X)を取得
var ly = bone_map[? "y"]; // ボーンのローカル座標(Y)を取得

// アニメーションの現在の情報を取得
skeleton_bone_state_get(name, bone_map);

var px = bone_map[? "worldX"]; // ワールド座標Xを取得
var py = bone_map[? "worldY"]; // ワールド座標Yを取得
var dx = mouse_x - px; // マウス座標Xへの距離を計算する
var dy = mouse_y - py; // マウス座標Yへの距離を計算する
if(mouse_check_button(mb_left)) {
  // 左クリックしていたら5%の距離を移動する
  xofs += dx * 0.05; // あらかじめ定義したオフセット座標Xに足し込む
  yofs += dy * 0.05; // あらかじめ定義したオフセット座標Yに足し込む
}
else {
  // 左クリックしていなかったら元の座標に戻る(0に近づける)
  xofs *= 0.97;
  yofs *= 0.97;
}

// ローカル座標を上書き.
bone_map[? "x"] = lx + xofs;
bone_map[? "y"] = ly - yofs; // Y軸は逆になることに注意!

// アニメーションデータを上書き
skeleton_bone_state_set(name, bone_map);

注意点は基本ポーズのローカル座標の情報を skeleton_bone_data_get() で取得しておき、その座標のオフセットを使ってskeleton_bone_state_set() で上書きを行うようにします。理由としてはアニメーションのローカル座標を書き換えると、ワールドの値も変化するため、基本ポーズを基準に座標を設定する必要があるからです。
また、ローカル座標Yはスクリーン座標と向きが逆になることにも注意します。

その他情報

公式ブログの情報

Wiki内検索

#search(): You already view a search box

MENU

ドキュメント

GMLリファレンス

2ch

その他



最新の30件

2024-03-07 2023-08-09 2023-05-21 2023-05-20 2023-05-04 2022-10-13 2022-07-21 2022-07-02 2022-04-06 2021-11-30
  • Spineの制御と描画
2021-11-26 2021-10-03 2021-09-23 2021-08-15 2021-06-02 2021-01-23 2021-01-21 2021-01-19 2021-01-18 2021-01-16 2021-01-15

人気の10件

今日の10件



これまでの訪問者: 6277
今日の訪問者: 1
昨日の訪問者: 3
閲覧者: 4