まず、
(4)data.cpp 町イベントを接続。
です。
[data.cpp]
●インクルードの追加 ●マップ定義の配列
g_MapDefDatasにイベント構造体ポインタを追加しています。
今後は、マップ毎にそれぞれのg_TownEventDataを追加していく形になります。
//----------------------------------------
// マップ定義の配列
//----------------------------------------
MapDefine_t g_MapDefDatas[] = {
{ // 町
"town", //マップ名
"data/map/town.fmf", //マップファイル名(fmf)
"data/map/town.png", //マップチップ画像ファイル名
{ //マップ固有のキャラクタ・ファイル
"data/char/people00.png",
"data/char/people01.png",
"data/char/people02.png",
},
0, //エンカウント平均歩数(0にするとバトルは発生しない)
0, //エンカウントする敵の種別
&g_TownEventData //イベント構造体ポインタ
},
{
NULL,NULL,NULL,{NULL}, // データの最後を示すストッパ
}
};
(5)scnTown.cpp/h 町イベント・シナリオだけのソースファイル。
です。
[scnTown.h]
ここには、町のイベント・シナリオだけを記述します。
●変数
実は構造体の名前だけの定義です。
上に書いたg_MapDefDatasで参照するためだけのモノです。
#ifndef INCLUDE_SCNTOWN_H
#define INCLUDE_SCNTOWN_H
//----------------------------------------------------------------------
// 変数
//----------------------------------------------------------------------
// 町のイベントデータ
extern struct tag_EventData g_TownEventData;
#endif /*INCLUDE_SCNTOWN_H*/
[scnTown.cpp]
こちらがイベントの実体です。
●ヘッダインクルード
まず先頭にインクルードです。
●シナリオを配列で記述します
初期スタート時のシナリオで、自キャラの位置を変更してセリフを表示してイベントを抜けるのが内容です。
SCN_ENDはお約束ですのでシナリオの定義には必ず書いてください(シナリオの暴走阻止のため)。
なお、この配列をテキストファイルから作る事でシナリオのファイル化が出来ます。
csvにすればExcelでシナリオが管理できますし、コマンドにすれば簡易スクリプトにもなります。
csvに付いては、「龍神録プログラミングの館 エクセルを使って敵の出現データを作ってみよう」http://dixq.net/rp/11.html
と同じように作成します。
それについては拡張編で解説しますね。
//----------------------------------------------------------------------
// 変数
//----------------------------------------------------------------------
// 初期スタート時シナリオ
static ScnData_t InitStartScn[] = {
// シナリオ命令,文字列,数値パラメータ1,数値パラメータ2,
{ SCN_PLY_EPOS, NULL, 0 }, //自キャラの位置をイベント番号の位置にします。
{ SCN_MES, "さーて!今日はレベル上げちゃおっかな(勇なま風)", TRUE, SCN_WND_MSGD },//セリフ
{ SCN_EXIT }, //イベントを抜けます。
{ SCN_END }, //イベントを抜けます。ストッパとしてシナリオ終端に必須です。
};
イベントとシナリオつなぐテーブルです。
発生したイベント毎のシナリオの配列名を書くだけです。
ここもシナリオファイル化できますので、それは拡張編で。
//----------------------------------------
// 町のイベントデータ
//----------------------------------------
struct tag_EventData g_TownEventData = {
{ //システムイベント
InitStartScn, // 初期スタート時イベント
NULL, // ゲームロード時イベント
NULL, // マップチェンジ受けイベント
},
{ //地形イベント
NULL, //初期スタート時の出現位置
NULL, //出口イベント
},
{ //キャラクタイベント
NULL, //町の入口
NULL, //道具屋
NULL, //宿屋
},
};
(6)gameMain.cpp イベント処理の組み込み。
を行います。
[gameMain.cpp]
●ヘッダ追加と内部関数の戻り値変更
eventScn.hを新たに追加します。
それとGameMain_Event()関数の戻り値を変更します。
#include "eventScn.h"
//----------------------------------------------------------------------
// 内部関数
//----------------------------------------------------------------------
static int GameMain_Event();
●定数の変更です
BATTLE_STATE_ENDINGは不要になったので削除してください。
//----------------------------------------------------------------------
// 定数
//----------------------------------------------------------------------
// バトルの結果
enum BattleState_t {
BATTLE_STATE_CONTINUE, //バトル継続
BATTLE_STATE_GAMEOVER, //ゲームオーバー
// 削除
BATTLE_STATE_WIN, //戦闘に勝利
};
●構造体の変更
msg_winnoは不要になったので削除してください。
//----------------------------------------------------------------------
// 構造体
//----------------------------------------------------------------------
// ゲーム本編のデータの構造体。
typedef struct {
GameMainInitType_t initType; //初期化タイプ
int bFirstInit; //一回目の初期化済みのフラグ。
STATEMNG_OBJECT StateObj; //ゲーム本編の状態管理オブジェクト
int beforeBattleInState; //バトル開始前の状態
// マップ移動に関連したデータ
MapMoveInfo_t mapMoveData;
// 削除
// メニューに関連したデータ
STATEMNG_OBJECT MenuStateObj; //メニューのオブジェクト
} GameMainData_t;
●GameMain_Initの変更
初回の処理に次の2行のイベント関数呼び出しを追加してください。
イベントの初期化event_Init()で"town"をスタートマップに設定します。
次にevent_SetEventで初期化スタートイベント(EVENT_TYPE_NEW_START)を設定します。
//----------------------------------------------------------------------
// ゲーム本編の初期化
//----------------------------------------------------------------------
void GameMain_Init(GameMainInitType_t initType)
・
・
・
// イベント処理の初期化
event_Init("town"); //初期スタートのマップ情報
// 起動するイベントの情報を設定する。
event_SetEvent(EVENT_TYPE_NEW_START,0); //初期スタート時イベント
●GameMainの変更
GAME_STATE_ENDINGへの状態遷移がGAMEMAIN_STATE_BATTLE状態からGAMEMAIN_STATE_EVENT状態に移りました。
ややこしいので関数全体を掲載します。
//----------------------------------------------------------------------
// ゲーム本編
//----------------------------------------------------------------------
GameState_t GameMain()
{
// ゲーム状態の更新・フレームカウント
STM_UpdateState(s_GameMainData.StateObj);
// ゲーム本編の状態で振り分ける。
switch( STM_GetState(s_GameMainData.StateObj) ) {
case GAMEMAIN_STATE_MAPLOAD:
//マップロード処理
GameMain_MapLoad();
break;
case GAMEMAIN_STATE_EVENT:
//イベント中
if( GameMain_Event() ) {
// エンディングに遷移
return GAME_STATE_ENDING; //ゲーム全体の状態を遷移。
}
break;
case GAMEMAIN_STATE_SHOP:
//お店で買い物中
GameMain_Shop();
break;
case GAMEMAIN_STATE_MOVE:
//マップ移動中
GameMain_MapMove();
break;
case GAMEMAIN_STATE_MENU:
//メニュー中
GameMain_Menu();
break;
case GAMEMAIN_STATE_BATTLE_IN:
//戦闘開始
GameMain_BattleIn();
break;
case GAMEMAIN_STATE_BATTLE:
// 戦闘中
switch( GameMain_Battle() ) {
case BATTLE_STATE_CONTINUE: //バトル継続
break;
case BATTLE_STATE_GAMEOVER: //ゲームオーバー
return GAME_STATE_GAMEOVER; //ゲーム全体の状態を遷移。
case BATTLE_STATE_WIN: //戦闘に勝利
STM_ChangeState(s_GameMainData.StateObj,GAMEMAIN_STATE_BATTLE_END);//戦闘結果報告へ遷移。
break;
}
break;
case GAMEMAIN_STATE_BATTLE_END:
//戦闘結果報告
GameMain_BattleEnd();
break;
}
// ゲーム全体の状態を継続
return g_MainData.gameState;
}
map_Loadがevent_GetLoadMapName()で得たマップ名でアップロードするようになりました。
event_SetEventDataTableでアップロード後のイベント情報をmap_GetEventData()で引き継ぎます。
ロードが終了したらイベント処理に処理が移ります。
//----------------------------------------------------------------------
// マップロード処理
//----------------------------------------------------------------------
static void GameMain_MapLoad()
{
// イベント情報に従ってマップチェンジ。
s_GameMainData.mapMoveData.MapSize = map_Load(event_GetLoadMapName());
// マップチェンジ後のマップのイベント情報ポインタを設定する。
event_SetEventDataTable(map_GetEventData());
// 次はマップロード時のイベントへ。
STM_ChangeState(s_GameMainData.StateObj,GAMEMAIN_STATE_EVENT);//イベント中へ遷移。
}
●GameMain_Event
ここは大幅に変更が加わっています。
まず、この関数の戻り値がエンディングではない(FALSE)/エンディングである(TRUE)になります、
event_Mainでイベント処理を呼び出します。引数はマップ移動関係のデータです。
戻り値でゲーム状態遷移の状態遷移がきまります。
マップとキャラクタはここでも表示しますので、mapMove_Draw()だけは呼び出します。
event_Draw(frame)でイベントに関連したものをマップとキャラクタの上に描画しています。
//----------------------------------------------------------------------
// イベント中
//----------------------------------------------------------------------
static int GameMain_Event()
{
int bEnding = FALSE; //エンディングではない
// 今のフレーム
int frame = STM_GetFrameCount(s_GameMainData.StateObj);
// イベントを実行する。
int rtnCode = event_Main(frame,&s_GameMainData.mapMoveData);
switch( rtnCode ) {
case EVENT_RTN_CONTINE: //イベント継続
// この状態を継続します。
break;
case EVENT_RTN_MAPMOVE: //マップ移動へ遷移。
STM_ChangeState(s_GameMainData.StateObj,GAMEMAIN_STATE_MOVE);//マップ移動へ遷移。
break;
case EVENT_RTN_MAPCHANGE://マップチェンジに遷移。
STM_ChangeState(s_GameMainData.StateObj,GAMEMAIN_STATE_MAPLOAD);//マップロード処理に遷移
break;
case EVENT_RTN_SHOP: //SHOPへ遷移。
STM_ChangeState(s_GameMainData.StateObj,GAMEMAIN_STATE_SHOP);//お店に遷移
break;
case EVENT_RTN_BATTLE: //バトルに遷移。
STM_ChangeState(s_GameMainData.StateObj,GAMEMAIN_STATE_BATTLE_IN);//戦闘開始へ遷移。
break;
case EVENT_RTN_ENDING: //エンディングへ遷移。
bEnding = TRUE;
break;
}
// マップとキャラクタ表示処理
mapMove_Draw(&s_GameMainData.mapMoveData,frame,FALSE);
// イベントを描画する
event_Draw(frame);
// ↓とりあえずの処理。
// ゲーム本編だよって表示
CenterDrawString( "ゲーム本編です。", 28, 200, GetColor(255,255,255) );
CenterDrawString( "イベント中です。", 20, 260, GetColor(255,255,255) );
// エンディング遷移条件
return bEnding;
}
GameMain_Battleからエンディングのキー入力を取り除きます。
下記のコメントアウトしたる部分を削除してください。
//----------------------------------------------------------------------
// 戦闘中
//----------------------------------------------------------------------
static int GameMain_Battle()
・
・
・
// エンディングのキー入力
// CenterDrawString( "「E」ボタンでエンディングになります。", 20, 280, GetColor(155,155,255) );
// if( g_MainData.key[KEY_INPUT_E] == 1) {
// return BATTLE_STATE_ENDING; //戦闘でボスを倒した。
// }
お疲れさまでした。難関であるイベント処理の基本部分の完成です。
長かったですが如何でしたでしょうか?
さて、今回のプロジェクトです。 今後としてはイベント処理を幾つか拡張して、町人の会話やマップチャンジなどを実装してみましょう。
それでは次回まで!