簡単RPG講座12-1。お店と宝箱。その1

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

簡単RPG講座12-1。お店と宝箱。その1

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

またまたシナリオに戻って、今回はお店と宝箱を作ります。
ダンジョンを接続しますので、これでこのRPG講座のマップは全部揃ったことになります。
まず、新規に作成した関数とかモジュールを説明します。

まず状態管理から、ヘッダです。
[stateMng.h]
●関数の宣言
関数を追加します。バグというか制御の都合のための関数ですね。
状態遷移の流れの中で、うまく初期化されない場合があってので機能追加しました。

CODE:

//	状態を強制設定する。フレームカウントは0に初期化される。
extern void STM_ResetState(STATEMNG_OBJECT object,int state);
続いてプログラム本体。
[stateMng.cpp]
●構造体
bResetを追加しています。

CODE:

//	状態管理オブジェクトの構造体
struct tag_StateMngObject {
	int nowState;			//現在の状態
	int beforeState;		//前の状態(STM_UpdateStateで現在の状態が変化なら保存)
	int nextState;			//次の状態(STM_UpdateStateで現在の状態にコピー)
	int stateNums;			//状態数
	int bBack;				//状態を戻すフラグ
	int bReset;				//状態を強制設定するフラグ
	int *pFlameCounts;		//フレームカウント配列。状態数分。
};
●STM_Init
bResetの初期化を追加。

CODE:

//----------------------------------------------------------------------
//	状態管理の初期化。オブジェクトを返す。
//----------------------------------------------------------------------
STATEMNG_OBJECT STM_Init(int stateNums)
{
	STATEMNG_OBJECT object = NULL;
	
	//	まず状態管理オブジェクトメモリを確保する。
	object = (STATEMNG_OBJECT)malloc( sizeof(struct tag_StateMngObject)) ;
	
	//	状態管理オブジェクトの値を初期化する。
	object->nowState = -1;			//現在の状態
	object->beforeState = -2;		//前の状態(STM_UpdateStateで現在の状態が変化なら保存)
	object->nextState = -3;			//次の状態(STM_UpdateStateで現在の状態にコピー)
	object->stateNums = stateNums;	//状態数
	object->bBack = FALSE;			//状態を戻すフラグ
	object->bReset = FALSE;			//状態を強制設定するフラグ
	object->pFlameCounts = NULL;	//フレームカウント配列。状態数分。
	
	//	フレームカウント配列を確保する。
	if( stateNums > 0 ) {
		object->pFlameCounts = (int*)malloc( sizeof(int) * stateNums );
	}
	
	//	状態管理オブジェクトを返す。
	return object;
}
●STM_ChangeState
ここもbResetの追加。くどいぐらいあちこちに追加があります。

CODE:

//----------------------------------------------------------------------
//	状態を遷移する。フレームカウントは0に初期化される。
//----------------------------------------------------------------------
void STM_ChangeState(STATEMNG_OBJECT object,int state)
{
	//	状態を遷移する準備。STM_UpdateStateで更新される。
	object->nextState = state;
	object->bBack = FALSE;			//状態を戻すフラグ
	object->bReset = FALSE;			//状態を強制設定するフラグ
}

●STM_ResetState
今回の目玉。強制設定関数の追加です。
フラグをセットしているだけで実際の処理は別の場所(STM_UpdateState)ですけどね。

CODE:

//----------------------------------------------------------------------
//	状態を強制設定する。フレームカウントは0に初期化される。
//----------------------------------------------------------------------
void STM_ResetState(STATEMNG_OBJECT object,int state)
{
	//	状態を遷移する準備。STM_UpdateStateで更新される。
	object->nextState = state;
	object->bBack = FALSE;			//状態を戻すフラグ
	object->bReset = TRUE;			//状態を強制設定するフラグ
}
●STM_SetBackState
ここもbResetの追加。

CODE:

//----------------------------------------------------------------------
//	前の状態に戻す。フレームカウントはそのまま。
//----------------------------------------------------------------------
void STM_SetBackState(STATEMNG_OBJECT object,int state)
{
	//	状態を遷移する準備。STM_UpdateStateで更新される。
	object->nextState = state;
	object->bBack = TRUE;	//状態を戻すフラグ
	object->bReset = FALSE;			//状態を強制設定するフラグ
}
●STM_UpdateState
いよいよ、実際の動作を定義します。
今までは、状態が変化したときのみフレームカウンタを0クリアしていましたが、強制設定(bReset)モードだと無条件に状態を設置してフレームカウンタを0クリアします。まぁ、お店メニューで問題が出たので、その対策なんですけどね。

CODE:

//----------------------------------------------------------------------
//	状態・フレームカウントを更新する。
//----------------------------------------------------------------------
void STM_UpdateState(STATEMNG_OBJECT object)
{
	int bTrans = FALSE; //状態遷移が無効
	
	//	状態の遷移?
	if( object->nextState != object->nowState ) {
		bTrans = TRUE;	//状態遷移する。
	}
	//	強制遷移?
	if( object->bReset ) {
		bTrans = TRUE;	//状態遷移する。
		object->bReset = FALSE;	//強制遷移を停止。
	}
	
	//	遷移有り?
	if( bTrans ) {
		//	今の状態を保存
		object->beforeState = object->nowState;
		//	新しい状態に遷移
		object->nowState = object->nextState;
		//	状態を戻した?
		if( object->bBack ) {
			//	フレームカウントを1つ加算。
			STM_SetFrameCount(object,STM_GetFrameCount(object)+1);
		} else {
			//	フレームカウントを初期化。
			STM_SetFrameCount(object,0);
		}
	} else {
		//	フレームカウントを1つ加算。
		STM_SetFrameCount(object,STM_GetFrameCount(object)+1);
	}
}
以上、stateMngでした。
続いては、ウィンドウ管理に関数を追加します。
[winMng.h]
まずヘッダに追加です。
●関数の宣言
ウィンドウの情報を返す関数を追加します。

CODE:

//	ウィンドウの情報を得る。
extern int winmng_GetWinParam(int winno,int *ppx,int *ppy,int *psizex,int *psizey);
続いて本体。
[winMng.cpp]
●winmng_GetWinParam
指定されたウィンドウ番号のウィンドウの情報を返す関数です。
全てポインタ参照の変数に代入する形でWindowの座標やサイズなどの値を返します。

CODE:

//----------------------------------------------------------------------
//	ウィンドウの情報を得る。
//----------------------------------------------------------------------
int winmng_GetWinParam(int winno,int *ppx,int *ppy,int *psizex,int *psizey)
{
	MACRO_ASSERT( winno>=0 );
	MACRO_ASSERT( winnomapCharFile[cn];//名前をローカル変数入れて扱いやすく
		if( file != NULL ) {
			//	マップ固有キャラをロードする。
			MapMngData.MapCharObj[cn] = char_Load(file,MAP_CHAR_XNUM,MAP_CHAR_YNUM);
			MapMngData.MapCharObjNums++;
			//	発生制御フラグを設定する。
			MapMngData.MapCharBorn[cn].bBorn = TRUE;	//発生可能フラグ
			if( NULL!=strstr(file,".one.png") ) {	//一回だけ発生の特殊キャラの名前。
				MapMngData.MapCharBorn[cn].bOnlyOne = TRUE;	//一回だけの発生。
			} else {
				MapMngData.MapCharBorn[cn].bOnlyOne = FALSE;//何回でも発生。
			}
		} else {
			//	マップ固有キャラは存在しない。
			MapMngData.MapCharObj[cn] = NULL;
			MapMngData.MapCharBorn[cn].bBorn = FALSE;	//発生可能フラグ
			MapMngData.MapCharBorn[cn].bOnlyOne = FALSE;//一回だけの発生。
		}
	}
	
	//	イベントレイヤーがない場合は発生しない。
	if( MapMngData.MapData[MAP_LAYER_EVENT] == NULL ) {
		return;
	}
	
	//	キャラ発生ポイントを全サーチ。
	for( DWORD x=0 ; x= EVENT_CHAR_BORN_NO) && (pno = MapMngData.MapCharObjNums ) objno = 0;
			//	一巡したらまずい。つまり割り当てる番号が無かった。
			MACRO_ASSERT( objno != *pBaseObjNo );
		}
	}
	//	オブジェクト番号を持ち帰る。
	return objno;
}
●map_CheckBornCharObjNo
指定されたキャラクタ・オブジェクト番号が発生可能か調べまてFALSE/TRUEを返します。
もし、発生可能でbOnlyOneなら以降は発生しない様にbBornをFALSEにします。

CODE:

//----------------------------------------------------------------------
//	(内部関数)キャラのオブジェクト番号が発生可能かチェックする。
//----------------------------------------------------------------------
static int map_CheckBornCharObjNo( int objno )
{
	//	オブジェクトが存在する?
	if( objno < MapMngData.MapCharObjNums ) {
		//	そのオブジェクトは発生可能?
		if( MapMngData.MapCharBorn[objno].bBorn ) {
			//	そのオブジェクトは一回きり?
			if( MapMngData.MapCharBorn[objno].bOnlyOne ) {
				//	発生完了で次回は発生しない。
				MapMngData.MapCharBorn[objno].bBorn = FALSE;
			}
			//	発生できる
			return TRUE;
		}
	}
	
	//	この番号では発生不能
	return FALSE;
}
と長くなりましたので一度区切ります。
次も下回りというか機能追加やら整理、新規モジュールの追加です。

きょーちゃん
記事: 11
登録日時: 14年前

Re: 簡単RPG講座12-1。お店と宝箱。その1

投稿記事 by きょーちゃん » 14年前

ようやくメッセージウィンドウまで到達しました。
早くリアルタイムで読めるようになりたいな~

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

Re: 簡単RPG講座12-1。お店と宝箱。その1

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

おぉ!結構早いですね。
メッセージウィンドウ後に練習問題がありますので、良かったら挑戦してください。

きょーちゃん
記事: 11
登録日時: 14年前

Re: 簡単RPG講座12-1。お店と宝箱。その1

投稿記事 by きょーちゃん » 14年前

練習問題とか超燃えます!!やってみます(>ε<)