G.D.M

「 Game Development Memo 」 の略称。 ゲーム開発の備忘録

 

スポンサーサイト 

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

category: スポンサー広告

TB: --    CM: --

Sprite Studioのアニメーションデータ( .ssbpファイル )のパーサー完成 

ゼミで制作しているゲームでSprite Studioを使おうということになったので、
公式で提供されているSSConverterの出力データである.ssbpファイルのパーサーを
数週間ほどかけて黙々と作成していたのだが、ようやく完成したため公開する。
※ ソースはこの記事の一番下


SSConverterは以下参考
コンバータの使い方 Ss5Converter


パーサーの使い方はこんな感じとなった。


#include "SpriteStudioLoader.h"

GALib::SpriteStudio::SSDataChunkPtr g_p_ss_data_chunk;

void Func()
{
g_p_ss_data_chunk = SpriteStudio::LoadSSData("character_template_comipo/character_template1.ssbp",
GALib::SpriteStudio::ABSOLUTE_COORDINATE);
}


SpriteStudioLoader.hをインクルードしLoadSSData関数に.ssbpファイルへのパスの指定と、
座標系の種類の設定( デフォルトは絶対座標 )を行うことで、データを取得できる。
取得したデータはSSDataChunkPtr型となっており、
これはshaderd_ptrであるため解放処理は必要ない。
あとはこのデータを元にスプライトを構築し、アニメーションを再生すればよい。


続いて、実装部分について。
まずパース時の処理のおおまかな流れは以下のようになっている。

--------------------------------------------------------------------
( エンディアンの確認・コンバータの有効化 )
      ↓
バッファを全て読み取る
      ↓
バージョンとIDの確認
      ↓
セル・セルマップのデータを取得
      ↓
アニメーションパックの取得
  → アニメーションデータの取得
     → パーツ・ラベルの取得( とデータを絶対座標系に変換 )
        → 各フーレムのデータを取得
      ↓
 構築したデータの出力
--------------------------------------------------------------------


各データの取得方法は.ssbpファイルはバイナリデータなので、最初に読み取ったバッファを
そのデータの構造に合わせた構造体にキャストしてやり、取得する。
.sspbファイルに対応した構造体はSpriteStudioParseAPI.hに全て定義してある。


static SSDataChunkPtr s_Parse(void* p_buffer, eDataType data_type)
{
assert(p_buffer);

ProjectData* p_PROJECT_DATA = reinterpret_cast<ProjectData*>(p_buffer);


}


フォーマットは以下参考
SpriteStudio/SpriteStudio5-SDK バイナリファイルのフォーマット


また各データにはバッファからのオフセット値がメンバとなっていて、
基本的にそのオフセットを利用し、データの構築を行う仕組みになっている。
この仕組みを簡単に行うためのクラスが以下のコードのDataShifterである。


static void s_GetCellData(const ProjectData* p_PROJECT_DATA, CellData* p_out_cell_data)
{
DataShifter projct_data_shifter(p_PROJECT_DATA);

const Parse::OffsetType CELLS_OFFSET = s_endian_converter.Convert(p_PROJECT_DATA->m_cells_offset);

const Parse::S_Cell* p_CELLS
= reinterpret_cast<const Parse::S_Cell*>(projct_data_shifter.GetData(CELLS_OFFSET));


}



これらの方法で大体のデータは取得できるが、各フレームのデータなどは
.ssbpファイルには変更した最低限のデータしか入っておらず、残りは初期値を参照する
ような方法で取得になっているため、最初にバッファからどのデータが入っているか判断するための
フラグを取得した後、そのフラグを参考にデータを取得する。
このとき取得するデータに合わせてバッファをそのバイト数分ずらす必要があるため、
そこではDataReaderというクラスを作成し、用いた。


static void s_GetFrameData(DataReader& r_frame_data_reader,
S_Part& r_part,
const Parse::S_InitialFrameData* p_INITIAL_FRAME_DATA,
S_FrameData* p_out_frame_data)
{
Uint32 part_flags = r_frame_data_reader.ReadAsUint32();

// 各データを取得
p_out_frame_data->m_cell_index = (part_flags & Parse::PART_FLAG_CELL_INDEX) ? r_frame_data_reader.ReadAsInt16() : s_endian_converter.Convert(p_INITIAL_FRAME_DATA->m_cell_index);
p_out_frame_data->m_position_x = (part_flags & Parse::PART_FLAG_POSITION_X) ? static_cast<float>(r_frame_data_reader.ReadAsInt16()) : static_cast<float>(s_endian_converter.Convert(p_INITIAL_FRAME_DATA->m_position_x));
p_out_frame_data->m_position_y = (part_flags & Parse::PART_FLAG_POSITION_Y) ? static_cast<float>(r_frame_data_reader.ReadAsInt16()) : static_cast<float>(s_endian_converter.Convert(p_INITIAL_FRAME_DATA->m_position_y));


}


以上を踏まえて、あとはgithubのソースの方を参照して欲しい。

ちなみに今回作成したパーサーはもともとコンシューマ環境( C++03のコンパイラ )で動く
ように書いたコードなのだが、公開するうえで複数のヘッダファイルへ依存すると面倒だったため、
C++11の標準で提供されているAPIに直せる部分は若干直しておいた。
さらにコンシューマ環境ではエンディアンの問題も発生したため、作成したパーサーには
データをその時の環境にあったエンディアンに直すコードが書かれている。

また公開したgithubのリポジトリのSpriteStudio/Player/
に入っているSpriteAnimationPlayerが実際にパーサーから取得したデータを
再生するテストに利用したクラスが書かれているファイルなのだが、
そこで利用しているヘッダファイルは私の利用しているライブラリへの依存性が高く、
全て公開するのは厳しいとみたので省いておいた。
あくまでこのクラスは再生時の大まかな流れを知るためのサンプルとして見ること。


ソース( ご自由にどーぞ )
risaki-masa/SpriteStudioParser


スポンサーサイト

category: パーサー

TB: --    CM: 0

プロフィール

カレンダー

最新記事

カテゴリ

検索フォーム

ツイッター

GitHub

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。