簡単RPG講座10-6。イベント(シナリオ)システム編6

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

簡単RPG講座10-6。イベント(シナリオ)システム編6

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

さて、会話とマップチェンジで使うシナリオ命令を作っていきます。

[eventScn.h]
●シナリオ命令表
シナリオ命令表ですが、差し替えがありますのでコピペでお願いします。

CODE:

//----------------------------------------------------------------------
//	シナリオ命令表
//----------------------------------------------------------------------
//┌───────┬────────┬──────────┬────────┬───────────────────────┐
//│コマンド名    │パラメータ文字列│パラメータ数値1     │パラメータ数値2 │機能                                          │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_MES       │メッセージ      │一文字づつの出力有無│使用する        │メッセージの出力。                            │
//│              │                │                    │ウィンドウ      │                                              │
//│              │                │                    │のタイプ        │                                              │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_PLY_POS   │NULL            │x                   │y               │自キャラの位置を変えます。                    │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_PLY_EPOS  │NULL            │イベント番号        │                │自キャラの位置をイベント番号の位置にします。  │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_PLY_MUKI  │NULL            │方向                │                │自キャラの方向を変えます。                    │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_MAP_CHG   │マップ名        │                    │                │マップを変更します。                          │
//│              │                │                    │                │マップチェンジに遷移。                        │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_CHR_MUKI  │NULL            │キャラ番号          │方向            │マップ固有キャラの方向を変えます。            │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_CHR_ANM   │NULL            │キャラ番号          │アニメ有無      │マップ固有キャラのアニメ有無を設定します。    │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_SHOP      │NULL            │SHOP番号            │                │お店に入る                                    │
//│              │                │                    │                │ or                                           │
//│              │                │                    │                │宿に泊まります(セーブします)。              │
//│              │                │                    │                │SHOPへ遷移。                                  │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_BOSS_BTL  │NULL            │敵番号              │                │ボスとのバトル。                              │
//│              │                │                    │                │バトルに遷移。                                │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_ENDING    │NULL            │                    │                │エンディングに入ります。                      │
//│              │                │                    │                │エンディングへ遷移。                          │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_EXIT      │NULL            │                    │                │イベントを抜けます。                          │
//│              │                │                    │                │マップ移動へ遷移。                            │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_LABEL     │ラベル名        │                    │                │ラベル名を定義します。                        │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_GOTO      │ラベル名        │                    │                │ラベル名にジャンプします。                    │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_IF_SKIP   │文字列          │シナリオ変数番号    │IFの条件        │変数と条件一致する文字列なら                  │
//│              │                │                    │==,!=などの     │次のシナリオ命令をスキップします。            │
//│              │                │                    │条件フラグ      │                                              │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_SET_VAR   │文字列          │シナリオ変数番号    │                │変数に文字列を設定します。                    │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│EVENT_ADD_VAR │NULL            │シナリオ変数番号    │加算値          │変数の文字列を数値変換して加算します。        │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_IF_TBOX   │NULL            │宝箱の番号          │                │宝箱が空いていなかったら                      │
//│              │                │                    │                │次の命令をスキップします。                    │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_SET_TBOX  │NULL            │宝箱の番号          │                │宝箱を開けたことを覚えます。                  │
//├───────┼────────┼──────────┼────────┼───────────────────────┤
//│SCN_GET_ITEM  │NULL            │アイテム番号        │                │アイテムを袋に入れます。                      │
//│              │                │                    │                │もし袋がいっぱいなら次の命令をスキップします。│
//└───────┴────────┴──────────┴────────┴───────────────────────┘
●シナリオ命令
これも単なるコメント間違いの修正です。

CODE:

//	シナリオ命令
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_CMD_MAX,	//	イベント(シナリオ)命令の個数
};
●定数
シナリオ命令で使う比較演算条件の定義です。

CODE:

//	シナリオ条件のフラグ
enum {
	IF_EQUAL,			//	==
	IF_NOT_EQUAL,		//	!=
	IF_GREATER,			//	>
	IF_GREATER_EQUAL,	//	>=
	IF_LESS,			//	player_px += (scnData->p1*CHAR_PIXEL_SIZEX);
	EventControlData.mapMoveInfo->player_py += (scnData->p2*CHAR_PIXEL_SIZEY);
	
