簡単RPG講座13-2。戦闘システムの2

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

簡単RPG講座13-2。戦闘システムの2

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

続いては、色々な所をバトルに合わせて修正します。
[party.h]
パーティ処理のヘッダですが、魔法に関して問題があったので修正します。
●定数
魔法のタイプを追加。バトル用とフィールド用を同時指定可能にしました。

CODE:

//	魔法のタイプを指定する定数。party_getMagicData用
#define MAGIC_TYPE_FIELD	0x01	//まほう(フィールド)
#define MAGIC_TYPE_BATTLE	0x02	//まほう(バトル)
●関数の宣言
引数が変わりました。

CODE:

//	魔法情報を得る。
extern const MagicDef_t *party_getMagicData(PlayerParam_t *playerParam,int maig_list_no,int type);
//	魔法を使用する。
extern int party_useMagic(PlayerParam_t *playerParam,int maig_list_no,int type);
[party.cpp]
パーティ処理のプログラム側です。
●party_init
デバッグ用を無効にして、本来のパラメータを有効にします。
このとき最初の所持金を5と変えました。

CODE:

//----------------------------------------------------------------------
//	パラメータ初期化
//----------------------------------------------------------------------
void party_init(PlayerParam_t *playerParam)
{
	//	パラメータに初期値を与える。
#if 1
	playerParam->level = 1;				//レベル
	playerParam->expp = 0;				//経験値(Experience point)
	playerParam->hp = INI_HP_MAX;		//HP
	playerParam->hp_max = INI_HP_MAX;	//HPMAX
	playerParam->mp = INI_MP_MAX;		//MP
	playerParam->mp_max = INI_MP_MAX;	//MPMAX
	playerParam->attack = INI_ATTACK;	//攻撃力
	playerParam->def = INI_DEFENSE;		//防御力
	playerParam->money = 5;				//所持金
	for( int i=0 ; iitems[i] = ITEM_NON;//所持アイテム(4つまで)
	}
#else
	後略
●party_getMagicData
フィールドとバトルフラグで各々使える魔法かチェックできるようにしました。
type = MAGIC_TYPE_FIELD|MAGIC_TYPE_BATTLE
の場合は、どちらかで使えれば有効になります。

CODE:

//----------------------------------------------------------------------
//	魔法情報を得る。
//----------------------------------------------------------------------
const MagicDef_t *party_getMagicData(PlayerParam_t *playerParam,int maig_list_no,int type)
{
	//	魔法テーブルの検索
	int activeNo = 0;
	for( int i=0 ; i=0 );
	MACRO_ASSERT( py>=0 );
	MACRO_ASSERT( sizex>0 );
	MACRO_ASSERT( sizey>0 );
	
	//	bLiveがFALSEなウィンドウをサーチします。
	for( int i=0 ; i=0 );
	MACRO_ASSERT( winno=0  ; i-- ) {
			if( s_winData.win[i].bLive ) {
				s_winData.ActiveNo = i;
				return;
			}
		}
	}
}
●winmng_DelAllWin
メモリ解放が必要になったので、winmng_DelWin()で破棄するように変えました。

CODE:

