スプライトを表示してみよう


ここからは初級編という事で余計な説明は省きます。
コンパイルなどの説明は入門編を読んで下さい。

SGDKには便利で高機能なスプライトエンジンが実装されていますが、

現バージョン(2016年1月31日時点)では処理が重くスプライトが多く必要になるゲームには向いていません。
なのでスプライトエンジンを使わない方法でスプライトを描画します。


メガドライブは最小8x8最大32x32ピクセルのスプライトが最大80枚使えます(横256モードの場合は64枚)
背景面とスプライトではVRAMの並び順が違います。
画像をスプライトとして使う場合はスプライト用の方法で読み込みます。

 

画像を一つ用意し、その画像をスプライトとして表示するプログラムを作ります。

1、スプライト用の画像を用意する。

SGDKはBMP形式あるいはPNG形式で16色の画像をスプライトとして扱えます。
色はRGB333bitの計9bit(512色)の色が表示可能で、SGDKは9bitの画像では無い場合に自動で類似色を9bitに合わせて変換します。
パレットは一番目の色が透明色になります。パレットが操作出来るEdge等のソフトで透明色を設定して下さい。
メガドライブで表示出来るスプライトの最大の大きさは32x32ピクセルですが、それよりも大きな画像を扱いたい場合は複数のスプライトに別ける必要があります。
今回は一枚のスプライトで収まる横24ピクセル縦32ピクセルの画像を描画します。

2、画像のリソースを読み込む。

SGDKに用意されているrescompを使ってスプライト画像のリソースを読み込みます。

画像を表示してみようの3、リソース設定ファイルの作成と同じ要領で

resフォルダの中に.resファイルを作り、以下のようにスプライトの画像を設定します。

 SPRITE player_sprite "player.png" 3 4 -1

最後の3 4 -1は
3 xが3x8=24ピクセル
4 yが4x8=32ピクセル
-1 圧縮を指定せずオート圧縮

3、VRAMに画像を読み込む。

ROMからVRAMに画像をコピーします。

 VDP_loadTileSet(player_sprite.animations[0]->frames[0]->frameSprites[0]->tileset, pattern,0);

frames[]は同じ画像内の別フレームに使用する。
frameSprites[]はスプライトが32x32に入りきらなかった場合に使用する。

DMAについて

スプライトを設定、更新する為にはVRAMにアクセスする必要があります。
DMAを使うとVDPがメインメモリとVRAMにアクセスして高速に処理します。
DMAはBlank期間中に使えます。

VDP_loadTileSet関数の最後にある引数はDMA使用のフラグです。
このチュートリアルではVDP_loadTileSetでDMAを使っていません。

Blankについて

メガドライブは常に画面を表示をしていますが、表示期間以外の短いインターバルの事をBlankと呼びます。
Blank期間はDMAを使って高速にVRAMにアクセスが出来ます。
画面表示は左上からスタートします。
左から右へ1ラインずつ下に向かって描画していきます。
1ラインの描画が終わり一段下の左に戻る時に発生するインターバルをHorizontal blankと呼びます。
全ての描画が終わりスタート地点の左上に戻る時に発生するインターバルをVertical blankと呼びます。
VRAMにアクセスする処理をVertical blank中にまとめて処理すると高速に動作するプログラムが書けます。

4、スプライトを設定する。

スプライトを表示する為にスプライトの設定をします。

VDP_setSprite(index, pos_x, pos_y, SPRITE_SIZE(size_x, size_y),TILE_ATTR_FULL(pallet, priority, vertical_flip, horizontal_flip, tile_index), next_index);

メガドライブのスプライトは0番目から初めてリンク先の番号にジャンプして処理を続けます。
途中でリンク先を0番目にすると処理を終わらせる事が出来ます。
描画優先度は0番目が一番高いです。(おそらく描画は逆向きに処理しているのかもしれません)

 

SPRITE_SIZE(size_x, size_y)はマクロになっていて1~4のスプライトのサイズを指定します。
スプライトサイズの単位は1セル8x8です。

TILE_ATTR_FULL(pallet, priority, vertical_flip, horizontal_flip, tile_index)もマクロです。
パレット番号、優先順位、x軸反転、y軸反転、VRAMアドレスを指定します。

VDP関数について

 

VDP_setSpriteはVRAMにあるスプライトアトリビュートテーブルを設定する関数ですが、その場で更新せずにsprite list cacheというキャッシュにまとめて保存されます。

VDP_setSpriteDirectなどのDirect系の関数はキャッシュせず直接更新するので

Blankのタイミングできちんと更新すればこちらの関数の方が処理速度が速いらしいです。

このチュートリアルではキャッシュを使う方法を選択してます。

5、スプライトを更新する。

このチュートリアルではsprite list cacheというキャッシュを使っているので
このキャッシュされたリストを実際にVRAMに転送する必要があります。

//VBlank開始後に割り込む関数
void VBlank_func()
{
    VDP_updateSprites();//スプライトの更新
}

VBlank中に割り込みを使ってスプライトを更新してます。

停止したスプライトを表示するだけではつまらないのでサンプルではスプライトを回転運動させています。
回転運動の処理にはSGDKに用意されているsinテーブルを使ってます。



以下今回のソースコードです。

今回のソースコードとは別にさらに実践的なスプライトのサンプルも一緒に付けておきました

良かったら参考にして下さい。