	//	シナリオを次に進める。
	event_NextScn();
	
	//	イベントを継続する。
	return EVENT_RTN_CONTINE;
}
●scn_PlayerMuki
シナリオ命令の追加関数です。
指定した方向に自キャラを向けます。

CODE:

//######################################################################
//	(シナリオ命令)SCN_PLY_MUKI	自キャラの方向を変えます。
//	パラメータ:p1[方向]
//######################################################################
static int scn_PlayerMuki(ScnData_t *scnData)
{
	MACRO_ASSERT( scnData->p1 player_muki = scnData->p1;
	
	//	シナリオを次に進める。
	event_NextScn();
	
	//	イベントを継続する。
	return EVENT_RTN_CONTINE;
}
●scn_MapChange
シナリオ命令の追加関数です。
マップチェンジの命令で、指定されたマップに移ります。
まず現在のマップの情報をシナリオ変数に保存して、新しマップ名に書き換えます。
最後にマップチェンジ後のイベントを設定してアップロードに状態遷移します。

CODE:

//######################################################################
//	(シナリオ命令)SCN_MAP_CHG	マップを変更します。 
//	パラメータ:str[マップ名]
//######################################################################
static int scn_MapChange(ScnData_t *scnData)
{
	//	エラーガード
	MACRO_ASSERT( NULL!=(scnData->str) );
	
	//	マップ情報をシナリオ変数に保存する。
	MACRO_ASSERT( strlen(EventControlData.mapName)str)str);	//「ロードする」あるいは「ロード済み」のマップ名。
	
	//	チェンジ先のイベントも設定する。
	event_SetEvent(EVENT_TYPE_MAP_CHANGE,0);
	
	//	マップチェンジに遷移する。
	return EVENT_RTN_MAPCHANGE;
}
●scn_Label
シナリオ命令の追加関数です。
このラベルは、SCN_GOTOの飛び先ですので命令自体の動作は特にありません。

CODE:

//######################################################################
//	(シナリオ命令)SCN_LABEL		ラベル名を定義します。
//	パラメータ:str[ラベル名]
//######################################################################
static int scn_Label(ScnData_t *scnData)
{
	//	エラーガード
	MACRO_ASSERT( NULL!=(scnData->str) );
	
	//	ジャンプ先のラベルですので、動作としては特にありません。
	
	//	シナリオを次に進める。
	event_NextScn();
	
	//	イベントを継続する。
	return EVENT_RTN_CONTINE;
}
●scn_Goto
シナリオ命令の追加関数です。
指定されたラベルのシナリオ命令にジャンプします。
まず自分の命令から後ろを探して無ければ、先頭からラベルを探しています。
両方無ければエラーです。

CODE:

//######################################################################
//	(シナリオ命令)SCN_GOTO		ラベル名にジャンプします。
//	パラメータ:str[ラベル名]
//######################################################################
static int scn_Goto(ScnData_t *scnData)
{
	//	エラーガード
	MACRO_ASSERT( NULL!=(scnData->str) );
	
	//	今の位置から最後まで探す。あったら次の命令へ。
	if( event_SearchLabel(EventControlData.scnPoint+1,-1,scnData->str) ) {
		//	シナリオを次に進める。
		event_NextScn();
		//	イベントを継続する。
		return EVENT_RTN_CONTINE;
	}
	//	もし無ければ、先頭から今の位置まで探す。あったら次の命令へ。
	if( event_SearchLabel(0,EventControlData.scnPoint,scnData->str) ) {
		//	シナリオを次に進める。
		event_NextScn();
		//	イベントを継続する。
		return EVENT_RTN_CONTINE;
	}
	
	//	両方無ければエラー。
	DebugBreak();	//ここに来てはいけない。
	return FALSE;//ダミー
}

