簡単RPG講座9-4。ウィンドウ・システム本編4

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

簡単RPG講座9-4。ウィンドウ・システム本編4

投稿記事 by softya(ソフト屋) » 14年前

さて、いよいよゲーム本編に組み込んでみましょう。
[gameMain.cpp]
今回もヘッダは変更しないのでプログラム側だけです。

●ヘッダ追加
ウィンドウ管理のヘッダを追加して下さい。

CODE:

#include "winMng.h"
●定数
メニュー用の定数を追加します。

CODE:

//	メニューの状態
enum  {
	MENU_STATE_TOP,		//メニューTOP
	MENU_STATE_POWER,	//つよさ
	MENU_STATE_ITEM,	//アイテム
	MENU_STATE_MAGIC,	//まほう

	MENU_STATE_MAX,	//メニューの状態の数
};
●構造体
イベントとメニューに関連したデータを追加します。

CODE:

//	ゲーム本編のデータの構造体。
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
ゲーム本編の初期化に追加します。

CODE:

	//	初回?
	if( s_GameMainData.bFirstInit == FALSE ) {
		s_GameMainData.bFirstInit = TRUE;
			 ・
			 ・
			中略
			 ・
		//	メニューの状態管理オブジェクトの作成。
		s_GameMainData.MenuStateObj = STM_Init(MENU_STATE_MAX);
	}
●GameMain_End
ゲーム本編の終了にメニューの状態管理オブジェクトの破棄を追加します。

CODE:

//----------------------------------------------------------------------
//	ゲーム本編の終了
//----------------------------------------------------------------------
void GameMain_End()
{
	//	ゲーム本編の状態管理オブジェクトの破棄
	STM_End(s_GameMainData.StateObj);
	//	主人公キャラオブジェクトの破棄。
	char_Delete(s_GameMainData.mapMoveData.PlayerObj);
	//	マップ管理の終了
	map_End();
	//	メニューの状態管理オブジェクトの破棄
	STM_End(s_GameMainData.MenuStateObj);
}
●GameMain_Event
イベント処理に仮のメッセージ処理を組み込みます。
※ 将来的には別のものと置き換わります。
基本的なところは序章で作った仮のものと大差はありません。
winmng_SetFrame()で今のフレーム数をセットして、最初のフレームならwinmng_DelAllWin()で念のため全ウィンドウを破棄を破棄します。winmng_NewWin()関数で新しいウィンドウを作成して
winmng_SetMsg()でメッセージを設定します。ここまでが初期化ですね。
で、winmng_UpdateMsg()で毎フレーム更新します。メッセージの速度は5フレームに1文字です。
もし、メッセージが終了したらwinmng_DelWin()でウィンドウを破棄して次の状態に遷移します。
まだ表示が続く場合は、mapMove_Draw()でマップとキャラを表示した上にwinmng_Draw()で最新のウィンドウを実際に描画します。

そこから下は基本前のままですが、メッセージ位置などは調整されているのとRキーが強制的に移動モードになるボタンになっています。

CODE:

//----------------------------------------------------------------------
//	イベント中
//----------------------------------------------------------------------
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;
	}
}
●GameMain_Menu
前とまったく違うメニュー編です。
基本的なところは本物と同じになのですが、とりあえずの仮組みです。
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()で最新のウィンドウを実際に描画します。

CODE:

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ライブラリは自分でインストールされている人向け。

[拡張子 zip は無効化されているため、表示できません]

●DXライブラリ同梱版(ファイルサイズが大)
http://softyasu.net/dlcounter/?id=EASYRPG04DXLIBzip(3.3MB)

次は更に厄介なイベント・システム編を予定しています。
たぶん長くなるので、何回かに分けてお送りする予定です。
まず設計方針やイベント(シナリオ)のコマンド体系を説明しますのでご期待ください。
最後に編集したユーザー softya(ソフト屋) on 2010年12月01日(水) 00:29 [ 編集 5 回目 ]

コメントはまだありません。