連載
» 2009年11月27日 00時00分 公開

スプライトアニメーションはゲーム開発の超基本“BREW”アプリケーション開発入門(5)(3/3 ページ)

[末永貴一(エイチアイ),@IT MONOist]
前のページへ 1|2|3       

アニメーションの実行

 最後に、スプライトでアニメーションをさせてみたいと思います。

 アニメーションをさせるためには、“繰り返しの実行”が必要になり、“時間制御”も必要になります。

 連載第3回「BREWアプリケーションの構成を理解しよう!」で、BREWのイベント処理を確認しましたが、ソーステンプレートからも分かるように、BREWプログラミングでは基本的にイベントドリブンのプログラミングを行います。

 つまり、何らかのイベントが発生しない限りは、対象となる処理が実行されないことを意味します。そのため、アニメーションに必要な制御可能なイベント処理として、「コールバック」機能が提供されています。

コールバック

 BREWでコールバックを実装するには、「CALLBAKC_Init()」と「ISHELL_Resume()」を利用します。

 「CALLBAKC_Init()」には、状態を保存する「AEECallback」構造体、コールバック関数、コールバック関数に通知する値を設定します。「CALLBAKC_Init()」で設定された関数は、「ISHELL_Resume()」で「BREW AEE(Application Execution Environment)」に登録され、イベントループが次回行われた際に、登録された関数を自動的に呼び出します。

 以下は、これまで作成したスプライト処理をコールバック機能でアニメーションさせるサンプルです(ソース3)。

void animeSprite(anime2d* pMe){
        uint32 now_time;
        now_time = ISHELL_GetUpTimeMS (pMe->a.m_pIShell);       // 最新時間の取得
        // 一定時間以上経過している場合は、描画更新を実行
        if ((now_time - pMe->OldTime) > 30)
        {
                pMe->OldTime = now_time;       // 時間更新
                // 飛行機のアニメーション(エンジン)
                if(pMe->plane_anime < 3){
                        pMe->spriteCmd[0].unSpriteIndex = pMe->plane_anime;
                        pMe->plane_anime++;
                } else {
                        pMe->plane_anime = 0;
                }
                // 飛行機のアニメーション(上移動)
                if(pMe->spriteCmd[0].y > -64){
                        pMe->spriteCmd[0].y--;
                } else {
                        pMe->spriteCmd[0].y = pMe->DeviceInfo.cyScreen;
                }
                IDISPLAY_ClearScreen (pMe->a.m_pIDisplay);     // 画面クリア
                ISPRITE_DrawSprites(pMe->pISprite, &pMe->spriteCmd[0]);
                IDISPLAY_Update(pMe->a.m_pIDisplay);
        }
                // コールバック登録
                CALLBACK_Init (&pMe->Callback, (PFNNOTIFY)animeSprite, pMe);
                ISHELL_Resume (pMe->a.m_pIShell, &pMe->Callback);
} 
ソース3 スプライト処理をコールバック機能でアニメーションさせる

 状態維持の「AEECallback」構造体、更新時間の「OldTime」変数、スプライトインデックス用の変数は、関数をまたぐため、「Applet」構造体の下位に定義します。

AEECallback Callback;           // コールバックの状態維持
uint32 OldTime;                 // 更新時間の格納
int plane_anime;                // スプライトインデックス 

 また、時間取得の関数「ISHELL_GetUpTimeMS()」を利用していますので、以下のヘッダをインクルードします。

#include "AEEStdLib.h" 

 この関数呼び出しは、「EVT_APP_START」などのイベントから適宜呼び出します。無論、この関数の呼び出し前には今回説明した「spriteInit()」「drawSprite()」を呼び出しておく必要があります。例えば、以下のような記述になります。

case EVT_APP_START:
        spriteInit(pMe);        // スプライト描画のための準備
        drawSprite(pMe);        // スプライト描画
        animeSprite(pMe);       // スプライトを利用したアニメーション 
描画結果 図7 描画結果

 ここでは、まずアニメーションを更新する「時間(フレームレート)」を設定するために「ISHELL_GetUpTimeMS()」を使用して、デバイス起動からの時間を取得し、これを更新時間のタイミングに利用しています。なお、ソース3では、30ミリ秒ごとにアニメーションを行うようにしています。

 実際に、スプライトをアニメーションさせている部分は、「AEESpriteCmd」構造体の画像インデックスが格納された「unSpriteIndex」と、スクリーンY座標が格納された「y」の変更です。「unSpriteIndex」のインデックスを変更することにより、描画される画像が変化するため、飛行機の噴射口がアニメーションし、「y」を変更することにより、飛行機が前進する(画面の上に動く)ようになります。

 これらの値を30ミリ秒ごとに変更しているため、その秒間隔でのスプライトの変化が起こることになります。最後に、「CALLBAKC_Init()」と「ISHELL_Resume()」によるコールバック登録に、自身の関数を登録することで、「BREW AEE」からのコールバックが行われ、繰り返しの実行となります。

※注2:BREWのコールバックには、そのほかにも「ISHELL_SetTimerEX()」を使ったタイマー処理による実装もあります。しかし、「ISHELL_Resume()」を利用した方が、速度的なアドバンテージがあるため、今回は「ISHELL_Resume()」での実装を紹介しました。




 今回は、プログラムを単純化するために動きを自動にしましたが、キー操作を行うイベント処理や、そのほかのオブジェクトの描画、当たり判定などを実装することで、よりゲームらしいプログラムを作ることも可能です。

 さて、次回からは2Dグラフィックスに比べ、より高い表現力を持つ「3Dグラフィックス」について解説したいと思います。お楽しみに!(次回に続く)

前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.