[eventScn.h]
イベント処理のヘッダ側です。
●コメント
SCN_SET_ENEMY を最後に追加。
エンカウントする敵の番号を設定する事のできるシナリオ命令です。
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_SET_ENEMY │NULL │敵の番号 │ │エンカウントする敵の番号を設定する。 │
//└───────┴────────┴──────────┴────────┴───────────────────────┘
イベントの種別にEVENT_TYPE_GOV_RESTARTを追加。ゲームオーバー再開専用イベントです。
シナリオ命令にSCN_SET_ENEMYを追加してください。
// イベントの種別
enum {
EVENT_TYPE_NEW_START, // 初期スタート時イベント
EVENT_TYPE_GAME_LOAD, // ゲームロード時イベント
EVENT_TYPE_MAP_CHANGE, // マップチェンジ受けイベント
EVENT_TYPE_GOV_RESTART, // ゲームオーバーの再開用
EVENT_SYSTEM_MAX, // ↑ここまでがシステム・イベント ↓ここからは複数あるマップ関連イベント
EVENT_TYPE_MAP, // 地形のイベント
EVENT_TYPE_CHAR, // キャラクタのイベント
};
// シナリオ命令
enum {
SCN_END, // シナリオの終端を示すコマンドで必須です。SCN_GOTOのストッパでもあります。
SCN_MES, // メッセージの出力
SCN_PLY_POS, // 自キャラの位置を変えます。
SCN_PLY_EPOS, // 自キャラの位置をイベント番号の位置にします。
SCN_PLY_MUKI, // 自キャラの方向を変えます。
SCN_MAP_CHG, // マップを変更します。
SCN_CHR_MUKI, // マップ固有キャラの方向を変えます。
SCN_CHR_ANM, // マップ固有キャラのアニメ有無を設定します。
SCN_SHOP, // お店に入るor宿に泊まります(セーブします)。
SCN_BOSS_BTL, // ボスとのバトル。
SCN_ENDING, // エンディングに入ります。
SCN_EXIT, // イベントを抜けます。
SCN_LABEL, // ラベル名を定義します。
SCN_GOTO, // ラベルにジャンプします。
SCN_IF_SKIP, // 変数と一致する文字列なら次のシナリオ命令をスキップします。
SCN_SET_VAR, // 変数に文字列を設定します。
SCN_ADD_VAR, // 変数の文字列を数値変換して加算します。
SCN_IF_TBOX, // 宝箱が開いていなかったら次の命令をスキップします。
SCN_SET_TBOX, // 宝箱を開けたことを覚えます。
SCN_GET_ITEM, // アイテムを袋に入れます。もし袋がいっぱいなら次の命令をスキップします。
SCN_SET_ENEMY, // エンカウントする敵の番号を設定する。
SCN_CMD_MAX, // イベント(シナリオ)命令の個数
};
イベント処理のプログラム側です。
●ヘッダのインクルード
敵処理のヘッダを組み込みます。 ●内部関数(シナリオ命令)
バトル関係のシナリオ命令の関数の宣言を追加します。
static int scn_SetEnemy(ScnData_t *scnData);
static int scn_BossBtl(ScnData_t *scnData);
static int scn_Ending(ScnData_t *scnData);
scn_SetEnemy、scn_BossBtl、scn_Endingを追加します。
結局実装していない命令がありますが、まあよく有ることです(^^;
// シナリオ命令を実行する関数ポインタ。シナリオ命令のenum並びと同一にすること。
const CmdFunc_t s_scnCmdFunc[SCN_CMD_MAX] = {
scn_Exit, //SCN_END シナリオの終端を示すコマンドで必須です。SCN_GOTOのストッパでもあります。
scn_Message, //SCN_MES メッセージの出力
scn_PlayerPos, //SCN_PLY_POS 自キャラの位置を変えます。
scn_PlayerEvtPos, //SCN_PLY_EPOS 自キャラの位置をイベント番号の位置にします。
scn_PlayerMuki, //SCN_PLY_MUKI 自キャラの方向を変えます。
scn_MapChange, //SCN_MAP_CHG マップを変更します。
scn_CharMuki, //SCN_CHR_MUKI マップ固有キャラの方向を変えます。
NULL, //SCN_CHR_ANM マップ固有キャラのアニメ有無を設定します。
scn_Shop, //SCN_SHOP, お店に入るor宿に泊まります(セーブします)。
scn_BossBtl, //SCN_BOSS_BTL ボスとのバトル。
scn_Ending, //SCN_ENDING エンディングに入ります。
scn_Exit, //SCN_EXIT イベントを抜けます。
scn_Label, //SCN_LABEL ラベル名を定義します。
scn_Goto, //SCN_GOTO ラベルにジャンプします。
scn_IfSkip, //SCN_IF_SKIP 変数と一致する文字列なら次のシナリオ命令をスキップします。
NULL, //SCN_SET_VAR 変数に文字列を設定します。
NULL, //SCN_ADD_VAR 変数の文字列を数値変換して加算します。
scn_IfTBox, //SCN_IF_TBOX 宝箱が開いていなかったら次の命令をスキップします。
scn_SetTBox, //SCN_SET_TBOX 宝箱を開けたことを覚えます。
scn_GetItem, //SCN_GET_ITEM アイテムを袋に入れます。もし袋に入ったら次の命令をスキップします。
scn_SetEnemy, //SCN_SET_ENEMY エンカウントする敵の番号を設定する。
};
winmng_SetMsgのパラメータをMSG_MODE_PAUSE_MARKに変更しました。
//######################################################################
// (シナリオ命令)SCN_MES メッセージの出力
// パラメータ:str[メッセージ]、p1[一文字づつの出力有無]、p2[使用するウィンドウのタイプ]
//######################################################################
static int scn_Message(ScnData_t *scnData)
{
// 命令の最初のフレーム?
if( EventControlData.scnCmdFrame == 0 ) {
// ウィンドウを有効にする。
event_ActiveWnd(scnData->p2);
// メッセージを設定する。待機カーソルあり。
winmng_SetMsg(scnData->str,MSG_MODE_PAUSE_MARK);
}
あとは変更有りません。
エンカウントする敵の番号を書き換える命令です。
実際には、map_SetEnemy()のマップ関数で設定します。
SCN_SET_ENEMYはイベントでエリア毎に出現する敵を切り替えるのに使用しています。
//######################################################################
// (シナリオ命令)SCN_SET_ENEMY エンカウントする敵の番号を設定する。
// パラメータ:p1[敵番号]
//######################################################################
static int scn_SetEnemy(ScnData_t *scnData)
{
// 敵の番号
int enemy_no = scnData->p1;
MACRO_ASSERT( enemy_no >= 0 );
MACRO_ASSERT( enemy_no p1;
MACRO_ASSERT( enemy_no >= 0 );
MACRO_ASSERT( enemy_no encountEnemyType = enemy_no;
EventControlData.mapMoveInfo->bBossEnemy = TRUE;
// シナリオを次に進める。
event_NextScn();
// バトルに遷移する。
return EVENT_RTN_BATTLE;
}
エンディングに遷移します。
//######################################################################
// (シナリオ命令)SCN_ENDING エンディングに入ります。
// パラメータ:p1[宝箱の番号]
//######################################################################
static int scn_Ending(ScnData_t *scnData)
{
// エンディングへ遷移。
return EVENT_RTN_ENDING;
}
[main.cpp]
メイン処理のプログラム側です。
●ヘッダのインクルード
winMngの初期化・終了のためにヘッダをインクルードします。 ●変数
エンディングの処理フレームを追加します。 ●MainInit
winmng_Init()を追加しました。
//----------------------------------------------------------------------
// ゲームの各種値を初期化
//----------------------------------------------------------------------
void MainInit()
{
// ゲーム全体の値を設定。
g_MainData.gameState = GAME_STATE_TITLE; //タイトル画面でスタート
// ゲーム本編は初期スタートを仮に設定。
GameMain_Init(GAMEMAIN_INITTYPE_FIRSTSTART);
// 仮にキーコンフィグを行う。
g_MainData.key_up = KEY_INPUT_UP;
g_MainData.key_down = KEY_INPUT_DOWN;
g_MainData.key_left = KEY_INPUT_LEFT;
g_MainData.key_right= KEY_INPUT_RIGHT;
g_MainData.key_menu = KEY_INPUT_RETURN;
g_MainData.key_act = KEY_INPUT_SPACE;
// ウィンドウの初期化
winmng_Init();
}
winmng_End()を追加しました。
//----------------------------------------------------------------------
// ゲームの各種終了処理
//----------------------------------------------------------------------
void MainEnd()
{
// ウィンドウの終了
winmng_End();
// ゲーム本編の終了処理。
GameMain_End();
}
「なにかキーを押すと生き返ります」を追加。
//----------------------------------------------------------------------
// ゲームオーバー
//----------------------------------------------------------------------
GameState_t GameOver()
{
// ゲームオーバーの表示
CenterDrawString( "あなたは しんでしまった。", 28, 160, GetColor(255,255,255) );
// HIT ANY KEY
CenterDrawString( "なにかキーを押すと生き返ります。", 20, 240, GetColor(255,255,255) );
CenterDrawString( "HIT ANY KEY", 20, 280, GetColor(155,155,255) );
// 何かキーが押された?
if( g_MainData.AllKeyCount == 1 ) {
// ゲーム本編は再スタートを設定。
GameMain_Init(GAMEMAIN_INITTYPE_RESTART);
// 次のフレームはゲーム本編へ
return GAME_STATE_MAIN;
}
// 継続
return g_MainData.gameState;
}
ここは新作に等しいですね。
エンディングロールをコントロールする関数です。
お約束で下から上に文字がスクロールアウトしていきます。
s_EndingDataがスタッフロールの文字列で、文字列配列にして複数行のデータを定義しています。
先頭にあるbやらtやらは文字色や文字の大きさなどのコントロールで後ほど説明します。
ENDING_START_POSYがスタッフロールの開始ポジションで画面下の外です。
ENDING_FONT_SIZEが標準のフォントサイズです。
lineが今表示するスタッフロールの行番号、posyがENDING_START_POSYを基準とする表示位置。
drawposyはスタッフロールでロール位置に補正した表示すべき位置を表す変数です。
whileループでスタッフロールの行の内容がなくなるまで表示を繰り返します。
drawposyをposyとs_EndingFrameを基準で計算して現在の表示位置を求めて、
if( (drawposy >= -ENDING_FONT_SIZE) && (drawposy = -ENDING_FONT_SIZE) && (drawposy (SCREEN_Y/2-ENDING_FONT_SIZE) ) {
// 終了までフレームカウントする。
s_EndingFrame++;
} else {
// HIT ANY KEY
CenterDrawString( "HIT ANY KEY", 20, 320, GetColor(155,155,255) );
// 何かキーが押された?
if( g_MainData.AllKeyCount == 1 ) {
// ゲーム本編は再スタートを設定。
GameMain_Init(GAMEMAIN_INITTYPE_FIRSTSTART);
// 次のフレームはゲームタイトルへ
return GAME_STATE_TITLE;
}
}
// 継続
return g_MainData.gameState;
}
[/code]
●WinMain
追加したのは、
#if 0 /* テスト用 */
[tab=8]// デバッグ用のコンソール。
[tab=8]AllocConsole();
[tab=8]freopen("CONOUT$", "w", stdout); //標準出力をコンソールにする
#endif
でデバッグ専用のコンソール画面を開く部分。今は無効化してあります。
これを有効にするとprintfが出来るようになります。
これも無効化されてますが、いきなりエンディングでスクロールのテスト用です。
#if 0 /*いきなりエンディング*/
[tab=8]g_MainData.gameState=GAME_STATE_ENDING;
[tab=8]s_EndingFrame = 0;//フレーム初期化
#endif
#endif
あとエンディングの遷移するときに
s_EndingFrame = 0;//フレーム初期化
でフレームを初期化するようにしました。
//----------------------------------------------------------------------
// メイン
//----------------------------------------------------------------------
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
//--------------------------------------------
// 初期化
//--------------------------------------------
#if 0 /* テスト用 */
// デバッグ用のコンソール。
AllocConsole();
freopen("CONOUT$", "w", stdout); //標準出力をコンソールにする
#endif
// ウィンドウモード
ChangeWindowMode(TRUE);
// タイトル
SetMainWindowText(GAME_TITLE_STR);
// 画面の解像度 変更
SetGraphMode(SCREEN_X,SCREEN_Y,32);
// DXライブラリの初期化
if( DxLib_Init() == -1 || SetDrawScreen(DX_SCREEN_BACK)!=0 ) {
return -1;//初期化と裏画面化
}
// ゲームの各種値を初期化
MainInit();
//--------------------------------------------
// メインループ
//--------------------------------------------
while(ProcessMessage()==0 && ClearDrawScreen()==0 &&
//↑メッセージ処理 ↑画面をクリア
GetHitKeyStateAll_2(g_MainData.key)==0 && g_MainData.key[KEY_INPUT_ESCAPE]==0 ) {
//↑入力状態を保存 ↑ESCが押されていない
// 全キーの押下カウント
GetCheckHitKeyAll_2(&g_MainData.AllKeyCount);
// FPSの計算
CalcFps(FPS);
// ゲーム全体の状態で振り分ける。
switch( g_MainData.gameState ) {
case GAME_STATE_TITLE: //タイトル画面
g_MainData.gameState = Title();
#if 0 /*いきなりエンディング*/
g_MainData.gameState=GAME_STATE_ENDING;
s_EndingFrame = 0;//フレーム初期化
#endif
break;
case GAME_STATE_NAME: //名前入力
g_MainData.gameState = NameInput();
break;
case GAME_STATE_MAIN: //ゲーム本編
g_MainData.gameState = GameMain();
// エンディングなら
if( g_MainData.gameState==GAME_STATE_ENDING ) {
s_EndingFrame = 0;//フレーム初期化
}
break;
case GAME_STATE_GAMEOVER: //ゲームオーバー
g_MainData.gameState = GameOver();
break;
case GAME_STATE_ENDING: //エンディング
g_MainData.gameState = Ending();
break;
}
// FPS表示
DrawFps();
// 裏画面反映
ScreenFlip();
// 一定速度に保つ処理
WaitFpsConstant(FPS);
}
//--------------------------------------------
// 終了処理
//--------------------------------------------
// ゲームの各種終了処理
MainEnd();
// DXライブラリ使用の終了処理
DxLib_End();
return 0;
}
[scnTown.cpp]
町・シナリオです。
●ヘッダのインクルード
敵処理のヘッダをインクルード。 ●システム・シナリオ
初期スタート時シナリオ(InitStartScn)に無効にしてますが、戦闘テストのシナリオを書き加えています。
それとゲームオーバー時の再開用シナリオ(GameOverReStart)を追加。
// 初期スタート時シナリオ
static ScnData_t InitStartScn[] = {
// シナリオ命令,文字列,数値パラメータ1,数値パラメータ2,
{ SCN_PLY_EPOS, NULL, 0 }, //自キャラの位置をイベント番号の位置にします。
#if 1
{ SCN_MES, "さーて!今日はレベル上げちゃおっかな(勇なま風)", TRUE, SCN_WND_MSGD },//セリフ
#else
{ SCN_MES, "戦闘テスト", TRUE, SCN_WND_MSGD },//セリフ
{ SCN_BOSS_BTL,NULL,ENEMY_FIELD_ZAKO1 },//バトル開始。
#endif
{ SCN_EXIT }, //イベントを抜けます。
{ SCN_END }, //ストッパとしてシナリオ終端に必須です。
};
// ゲームオーバーの再開用
static ScnData_t GameOverReStart[] = {
// シナリオ命令,文字列,数値パラメータ1,数値パラメータ2,
{ SCN_PLY_EPOS, NULL, 0 }, //自キャラの位置をイベント番号の位置にします。
{ SCN_MES, "あなたは、ふと気づくと町中にたっていた。", TRUE, SCN_WND_MSGD },//セリフ
{ SCN_MES, "あれ?お金が半分無くなっている。", TRUE, SCN_WND_MSGD },//セリフ
{ SCN_EXIT }, //イベントを抜けます。。
{ SCN_END }, //ストッパとしてシナリオ終端に必須です。
};
お遊びで行き止まりイベントを追加。
// 行き止まり
static ScnData_t deadEnd[] = {
// シナリオ命令,文字列,数値パラメータ1,数値パラメータ2,
{ SCN_MES, "何も無い。どうやら行き止まりのようだ。", TRUE, SCN_WND_MSGD },//セリフ
{ SCN_EXIT }, //イベントを抜けます。
{ SCN_END }, //ストッパとしてシナリオ終端に必須です。
};
ゲームオーバーの再開用イベントのGameOverReStartと
行き止まりイベントのdeadEndを追加。
//----------------------------------------
// 町のイベントデータ
//----------------------------------------
struct tag_EventData g_TownEventData = {
{ //システムイベント
InitStartScn, // 初期スタート時イベント
NULL, // ゲームロード時イベント
MapChangeScn, // マップチェンジ受けイベント
GameOverReStart,// ゲームオーバーの再開用イベント
},
{ //地形イベント
NULL, //初期スタート時の出現位置
mapExit, //出口イベント
deadEnd, //行き止まり
},
{ //キャラクタイベント
Man0, //町の入口
Man1, //道具屋
Man2, //宿屋
},
};
フィールド・シナリオです。
●ヘッダのインクルード
敵処理のヘッダをインクルード。 ●マップイベントのシナリオ
monstar1とmonstar2はエンカウントするモンスターを切り替えるイベントシナリオです。
Kanban4からKanban9までは、お遊びで付けた看板イベントです。
// エンカウントモンスターを切り替える。
static ScnData_t monstar1[] = {
{ SCN_SET_ENEMY, NULL, ENEMY_FIELD_ZAKO1 }, //敵1
{ SCN_EXIT }, //イベントを抜けます。
{ SCN_END }, //ストッパとしてシナリオ終端に必須です。
};
// エンカウントモンスターを切り替える。
static ScnData_t monstar2[] = {
{ SCN_SET_ENEMY, NULL, ENEMY_FIELD_ZAKO2 }, //敵2
{ SCN_EXIT }, //イベントを抜けます。
{ SCN_END }, //ストッパとしてシナリオ終端に必須です。
};
// 看板
static ScnData_t Kanban4[] = {
{ SCN_MES, "看板「名もない町はこちら」", TRUE, SCN_WND_MSGD },//セリフ
{ SCN_EXIT }, //イベントを抜けます。
{ SCN_END }, //ストッパとしてシナリオ終端に必須です。
};
// 看板
static ScnData_t Kanban5[] = {
{ SCN_MES, "看板「向こうに渡ると痛い目に合うぞ」", TRUE, SCN_WND_MSGD },//セリフ
{ SCN_EXIT }, //イベントを抜けます。
{ SCN_END }, //ストッパとしてシナリオ終端に必須です。
};
// 看板
static ScnData_t Kanban6[] = {
{ SCN_MES, "看板「そろそろボロボロじゃないですか?大丈夫ですか?」", TRUE, SCN_WND_MSGD },//セリフ
{ SCN_EXIT }, //イベントを抜けます。
{ SCN_END }, //ストッパとしてシナリオ終端に必須です。
};
// 看板
static ScnData_t Kanban7[] = {
{ SCN_MES, "看板「ここまで来れるとは!あと少しです。がんばれ!」", TRUE, SCN_WND_MSGD },//セリフ
{ SCN_EXIT }, //イベントを抜けます。
{ SCN_END }, //ストッパとしてシナリオ終端に必須です。
};
// 看板
static ScnData_t Kanban8[] = {
{ SCN_MES, "看板「いよいよ洞窟ですよ~。準備は出来ましたか?」", TRUE, SCN_WND_MSGD },//セリフ
{ SCN_EXIT }, //イベントを抜けます。
{ SCN_END }, //ストッパとしてシナリオ終端に必須です。
};
// 看板
static ScnData_t Kanban9[] = {
{ SCN_MES, "看板「来るものは拒まず」", TRUE, SCN_WND_MSGD },//セリフ
{ SCN_EXIT }, //イベントを抜けます。
{ SCN_END }, //ストッパとしてシナリオ終端に必須です。
};
monstar2~Kanban9までのイベントを追加です。
//----------------------------------------
// フィールドのイベントデータ
//----------------------------------------
struct tag_EventData g_FieldEventData = {
{ //システムイベント
NULL, // 初期スタート時イベント
NULL, // ゲームロード時イベント
MapChangeScn, // マップチェンジ受けイベント
},
{ //地形イベント
townIn, // 町に入る
dungeonIn, // ダンジョンに入る。
monstar2, // エンカウントモンスターを切り替える。
monstar1, // エンカウントモンスターを切り替える。
Kanban4, // 看板
Kanban5, // 看板
Kanban6, // 看板
Kanban7, // 看板
Kanban8, // 看板
Kanban9, // 看板
},
};
ダンジョン・シナリオです。
●ヘッダのインクルード
敵処理のヘッダをインクルード。 ●マップイベントのシナリオ
bossScnは、ボスバトル開始からエンディングまでのイベントを記述しました。
monstar3とmonstar4はエンカウントするモンスターを切り替えるイベントシナリオです。
// ボス遭遇イベント
static ScnData_t bossScn[] = {
// シナリオ命令,文字列,数値パラメータ1,数値パラメータ2,
{ SCN_MES, "悪いドラゴン「よく来たな小僧!」", TRUE, SCN_WND_MSGD },//セリフ
{ SCN_MES, "悪いドラゴン「我が力!思い知るがいい!」", TRUE, SCN_WND_MSGD },//セリフ
// 戦闘開始
{ SCN_BOSS_BTL,NULL,ENEMY_BOSS }, //ボスバトル開始。
{ SCN_CHR_MUKI, NULL, 0, CHAR_MUKI_UP }, //ボスを別の方向に向けると消える。
{ SCN_MES, "かろうじて、悪いドラゴンに勝利した・・・。しかし、戦いはまだ続く・・・。", TRUE, SCN_WND_MSGD },//セリフ
{ SCN_MES, "負けるな!この世界を人間の手に取り戻すその日まで!!", TRUE, SCN_WND_MSGD },//セリフ
{ SCN_ENDING }, //勝利したのでエンディング
{ SCN_END }, //ストッパとしてシナリオ終端に必須です。
};
// エンカウントモンスターを切り替える。
static ScnData_t monstar3[] = {
{ SCN_SET_ENEMY, NULL, ENEMY_DUNGEON_ZAKO1 }, //敵1
{ SCN_EXIT }, //イベントを抜けます。
{ SCN_END }, //ストッパとしてシナリオ終端に必須です。
};
// エンカウントモンスターを切り替える。
static ScnData_t monstar4[] = {
{ SCN_SET_ENEMY, NULL, ENEMY_DUNGEON_ZAKO2 }, //敵2
{ SCN_EXIT }, //イベントを抜けます。
{ SCN_END }, //ストッパとしてシナリオ終端に必須です。
};
monstar4,monstar3のエンカウントモンスターを切り替えるイベントを追加。
//----------------------------------------
// ダンジョンのイベントデータ
//----------------------------------------
struct tag_EventData g_DungeonEventData = {
{ //システムイベント
MapChangeScn, // 初期スタート時イベント
NULL, // ゲームロード時イベント
MapChangeScn, // マップチェンジ受けイベント
},
{ //地形イベント
dungeonOut, // ダンジョンに入る。
bossScn, // ボスイベント
monstar4, // エンカウントモンスターを切り替える。
monstar3, // エンカウントモンスターを切り替える。
},
{ //キャラクタイベント
NULL, //ボスたが接触できないので定義しない。
takara1, //宝箱1
takara2, //宝箱2
takara3, //宝箱3
takara4, //宝箱4
takara5, //宝箱5
},
};
敵処理のヘッダ側です。
これは新規作成のファイルです。
●定数
敵の種類(ENEMY_???)は、敵の種別を示します。
攻撃タイプ(ENEMY_ATK_TYPE_???)は、特殊攻撃の種類を示します。
#ifndef INCLUDE_ENEMY_H
#define INCLUDE_ENEMY_H
//----------------------------------------------------------------------
// 定数
//----------------------------------------------------------------------
// 敵の種類
enum {
ENEMY_FIELD_ZAKO1, //フィールド雑魚1
ENEMY_FIELD_ZAKO2, //フィールド雑魚2
ENEMY_DUNGEON_ZAKO1, //ダンジョン雑魚1
ENEMY_DUNGEON_ZAKO2, //ダンジョン雑魚2
ENEMY_BOSS, //ボス
ENEMY_MAX,
};
// 攻撃タイプ
enum {
ENEMY_ATK_TYPE_NORMAL, //攻撃は打撃のみ。
ENEMY_ATK_TYPE_ROLL, //「なぎたおし」の攻撃も含めるタイプ。
ENEMY_ATK_TYPE_FIREMAGIC, //「ほのおのまほう」の攻撃も含めるタイプ。
ENEMY_ATK_TYPE_BOSS, //ボスの特殊攻撃
};
敵ファイル定義構造体(EnemyFileDefine_t)は、バトルで使用する敵のファイル情報と表示座標を定義するための構造体です。
敵パラメータ(EnemyParam_t)は、敵のパラメータを定義する構造体です。
//----------------------------------------------------------------------
// 構造体
//----------------------------------------------------------------------
// 敵ファイル定義構造体
typedef struct {
char *enemyCgName; //敵cg名
char *bgName; //背景ファイル名
int x,y; //座標
} EnemyFileDefine_t;
// 敵パラメータ
typedef struct {
// 識別情報
char *name; //名前
// 基本パラメータ
int hp; //HP
int attack; //攻撃力
int def; //防御力
// 特殊パラメータ
int atk_type; //攻撃種別
// 倒したときに貰える。
int expp; //経験値(Experience point)
int money; //お金
} EnemyParam_t;
enemy_GetParam()敵パラメータの複製を作るための関数です。
//----------------------------------------------------------------------
// 関数の宣言
//----------------------------------------------------------------------
// 敵パラメータの複製を得る。
extern EnemyParam_t enemy_GetParam(int enemyType);
#endif /*INCLUDE_ENEMY_H*/
敵処理のプログラム側です。
これは新規作成のファイルです。
●ヘッダのインクルード ● ●変数
s_enemyDatasは敵のパラメータを定義するテーブルです。
今回登場する全ての敵のパラメータを持っています。
今回は初期値で持っていますが、csvなどファイルから読み込む様にするとパラメータ調整が便利になります。
//----------------------------------------------------------------------
// 変数
//----------------------------------------------------------------------
// 敵パラメータ・テーブル。enum ENEMY_???の並びと合わせてください。
static const EnemyParam_t s_enemyDatas[ENEMY_MAX] = {
// 名前, HP, 攻撃力,防御力,攻撃種別, 経験値,お金
{"エビル・バット", 10, 7, 11, ENEMY_ATK_TYPE_NORMAL, 6 ,3}, //フィールド雑魚1
{"イーター", 17, 14, 17, ENEMY_ATK_TYPE_ROLL, 26 ,6}, //フィールド雑魚2
{"ゴブリン", 25, 24, 31, ENEMY_ATK_TYPE_NORMAL, 108 ,9}, //ダンジョン雑魚1
{"まどうゾンビ", 35, 31, 41, ENEMY_ATK_TYPE_FIREMAGIC, 278 ,12}, //ダンジョン雑魚2
{"古代ドラゴン", 500, 35, 43, ENEMY_ATK_TYPE_BOSS, 3000,1000}, //ボス
};
敵パラメータの複製を戻す関数です。
バトルで使用するとHPなど値が変わってしまいますので、この関数でパラメータの複製を作ります。
//----------------------------------------------------------------------
// 敵パラメータの複製を得る。
//----------------------------------------------------------------------
EnemyParam_t enemy_GetParam(int enemyType)
{
MACRO_ASSERT(enemyType>=0);
MACRO_ASSERT(enemyType<ENEMY_MAX);
// 敵パラメータを持ち帰る。
return s_enemyDatas[enemyType];
}
データ定義のヘッダ側です。
●ヘッダのインクルード
敵の構造体をインクルードする。 ●変数
g_EnemyFileDatasは敵のファイル定義テーブルです。 [data.cpp]
データ定義のプログラム側です。
●マップ定義の配列
エンカウント平均歩数とエンカウントする敵の種別を設定します。
// フィールド(島)
{
"島", //マップ名
"data/map/field.fmf", //マップファイル名(fmf)
"data/map/field.png", //マップチップ画像ファイル名
{ //マップ固有のキャラクタ・ファイル
NULL,
},
8, //エンカウント平均歩数(0にするとバトルは発生しない)
ENEMY_FIELD_ZAKO1, //エンカウントする敵の種別
&g_FieldEventData //イベント構造体ポインタ
},
// ダンジョン(洞窟)
{
"洞窟", //マップ名
"data/map/dangeon.fmf", //マップファイル名(fmf)
"data/map/bg.png", //マップチップ画像ファイル名
{ //マップ固有のキャラクタ・ファイル
"data/char/boss.one.png",
"data/char/box.png",
},
7, //エンカウント平均歩数(0にするとバトルは発生しない)
ENEMY_DUNGEON_ZAKO1, //エンカウントする敵の種別
&g_DungeonEventData //イベント構造体ポインタ
},
敵のファイル定義情報です。
最後の数字はモンスターの表示座標で、(0,0)の場合は自動で座標を計算します。
// 敵ファイル定義の配列。enum ENEMY_???の並びと合わせてください。
EnemyFileDefine_t g_EnemyFileDatas[ENEMY_MAX] = {
// 敵CGファイル、背景ファイル
{ "data/battle/monster1.png","data/battle/sougen.png",0,0 }, //ENEMY_FIELD_ZAKO1 フィールド雑魚1
{ "data/battle/monster2.png","data/battle/sougen.png",0,0 }, //ENEMY_FIELD_ZAKO2 フィールド雑魚2
{ "data/battle/monster3.png","data/battle/doukutu.png",0,0 }, //ENEMY_DUNGEON_ZAKO1 ダンジョン雑魚1
{ "data/battle/monster4.png","data/battle/doukutu.png",0,0 }, //ENEMY_DUNGEON_ZAKO2 ダンジョン雑魚2
{ "data/battle/boss.png","data/battle/boss_haikei.png",169,80 }, //ENEMY_BOSS ボス
};
さていよいよ戦闘システムが残るだけとなりました。
下回りから作成して一気にバトルシステムを完成させますよ!