●scn_IfSkip
シナリオ命令の追加関数です。
シナリオ命令の条件判断命令で条件が一致したら一命令スキップします。
この命令とSCN_GOTOを組み合わせるとif文と同じ機能を実現できます。
例えば、
SCN_IF_SKIP
SCN_GOTO ← 条件成立時にスキップされる。
SCN_XXXX
と並んでいる場合には条件が成立した場合には、命令SCN_XXXXが実行されますが、条件が未成立ならSCN_GOTOが実行されます。
p2で==,!=などの判断条件を変更することも出来ます。

CODE:

//######################################################################
//	(シナリオ命令)SCN_IF_SKIP	変数と条件一致する文字列なら次のシナリオシナリオ命令をスキップします。 
//	パラメータ:str[文字列]、p1[シナリオ変数番号]、p2[==,!=などの条件フラグ]
//######################################################################
static int scn_IfSkip(ScnData_t *scnData)
{
	int bSkip = FALSE;	//スキップしない。
	
	//	ガード
	MACRO_ASSERT( scnData->p1 p2 ) {
	case IF_EQUAL:			//	==
		bSkip = ( 0 == strcmp(g_scnVar[scnData->p1],scnData->str) );	//条件判定
		break;
	case IF_NOT_EQUAL:		//	!=
		bSkip = ( 0 != strcmp(g_scnVar[scnData->p1],scnData->str) );	//条件判定
		break;
	case IF_GREATER:		//	>
		bSkip = ( 0 >  strcmp(g_scnVar[scnData->p1],scnData->str) );	//条件判定
		break;
	case IF_GREATER_EQUAL:	//	>=
		bSkip = ( 0 >= strcmp(g_scnVar[scnData->p1],scnData->str) );	//条件判定
		break;
	case IF_LESS:			//	p1],scnData->str) );	//条件判定
		break;
	case IF_LESS_EQUAL:		//	p1],scnData->str) );	//条件判定
		break;
	}
	
	//	条件一致でスキップか?
	if( bSkip )	{
		//	1つ先行して命令を進める。
		EventControlData.scnPoint++;		//	今現在のシナリオ位置
	}
	//	シナリオを次に進める。
	event_NextScn();
	
	//	イベントを継続する。
	return EVENT_RTN_CONTINE;
}
●event_NextScn
条件が間違っていたので修正します。

CODE:

		//	シナリオ終端以外なら
		if( EventControlData.cur_Scn[EventControlData.scnPoint].scnCmd != SCN_END ) {
●event_SearchLabel
ラベル検索用の追加関数です。
かなり厳重にガードしてます。
ループを抜ける不成立条件は、SCN_ENDを見つけた場合と指定された検索終了ポイントに到達した場合はFALSEで帰ります。
ラベルを見つけてラベル名が一致したら、そのラベルにシナリオ位置を変更してTRUEの戻り値で帰ります。
あとシナリオ命令の書き間違いを用心して無限ループのガードにMAX_LOOPチェックを入れています。

CODE:

//----------------------------------------------------------------------
//	指定されたラベルを指定範囲内で探します。
//----------------------------------------------------------------------
static int event_SearchLabel(int st,int end,char *label)
{
	//	ガード
	MACRO_ASSERT( st >= 0 );
	MACRO_ASSERT( label != NULL );
	if( end != -1 ) {
		MACRO_ASSERT( st  end ) {
				break;
			}
		}
		//	無限ループの防止
		loop++;
		if( loop > MAX_LOOP ) {
			DebugBreak();//こんなに命令数があるはずない。
		}
	}
	
	//	該当ラベルがありませんでした。
	return FALSE;
}
以上シナリオ命令関係でした。

[mapMove.cpp]

●ヘッダ
イベントの処理をするので、ヘッダを追加します。

CODE:

#include "eventScn.h"
●内部関数の定義
内部関数としてキャラクタのイベントチェック関数を追加します。

CODE:

//	その方向にキャラクタがいるかイベントチェックする
static int mapMove_CheckEventChar( MapMoveInfo_t *mapMoveInfo, int muki, int px, int py );
●mapMove_Mainの途中
移動終わりの判定の処理にマップイベントを踏んだかの判定を追加します。
画像
イベントを踏んだ場合、踏んだイベントの番号をイベントに設定してイベントに状態遷移します。
ここで判定しているのは、移動中まで判定してしまうとイベントを移動中に続けて発生してしまうためです。

CODE:

	//	丁度、マップチップのブロックの境目の位置なら移動終わり。
	if( (px%CHAR_PIXEL_SIZEX)==0 && (py%CHAR_PIXEL_SIZEY)==0 ) {
		//	移動中なら
		if( bPlayerMoving ) {
			//	移動停止
			bPlayerMoving = FALSE;
			//	座標のイベント判定。イベントでなければ-1が戻る。イベントを踏んだか判定
			int evtno = map_CheckMapEvent( px,py );
			if( evtno >= 0 ) {
				//	イベント情報を設定する。
				event_SetEvent(EVENT_TYPE_MAP,evtno);
				//	イベント発生
				mapMoveInfo->rtnCode = MAPMOVE_RTNCODE_EVENT;
				//	このまま抜ける。
				return;
			}
		}
	}
●mapMove_Mainの最後のほう
イベントのキー入力と差し替えます。
アクションキーを押すと一歩前にマップ固有のキャラクタがいるか判断しています。
画像
キャラクタがいたら話しかけるためにイベントを設定してイベントに遷移します。
この仕組を使って宝箱もキャラクタとして処理する予定です。

CODE:

	//	アクションのキー入力
	if( g_MainData.key[g_MainData.key_act] == 1) {
		//	キャラクタが前方に存在するか?
		int evtno = mapMove_CheckEventChar( mapMoveInfo,muki,px,py );
		if( evtno >= 0 ) {
			//	イベント情報を設定する。
			event_SetEvent(EVENT_TYPE_CHAR,evtno);
			//	イベント発生
			mapMoveInfo->rtnCode = MAPMOVE_RTNCODE_EVENT;
			//	このまま抜ける。
			return;
		}
	}
	
	//	↓テスト用。ちゃんとしたら消します。
	
	//	バトルのキー入力
	if( g_MainData.key[KEY_INPUT_B] == 1) {
		mapMoveInfo->rtnCode = MAPMOVE_RTNCODE_ENCOUNT;	//エンカウント
		return;
	}
}
●mapMove_Draw
単にメッセージを変更しただけです。

CODE:

	//	メッセージ
	if( bComment ) {
		int basey = 400;
		CenterDrawString( "「←↑→↓」で移動できます。", 20, basey, GetColor(210,210,255) );
		CenterDrawString( "「MENU」ボタンでメニューが開きます。", 20, basey+20, GetColor(210,210,255) );
		CenterDrawString( "「B」ボタンでバトル発生。", 20, basey+40, GetColor(210,210,255) );
	}
●mapMove_CheckEventChar
その方向にキャラクタがいるか判定します。
仮想的にキャラクタを一歩前に移動して、その位置でマップ固有のキャラクタと衝突するかでキャラクタが前にいるかチェックしています。
衝突したら、そのイベント番号を持ち帰ります。
衝突しない場合は、お約束の-1です。

CODE:

//----------------------------------------------------------------------
//	その方向にキャラクタがいるかイベントチェックする
//----------------------------------------------------------------------
static int mapMove_CheckEventChar( MapMoveInfo_t *mapMoveInfo, int muki, int px, int py )
{
	//	向きに合わせて仮に移動した座標を得る。一歩前にキャラクタがいるか確認するため。
	mapMove_MoveMuki( muki, &px ,&py, CHAR_PIXEL_SIZEX, CHAR_PIXEL_SIZEY );
	
	//	マップ固有のキャラクタとの衝突判定。
	int evtno = map_CharHitJudge(px,py);
	if( evtno >= 0 ) {//衝突
		//	前にいるキャラクタのイベント番号
		return evtno;
	}
	
	//	前にキャラクタはいません。
	return -1;
}
以上でイベント処理の準備は出来ました。
次はマップ情報やイベント・シナリオ命令を記述します。

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