//----------------------------------------------------------------------
//	全てのウィンドウを破棄します。
//----------------------------------------------------------------------
void winmng_DelAllWin()
{
	//	全てのウィンドウを閉じます。
	for( int i=0 ; i=0 );
	MACRO_ASSERT( winno=0 );
	MACRO_ASSERT( winno=0 );
	MACRO_ASSERT( winno 0 ) {
			//	開始フレームと今フレームから経過フレーム数を求めます。
			int passFrame = s_winData.frame - s_winData.win[winno].startFrame;
			//	それをスピードで割れば今の表示ポイントが分かります。
			//	演算順位で処理されれるとは言えカッコで囲んでおきましょう。
			s_winData.win[winno].msgNowPoint = s_winData.win[winno].msgEndPoint + (passFrame/speed);
		} else {
			//	最初から全てを表示。
			s_winData.win[winno].msgNowPoint = s_winData.win[winno].msgBuffSize;	//最大文字数を仮定で。
		}
		
		//	ポーズカーソルのフラグをOFF
		s_winData.win[winno].bPause = FALSE;	//	待機カーソル
		
		//	文字描画を描画なしの仮で呼び出して、文字列端で決定ボタンを
		//	押されたらTRUEで戻ります。
		int rtn = winmng_DrawMsg(winno,FALSE);
		switch( rtn ) {
		case DRAWMSG_RTN_CONTINE:	//表示継続中
			break;

		case DRAWMSG_RTN_WINEND:	//ウィンドウの終端
			//	ポーズカーソルのフラグ
			s_winData.win[winno].bPause = TRUE;	//	待機カーソル
			//	決定ボタンを受け付ける。
			if( g_MainData.key[g_MainData.key_act] == 1) {
				//	表示開始位置を変更する。
				s_winData.win[winno].msgStart = s_winData.win[winno].msgEnd;
				s_winData.win[winno].startFrame = s_winData.frame;	//開始フレームを再設定。
			}
			break;

		case DRAWMSG_RTN_MOJIEND:	//文字列終端
			//	ポーズカーソルのフラグ
			s_winData.win[winno].bPause = TRUE;	//	待機カーソル
			//	決定ボタンを受け付ける。
			if( g_MainData.key[g_MainData.key_act] == 1) {
				return TRUE;
			}
			//	ポーズ無しで自動送り。
			if( s_winData.win[winno].msgMode==MSG_MODE_AUTO ||
				s_winData.win[winno].msgMode==MSG_MODE_BTL_AUTO ) {
				return TRUE;
			}
			break;
		}
	}
	//	文字列終端に達していない。
	return FALSE;
}
●winmng_ClearMsg
アクティブなウィンドウのメッセージバッファの先頭から使うようにバッファをクリアします。

CODE:

//----------------------------------------------------------------------
//	内部メッセージバッファをクリアする。
//----------------------------------------------------------------------
void winmng_ClearMsg()
{
		//	アクティブなウィンドウがあるなら
	if( s_winData.ActiveNo != -1 ) {
		int winno = s_winData.ActiveNo;
		//	先頭から描画フラグ
		s_winData.win[winno].bMsgTop=TRUE;
		//	メッセージバッファをクリアする。
		strcpy(s_winData.win[winno].msgBuff,"");
	}
}
●(内部関数)winmng_DrawWin
ポーズカーソルを表示でMSG_MODE_PAUSE_MARKとMSG_MODE_BTL_PAUSEだけに表示を行うように変更。

CODE:

//----------------------------------------------------------------------
//	(内部)ウィンドウ描画処理
//----------------------------------------------------------------------
static void winmng_DrawWin(int winno,int bActive)
{
	//	ウィンドウが有効なら
	MACRO_ASSERT( s_winData.win[winno].bLive );
	
	//	ウィンドウの形状を描画する。
	winmng_DrawWinFrame( winno );
	
	//	メッセージなら
	switch( s_winData.win[winno].mode ) {
	case WIN_MODE_MSG:	//メッセージ・モード
		//	メッセージを描画する
		winmng_DrawMsg(winno,TRUE);
		
		//	アクティブ・ウィンドウだけ
		if( bActive ) {
			//	ポーズカーソルを表示(ポーズ状態でポーズマーク有り)
			if( s_winData.win[winno].bPause &&
				(	(s_winData.win[winno].msgMode==MSG_MODE_PAUSE_MARK) ||
					(s_winData.win[winno].msgMode==MSG_MODE_BTL_PAUSE)
				) ) {
				winmng_DrawPause(winno);
			}
		}
		break;
	
	case WIN_MODE_MENU:	//メニュー・モード
		//	メニューリストを描画する。
		winmng_DrawItemList(winno,s_FontData[FONT_TYPE_MENU].size*2,8,FONT_TYPE_MENU,TRUE);
		break;
	
	case WIN_MODE_LIST:	//リスト・モード
		//	データリストを描画する。
		winmng_DrawItemList(winno,4,4,FONT_TYPE_LIST,FALSE);
		break;
	}
}
●(内部関数)winmng_DrawWinFrame
ウィンドウ表示位置のofsxとofsyの対応。
int px = s_winData.win[winno].px + s_winData.win[winno].ofsx; // ウィンドウのピクセル位置X
int py = s_winData.win[winno].py + s_winData.win[winno].ofsy; // ウィンドウのピクセル位置Y

ウィンドウ枠のカラー変更に対応。
frame_color = s_winData.win[winno].frame_color;

