[gameMain.cpp]
今回もヘッダは変更しないのでプログラム側だけです。
●ヘッダ追加
ウィンドウ管理のヘッダを追加して下さい。 ●定数
メニュー用の定数を追加します。
// メニューの状態
enum {
MENU_STATE_TOP, //メニューTOP
MENU_STATE_POWER, //つよさ
MENU_STATE_ITEM, //アイテム
MENU_STATE_MAGIC, //まほう
MENU_STATE_MAX, //メニューの状態の数
};
イベントとメニューに関連したデータを追加します。
// ゲーム本編のデータの構造体。
typedef struct {
GameMainInitType_t initType; //初期化タイプ
int bFirstInit; //一回目の初期化済みのフラグ。
STATEMNG_OBJECT StateObj; //ゲーム本編の状態管理オブジェクト
int beforeBattleInState; //バトル開始前の状態
// マップ移動に関連したデータ
MapMoveInfo_t mapMoveData;
// イベントに関連したデータ
int msg_winno; //メッセージ・ウィンドウの番号
// メニューに関連したデータ
STATEMNG_OBJECT MenuStateObj; //メニューのオブジェクト
} GameMainData_t;
●GameMain_Init
ゲーム本編の初期化に追加します。
// 初回?
if( s_GameMainData.bFirstInit == FALSE ) {
s_GameMainData.bFirstInit = TRUE;
・
・
中略
・
// メニューの状態管理オブジェクトの作成。
s_GameMainData.MenuStateObj = STM_Init(MENU_STATE_MAX);
}
ゲーム本編の終了にメニューの状態管理オブジェクトの破棄を追加します。
//----------------------------------------------------------------------
// ゲーム本編の終了
//----------------------------------------------------------------------
void GameMain_End()
{
// ゲーム本編の状態管理オブジェクトの破棄
STM_End(s_GameMainData.StateObj);
// 主人公キャラオブジェクトの破棄。
char_Delete(s_GameMainData.mapMoveData.PlayerObj);
// マップ管理の終了
map_End();
// メニューの状態管理オブジェクトの破棄
STM_End(s_GameMainData.MenuStateObj);
}
イベント処理に仮のメッセージ処理を組み込みます。
※ 将来的には別のものと置き換わります。
基本的なところは序章で作った仮のものと大差はありません。
winmng_SetFrame()で今のフレーム数をセットして、最初のフレームならwinmng_DelAllWin()で念のため全ウィンドウを破棄を破棄します。winmng_NewWin()関数で新しいウィンドウを作成して
winmng_SetMsg()でメッセージを設定します。ここまでが初期化ですね。
で、winmng_UpdateMsg()で毎フレーム更新します。メッセージの速度は5フレームに1文字です。
もし、メッセージが終了したらwinmng_DelWin()でウィンドウを破棄して次の状態に遷移します。
まだ表示が続く場合は、mapMove_Draw()でマップとキャラを表示した上にwinmng_Draw()で最新のウィンドウを実際に描画します。
そこから下は基本前のままですが、メッセージ位置などは調整されているのとRキーが強制的に移動モードになるボタンになっています。
//----------------------------------------------------------------------
// イベント中
//----------------------------------------------------------------------
static void GameMain_Event()
{
// 今のフレーム
int frame = STM_GetFrameCount(s_GameMainData.StateObj);
// 今のフレームをウィンドウ管理に設定。
winmng_SetFrame(frame);
// 最初のフレーム?
if( frame == 0 ) {
// 念のため全ウィンドウを破棄
winmng_DelAllWin();
// ウィンドウを生成してメッセージを設定。
int posy = 380;
s_GameMainData.msg_winno = winmng_NewWin(40/2,posy,(SCREEN_X-40),90,"テスト・ウィンドウ");
winmng_SetMsg("*「テストメッセージですよ。このウィンドウで禁則もテストするので色々書きますよ。」じつはプロポーショナル・フォントを使っています。等幅はカッコ子悪くて。\n"
"連続改行のテスト。\n"
"連続改行のテスト。\n"
"連続改行のテスト。\n"
"連続改行のテスト。",
TRUE );
}
// 毎フレームの更新
if( winmng_UpdateMsg(5) ) {
// メッセージが終了ならばウィンドウを消去。
winmng_DelWin(s_GameMainData.msg_winno);
// シナリオを次に進める。
// 次のフレームで遷移。
STM_ChangeState(s_GameMainData.StateObj,GAMEMAIN_STATE_MOVE);//マップ移動へ遷移。
}
// マップとキャラクタ表示処理
mapMove_Draw(&s_GameMainData.mapMoveData,frame,FALSE);
// 有効なウィンドウの描画
winmng_Draw();
// ↓とりあえずの処理。
// ゲーム本編だよって表示
CenterDrawString( "ゲーム本編です。", 28, 200, GetColor(255,255,255) );
CenterDrawString( "イベント中です。", 20, 260, GetColor(255,255,255) );
// メニューのキー入力
CenterDrawString( "「S」ボタンでお店です。", 20, 300, GetColor(155,255,255) );
if( g_MainData.key[KEY_INPUT_S] == 1) {
STM_ChangeState(s_GameMainData.StateObj,GAMEMAIN_STATE_SHOP);//お店に遷移
return;
}
// イベントのキー入力
CenterDrawString( "「M」ボタンでマップチェンジ。", 20, 320, GetColor(155,255,255) );
if( g_MainData.key[KEY_INPUT_M] == 1) {
STM_ChangeState(s_GameMainData.StateObj,GAMEMAIN_STATE_MAPLOAD);//マップロード処理に遷移
return;
}
// バトルのキー入力
CenterDrawString( "「B」ボタンでバトル発生。", 20, 340, GetColor(155,255,255) );
if( g_MainData.key[KEY_INPUT_B] == 1) {
STM_ChangeState(s_GameMainData.StateObj,GAMEMAIN_STATE_BATTLE_IN);//戦闘開始へ遷移。
return;
}
// 移動のキー入力
CenterDrawString( "「R」ボタンでマップ移動。", 20, 360, GetColor(155,255,255) );
if( g_MainData.key[KEY_INPUT_R] == 1) {
STM_ChangeState(s_GameMainData.StateObj,GAMEMAIN_STATE_MOVE);//マップ移動へ遷移。
return;
}
}
前とまったく違うメニュー編です。
基本的なところは本物と同じになのですが、とりあえずの仮組みです。
s_menuでメニューのリストを定義します。
s_listはつよさの表示用のメッセージリストですね。
winmng_SetFrame()で今のフレーム数をセットして、最初のフレームならwinmng_DelAllWin()で念のため全ウィンドウを破棄を破棄します。winmng_NewWin()関数で新しいウィンドウを作成して
winmng_SetMenu()でメニューを設定します。で状態管理をメニューTOPに設定しています。ここまでが初期化ですね。
で、ここからはメニュー状態で分岐します。
menuFrameは、メニュー状態だけの管理フレームです。
●MENU_STATE_TOP(メニューTOP)の場合。
winmng_SelectMenu()で選ばれているメニューに合わせて状態を遷移します。
もし、メニューボタンを押されたらwinmng_DelAllWinで全ウィンドウを破棄してメニューを抜けて、マップ移動へ遷移します。
●MENU_STATE_POWER(つよさ)の場合。
メニューのフレームが0なら初期化で、つよさウィンドウを作成してつよさパラメータのリストを設定します。
winmng_CheckCloseList()でリストの閉じるのを監視します。閉じられたら、このウィンドウを破棄してメニューTOPの状態に遷移します。
●MENU_STATE_ITEM(アイテム)とMENU_STATE_MAGIC(まほう)の場合。
ほとんどつよさウィンドウと同じなんですが、リストの代わりにメッセージを即表示します。
あとは、いつもと同じでmapMove_Draw()でマップとキャラを表示した上にwinmng_Draw()で最新のウィンドウを実際に描画します。
static void GameMain_Menu()
{
// メニューの処理。今のものウィンドウテストの仮のものです。
static char *s_menu[] = {
"つよさ",
"アイテム",
"まほう",
NULL,//ストッパ
};
enum {
SELECT_POWER, //つよさ選択
SELECT_ITEM, //アイテム選択
SELECT_MAGIC, //魔法選択
};
static char *s_list[] = {
"LV 3",
"exp 15",
"HP 10/30",
"MP 5/12",
"などと表示の予定",
NULL,//ストッパ
};
// 今のゲーム状態のフレーム
int frame = STM_GetFrameCount(s_GameMainData.StateObj);
// 今のゲーム状態のフレームをウィンドウ管理に設定。
winmng_SetFrame(frame);
// 最初のフレーム?
if( frame == 0 ) {
// 念のため全ウィンドウを破棄
winmng_DelAllWin();
// ウィンドウを生成してメニューリストを設定。
int sizex = 150;
int sizey = 100;
int posx = (SCREEN_X-sizex) / 2;
int posy = (SCREEN_Y-sizey) / 2;;
winmng_NewWin(posx,posy,sizex,sizey,"メニュー・ウィンドウ");
winmng_SetMenu(s_menu);
// メニュー状態を初期化
STM_ChangeState(s_GameMainData.MenuStateObj,MENU_STATE_TOP);//メニューTOPに遷移
}
// メニュー状態の更新・フレームカウント
STM_UpdateState(s_GameMainData.MenuStateObj);
int menuFrame = STM_GetFrameCount(s_GameMainData.MenuStateObj); //メニューのフレーム
// メニューの状態で振り分ける。
switch( STM_GetState(s_GameMainData.MenuStateObj) ) {
case MENU_STATE_TOP: //メニューTOP
// 毎フレームのメニュー処理
switch( winmng_SelectMenu() ) {
case SELECT_POWER://つよさ選択
STM_ChangeState(s_GameMainData.MenuStateObj,MENU_STATE_POWER);//つよさに遷移
break;
case SELECT_ITEM://アイテム選択
STM_ChangeState(s_GameMainData.MenuStateObj,MENU_STATE_ITEM);//アイテムに遷移
break;
case SELECT_MAGIC://魔法選択
STM_ChangeState(s_GameMainData.MenuStateObj,MENU_STATE_MAGIC);//まほうに遷移
break;
}
// メニューを抜ける?
if( g_MainData.key[g_MainData.key_menu] == 1) {
// メニューが終了ならば全ウィンドウを消去。
winmng_DelAllWin();
// 次のフレームで遷移。
STM_ChangeState(s_GameMainData.StateObj,GAMEMAIN_STATE_MOVE);//マップ移動へ遷移。
}
break;
case MENU_STATE_POWER: //つよさ
// つよさメニューの最初?
if( menuFrame==0 ) {
int sizex = 150;
int sizey = 200;
int posx = (SCREEN_X-sizex) / 3;
int posy = (SCREEN_Y-sizey) / 3;;
winmng_NewWin(posx,posy,sizex,sizey,"つよさ");
winmng_SetList( s_list );
}
// 毎フレームの更新
if( winmng_CheckCloseList() ) { //閉じる待ち
// 表示終了ならばこのウィンドウを消去。
winmng_DelWin(winmng_GetActiveWin());
// 次のフレームで遷移。
STM_ChangeState(s_GameMainData.MenuStateObj,MENU_STATE_TOP);//menu先頭に戻る。
}
break;
case MENU_STATE_ITEM: //アイテム
// アイテムメニューの最初?
if( menuFrame==0 ) {
int sizex = 150;
int sizey = 200;
int posx = (SCREEN_X-sizex) / 3;
int posy = (SCREEN_Y-sizey) / 3;;
winmng_NewWin(posx,posy,sizex,sizey,"アイテム");
winmng_SetMsg( "未作成", FALSE );
}
// 毎フレームの更新
if( winmng_UpdateMsg(0) || //0だと一括表示,
g_MainData.key[g_MainData.key_menu] == 1 ) { //キャンセル
// 表示終了ならばこのウィンドウを消去。
winmng_DelWin(winmng_GetActiveWin());
// 次のフレームで遷移。
STM_ChangeState(s_GameMainData.MenuStateObj,MENU_STATE_TOP);//menu先頭に戻る。
}
break;
case MENU_STATE_MAGIC: //まほう
// まほうメニューの最初?
if( menuFrame==0 ) {
int sizex = 150;
int sizey = 200;
int posx = (SCREEN_X-sizex) / 3;
int posy = (SCREEN_Y-sizey) / 3;;
winmng_NewWin(posx,posy,sizex,sizey,"まほう");
winmng_SetMsg( "未作成", FALSE );
}
// 毎フレームの更新
if( winmng_UpdateMsg(0) || //0だと一括表示,
g_MainData.key[g_MainData.key_menu] == 1 ) { //キャンセル
// 表示終了ならばこのウィンドウを消去。
winmng_DelWin(winmng_GetActiveWin());
// 次のフレームで遷移。
STM_ChangeState(s_GameMainData.MenuStateObj,MENU_STATE_TOP);//menu先頭に戻る。
}
break;
}
// マップとキャラクタ表示処理
mapMove_Draw(&s_GameMainData.mapMoveData,frame,FALSE);
// 有効なウィンドウの描画
winmng_Draw();
}
いやぁ、長かったですね。
今回のプロジェクトです。
●DXライブラリ非同梱版(ファイルサイズが小さい) DXライブラリは自分でインストールされている人向け。 ●DXライブラリ同梱版(ファイルサイズが大)
http://softyasu.net/dlcounter/?id=EASYRPG04DXLIBzip(3.3MB)
次は更に厄介なイベント・システム編を予定しています。
たぶん長くなるので、何回かに分けてお送りする予定です。
まず設計方針やイベント(シナリオ)のコマンド体系を説明しますのでご期待ください。