処理の流れとKLScene
KLib
KLibについては、まずこちらの記事を参照ください。
KLibのメインループ
KLibの処理の流れをざっくり説明すると
- iOSのメインループからKLibのメインループ(KLScene)がコールされる
- KLSceneにメインループにしたい関数(シーン関数)を設定する
- 毎ループその関数が呼ばれるので場面に応じて処理する関数を切り替える
を繰り返してゲーム全体の処理を切り替えます。
シーンの設定
シーンの設定はKLScene_ChangeTo関数で行います。
ここでは自作のタイトル画面用シーンに切り替える例を示します。
シーン関数は
void YourFuncName( KLObj*, void* )
という型の関数であれば、どんな名前でも構いません。
上記図でいう所の右上の初期化関数「Title_Init」がそれにあたります。
まずはこのような関数を定義し、初期化処理を関数内に記述します。
それを
KLScene_ChangeTo( Title_Init, NULL );
のように渡すことで次回ループから設定したTitle_Initが呼ばれるようになります。
第二パラメータは何かパラメータを受け渡したい時に使用します。なければNULLで構いません。
シーンワーク
シーンにはKLibが事前に確保したシーン用のヒープ(シーンワーク)が用意されています。
KLibユーザーはこのシーンワークを同じシーン内に限り
またがって自由に参照・書き換えができます。
シーンワークは各シーン任意の構造体として定義する事ができますが、
構造体の先頭の変数は必ずKLObjでなければいけません。
自分で作成したシーンワーク構造をシーンオブジェクトと呼びます。
例)
typedef struct{ KLObj core; // シーンオブジェクトにしたい構造体の先頭は必ずKLObjを配置する int drawposx, drawposy; // あとはワークサイズ以内に収まれば何を定義しても良い // 他いろいろ定義したい変数 // ・ // ・ // ・ }TitleScene;
KLibが事前に確保したシーンワークのポインタは、
先ほどシーン関数の引数にあった、KLObj*に入って渡されてきます。
このKLObj*を自分の作成したシーンオブジェクト型にキャストすると利用できます。
void Title_Init( KLObj* pObj, void* pParam ){ TitleScene* p = (TitleScene*)pObj; // KLibシーンワークを自作シーンオブジェクトにキャスト // シーンオブジェクトの初期化を行う p->drawposx = 128; p->drawposy = 256; }
シーン内での関数切り替え
これでKLibのメインループに最初のシーンの初期化関数を割り当てる事ができましたが、
以後、毎メインループにタイトル画面初期化関数をまたコールされては困ります。
そこで、初期化関数の最後にKLObj_SetFunctionを追加し
次回からは、シーンオブジェクトはそのまま使うけど、シーン関数は切り替えるという方法を取ります。
// 初期化後のメインループ void Title_Main( KLObj* pObj, void* pParam ){ TitleScene* p = (TitleScene*)pObj; // KLibシーンワークを自作シーンオブジェクトにキャスト // 描画とか } void Title_Init( KLObj* pObj, void* pParam ){ TitleScene* p = (TitleScene*)pObj; // KLibシーンワークを自作シーンオブジェクトにキャスト // シーンオブジェクトの初期化を行う p->drawposx = 128; p->drawposy = 256; KLObj_SetFunction( pObj, Title_Main ); //<-追加 }
こうすることで、次回からはTitle_Initではなく
Title_Main関数が呼ばれる事となります。
KLObj_SetFuntionとKLScene_ChangeToは似ていますが、
シーンが変わってしまうとシーンワークの内容が保証されないので注意してください。
アンロード関数の登録
場合によっては初期化関数の中でmallocやnewをして
シーンが変わるタイミングでfreeなりdeleteなりしたい事が出てくると思います。
そのような時の為に、シーンが切り替わり
現在のシーンがアンロードされるタイミングでコールバックする関数を指定する事ができます。
初期関数に以下のように追加します。
KLObj_SetUnload( pObj, Title_Unload ); //<-追加
これで、タイトル画面のシーンが終わる時に
Title_Unloadがコールされるので、Title_Unloadを同様に定義し
中で解放処理を行うといった事が可能になります。