CODE:

//----------------------------------------------------------------------
//	(内部)ウィンドウ形状の描画処理。
//----------------------------------------------------------------------
static void winmng_DrawWinFrame(int winno)
{
	//	ウィンドウ情報
	int px			= s_winData.win[winno].px + s_winData.win[winno].ofsx;	//	ウィンドウのピクセル位置X
	int py			= s_winData.win[winno].py + s_winData.win[winno].ofsy;	//	ウィンドウのピクセル位置Y
	int sizex		= s_winData.win[winno].sizex;	//	ウィンドウのピクセルサイズX
	int sizey		= s_winData.win[winno].sizey;	//	ウィンドウのピクセルサイズY
	char *winName	= s_winData.win[winno].winName;	//	ウィンドウ名
	
	//	ウィンドウの色
	int win_color,frame_color,title_color;
	win_color	= GetColor( 0,0,128 );
	frame_color	= s_winData.win[winno].frame_color;
	title_color	= GetColor(200,255,255);
	
	//	半透明のウィンドウを描く。
	SetDrawBlendMode(DX_BLENDMODE_ALPHA,WINDOW_BLEND_ALPHA_PARAM);	//アルファブレンド
	DrawBox( px, py, px+sizex, py+sizey, win_color, TRUE ) ; 
	SetDrawBlendMode(DX_BLENDMODE_NOBLEND,255);	//ノーマルブレンド
	
	//	外側の枠を描く。
	DrawLine(px-1,		py-1,		px+sizex,	py-1,		frame_color);	//上
	DrawLine(px-1,		py+sizey,	px+sizex,	py+sizey,	frame_color);	//下
	DrawLine(px-1,		py-1,		px-1,		py+sizey,	frame_color);	//左
	DrawLine(px+sizex,	py-1,		px+sizex,	py+sizey,	frame_color);	//右
	
	//	必要ならウィンドウ名を描画する。
	if( winName!=NULL ) {
		//	センタリングするため文字幅を先に得る。
		int fontsizex = winmng_DrawString(0,0,winName,FONT_TYPE_TITLE,0,FALSE);
		//	文字幅からセンタリング位置を得る。
		int posx = (sizex-fontsizex) / 2 + px;
		//	センタリングしてタイトルを表示。
		winmng_DrawString(posx,py+WINNAME_OFFSET_Y,winName, 
						FONT_TYPE_TITLE,title_color,TRUE );
	}
}
●(内部関数)winmng_DrawMsg
メッセージの一時バッファを動的確保に変更。
char *strbuf = (char*)malloc(s_winData.win[winno].msgBuffSize);
MACRO_ASSERT( strbuf!=NULL );

文字色変更に対応。
int font_color = s_winData.win[winno].font_color;// ウィンドウの文字色

ウィンドウ表示位置のofsxとofsyの対応。
int px = s_winData.win[winno].px + s_winData.win[winno].ofsx; // ウィンドウのピクセル位置X
int py = s_winData.win[winno].py + s_winData.win[winno].ofsy; // ウィンドウのピクセル位置Y


文字列終了位置を保存するようにしました。
s_winData.win[winno].msgEndPoint = len; // 表示終了位置(文字数単位の相対)

文字列描画でfont_colorを使うように変更。
winmng_DrawString(px+WINDOW_SPACE,posy,strbuf,
FONT_TYPE_MSG,font_color,TRUE );

残った文字列の描画でfont_colorを使うように変更。
if( strlen(strbuf) > 0 ) {
winmng_DrawString(px+WINDOW_SPACE,posy,strbuf,
FONT_TYPE_MSG,font_color,TRUE );
}

文字列バッファの解放を追加。
free( strbuf );

CODE:

//----------------------------------------------------------------------
//	(内部)メッセージ描画処理。文字列orウィンドウの終端ならTRUEを返す。
//----------------------------------------------------------------------
static int winmng_DrawMsg(int winno,int bDraw)
{
	char *strbuf = (char*)malloc(s_winData.win[winno].msgBuffSize);
	MACRO_ASSERT( strbuf!=NULL );
	
	int rtnCode = DRAWMSG_RTN_CONTINE;	//表示継続中
	
	//	ウィンドウ情報。
	int px			= s_winData.win[winno].px + s_winData.win[winno].ofsx;	//	ウィンドウのピクセル位置X
	int py			= s_winData.win[winno].py + s_winData.win[winno].ofsy;	//	ウィンドウのピクセル位置Y
	int sizex		= s_winData.win[winno].sizex;	//	ウィンドウのピクセルサイズX
	int sizey		= s_winData.win[winno].sizey;	//	ウィンドウのピクセルサイズY
	char *winName	= s_winData.win[winno].winName;	//	ウィンドウ名
	int font_color	= s_winData.win[winno].font_color;//	ウィンドウの文字色
	
	//	文字情報
	char *msgStart = s_winData.win[winno].msgStart;		//	表示開始位置(実際の場所)
	MACRO_ASSERT( msgStart!=NULL );
	int msgLen = s_winData.win[winno].msgNowPoint;		//	表示現在位置(文字数単位の相対)
	
	//	表示開始y座標。タイトルを避ける。
	int topy = py + WINDOW_SPACE;
	if( winName ) {
		topy += WINNAME_OFFSET_Y + s_FontData[FONT_TYPE_TITLE].size + 1;
	}
	
	//	文字列を表示単位までバッファに貯めて表示する。
	char *dst = strbuf;
	dst[0] = '\0';//仮の文字列終端。
	char *src = msgStart;
	int posy = topy;
	for( int len=0 ; len 0 ) {
			bNewLine = TRUE;
			src+= NewLineCodeSize;
		} else {
			//	全角文字をチェックする。
			if( SjisZenkaku(src) ) {
				//	2バイトコード(全角)
				dst[0] = src[0];
				dst[1] = src[1];
				dst++;src++;
				dst++;src++;
			} else {
				//	1バイトコード(半角)
				dst[0] = src[0];
				dst++;src++;
			}
		}
		dst[0] = '\0';//仮の文字列終端。
		
		//	出来上がった文字列長が一行をオーバーしていたら、改行処理。
		int fontsizex = winmng_DrawString(0,0,strbuf,FONT_TYPE_MSG,0,FALSE);
		if( fontsizex >= (sizex-s_FontData[FONT_TYPE_MSG].size-(WINDOW_SPACE*2)) ) {
			//	禁則処理判定で句読点かチェック
			if( ProhibitionCheck(src) ) {
				//	句読点用のサイズでチェックする。
				if( fontsizex >= (sizex-WINDOW_SPACE) ) {
					//	ここで改行する。
					bNewLine = TRUE;
				}
			} else {
				//	ここで改行する。
				bNewLine = TRUE;
			}
		}
		
		//	改行なら描画する。
		if( bNewLine ) {
			//	描画
			winmng_DrawString(px+WINDOW_SPACE,posy,strbuf, 
					FONT_TYPE_MSG,font_color,TRUE );
			//	改行
			posy += (s_FontData[FONT_TYPE_MSG].size + 1);
			//	文字列バッファを先頭に
			dst = strbuf;
			dst[0] = '\0';//仮の文字列終端。
			//	ウィンドウの下段に達したか?
			if( posy >= (topy+sizey-(WINDOW_SPACE*2)-s_FontData[FONT_TYPE_MSG].size) ) {
				//	一時中断ポイント
				rtnCode = DRAWMSG_RTN_WINEND;	//ウィンドウの終端
				break;
			}
		}
	}
	//	最後の位置を保存する。
	s_winData.win[winno].msgEnd = src;
	
	//	残った文字の処理。
	if( strlen(strbuf) > 0 ) {
		winmng_DrawString(px+WINDOW_SPACE,posy,strbuf, 
				FONT_TYPE_MSG,font_color,TRUE );
	}
	//	文字列バッファの解放
	free( strbuf );
	
	//	持ち帰る。
	return rtnCode;
}
●(内部関数)winmng_DrawPause
ウィンドウ表示位置のofsxとofsyの対応。
int px = s_winData.win[winno].px + s_winData.win[winno].ofsx; // ウィンドウのピクセル位置X
int py = s_winData.win[winno].py + s_winData.win[winno].ofsy; // ウィンドウのピクセル位置Y

CODE:

//----------------------------------------------------------------------
//	(内部)ポーズカーソルを表示
//----------------------------------------------------------------------
static void winmng_DrawPause(int winno)
{
	//	ウィンドウ情報
	int px			= s_winData.win[winno].px + s_winData.win[winno].ofsx;	//	ウィンドウのピクセル位置X
	int py			= s_winData.win[winno].py + s_winData.win[winno].ofsy;	//	ウィンドウのピクセル位置Y
	int sizex		= s_winData.win[winno].sizex;	//	ウィンドウのピクセルサイズX
	int sizey		= s_winData.win[winno].sizey;	//	ウィンドウのピクセルサイズY
	
	//	点滅周期で表示・非表示
#define PAUSE_BLINK_CYCLE	40
#define PAUSE_MARK_SIZE 	(WINDOW_SPACE*2)
	if( (s_winData.frame%PAUSE_BLINK_CYCLE) > (PAUSE_BLINK_CYCLE/2) ) {
		int x1 = px + ( sizex / 2 );
		int y1 = py + sizey + WINDOW_SPACE;
		int x2 = x1 - PAUSE_MARK_SIZE;
		int y2 = y1 - PAUSE_MARK_SIZE;
		int x3 = x1 + PAUSE_MARK_SIZE;
		int y3 = y1 - PAUSE_MARK_SIZE;
		//	三角形を描く
		DrawTriangle(x1,y1,x2,y2,x3,y3,GetColor(255,255,255),TRUE);
	}
}
●(内部関数)winmng_DrawItemList
ウィンドウ表示位置のofsxとofsyの対応。
int px = s_winData.win[winno].px + s_winData.win[winno].ofsx; // ウィンドウのピクセル位置X
int py = s_winData.win[winno].py + s_winData.win[winno].ofsy; // ウィンドウのピクセル位置Y

文字色変更に対応。
int font_color = s_winData.win[winno].font_color;// ウィンドウの文字色

文字色の変更に対応
// リスト項目を表示する。
winmng_DrawString(topx,topy,itemlist[sn],
FONT_TYPE_MENU,font_color,TRUE );

CODE:

//----------------------------------------------------------------------
//	(内部)リストを描画する。
//----------------------------------------------------------------------
static void winmng_DrawItemList(int winno,int spx,int spy,int fonttype,int bCursor)
{
	//	ウィンドウ情報。
	int px			= s_winData.win[winno].px + s_winData.win[winno].ofsx;	//	ウィンドウのピクセル位置X
	int py			= s_winData.win[winno].py + s_winData.win[winno].ofsy;	//	ウィンドウのピクセル位置Y
	int sizex		= s_winData.win[winno].sizex;	//	ウィンドウのピクセルサイズX
	int sizey		= s_winData.win[winno].sizey;	//	ウィンドウのピクセルサイズY
	char *winName	= s_winData.win[winno].winName;	//	ウィンドウ名
	int font_color	= s_winData.win[winno].font_color;//	ウィンドウの文字色
	
	//	選択情報
	char **itemlist = s_winData.win[winno].itemList;	//	リスト
	MACRO_ASSERT( itemlist!=NULL );
	int listNums = s_winData.win[winno].listNums;		//	リスト項目数
	int itemNo = s_winData.win[winno].itemNo;			//	選択番号

	//	表示開始座標。タイトルを避ける。
	int topx = px + spx;
	int topy = py + spy;
	if( winName ) {
		topy += WINNAME_OFFSET_Y + s_FontData[FONT_TYPE_TITLE].size + 1;
	}
	
	//	リストを表示する。
	for( int sn=0 ; sn<listNums ; sn++ ) {
		//	リスト項目を表示する。
		winmng_DrawString(topx,topy,itemlist[sn],
				FONT_TYPE_MENU,font_color,TRUE );
		//	選択カーソル?
		if( bCursor ) {
			//	選択項目ならカーソルを表示する。
			if( sn == itemNo ) {
				int x1 = topx - s_FontData[fonttype].size;
				int y1 = topy;
				int x2 = x1;
				int y2 = topy + s_FontData[fonttype].size;
				int x3 = x1 + PAUSE_MARK_SIZE;
				int y3 = topy + (s_FontData[fonttype].size/2);
				//	三角形を描く
				DrawTriangle(x1,y1,x2,y2,x3,y3,GetColor(255,255,255),TRUE);
			}
		}
		//	次の位置
		topy += s_FontData[fonttype].size + spy;
	}
}
以上でpartyとwinMngでした。
まだまだ続きます。

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