簡単RPG講座9-3。ウィンドウ・システム本編3

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

簡単RPG講座9-3。ウィンドウ・システム本編3

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

[winMng.cpp]
プログラム編の続きで、内部関数編です。

●winmng_SetItemList
メニューかリストのウィンドウの設定をします。
項目数はここで数えておきます。項目のラストは項目名がNULLで判定です。
初期選択番号は0で固定してます。

CODE:

//----------------------------------------------------------------------
//	(内部)リストを設定する。
//----------------------------------------------------------------------
static void winmng_SetItemList(char **itemlist,int mode)
{
	//	アクティブなウィンドウがあるなら
	if( s_winData.ActiveNo != -1 ) {
		int winno = s_winData.ActiveNo;
		
		//	処理モード
		s_winData.win[winno].mode = mode;	//	現在のモード
		//	リストを設定します。
		s_winData.win[winno].itemList = itemlist;
		//	項目数を数えます。(最大値は適当です)
		s_winData.win[winno].listNums = 0;
		for( int m=0 ; m 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,GetColor(255,255,255),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,GetColor(255,255,255),TRUE );
	}
	//	持ち帰る。
	return rtnCode;
}
●winmng_DrawString
初回なら、必要な全種類の文字フォントハンドルを作成します。
もし描画が有効なら、指定された位置に指定された文字列を指定フォントで描画します。
描画なしなら、文字列を描画したときのドット幅を持ち帰ります。

CODE:

//----------------------------------------------------------------------
//	(内部)文字列描画処理
//----------------------------------------------------------------------
static int winmng_DrawString(int px,int py,char *str,int fonttype,int color,int bDraw)
{
	//	文字フォント
	static int bInit = FALSE;				//	初期化済み
	static int FontHandles[FONT_TYPE_MAX];	//	フォントハンドル
	
	//	未初期化ならフォントハンドルを作成。
	if( bInit==FALSE ) {
		bInit = TRUE;
		//	フォントのハンドルを作成。
		for( int f=0 ; f (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
ウィンドウに設定されたリストを描画します。
選択カーソルが有効なら、その位置に選択カーソルも描画します。
ちなみにspy,spyで位置や行間も制御されています。

CODE:

//----------------------------------------------------------------------
//	(内部)リストを描画する。
//----------------------------------------------------------------------
static void winmng_DrawItemList(int winno,int spx,int spy,int fonttype,int bCursor)
{
	//	ウィンドウ情報。
	int px			= s_winData.win[winno].px;		//	ウィンドウのピクセル位置X
	int py			= s_winData.win[winno].py;		//	ウィンドウのピクセル位置Y
	int sizex		= s_winData.win[winno].sizex;	//	ウィンドウのピクセルサイズX
	int sizey		= s_winData.win[winno].sizey;	//	ウィンドウのピクセルサイズY
	char *winName	= s_winData.win[winno].winName;	//	ウィンドウ名
	//	選択情報
	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,GetColor(255,255,255),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;
	}
}
●SjisZenkaku
序章で説明したとおり、全角(2バイト文字)かどうかを判断する関数です。
2バイト文字ならTRUE、それ以外はFALSEを返します。

CODE:

//----------------------------------------------------------------------
//	シフトJIS全角文字判定
//----------------------------------------------------------------------
static int SjisZenkaku(char *str)
{
	BYTE *bstr = (BYTE*)str;
	
	// SJIS全角文字判定
	if( ( (BYTE)0x81<=bstr[0] && bstr[0]<=(BYTE)0x9F ) ||
		( (BYTE)0xE0<=bstr[0] && bstr[0]<=(BYTE)0xFF )	) {
		return TRUE;//全角
	} else {
		return FALSE;//半角
	}
}
●NewLineCheck
これも序章で説明したとおり、改行コードを判定します。
今回の判定は0x0d,0x0aの組みと0x0a単体の改行コードの2種類に対応させました。

CODE:

//----------------------------------------------------------------------
//	改行コード判定
//----------------------------------------------------------------------
static int NewLineCheck(char *str)
{
	//	0x0d,0x0aの並びなら改行。
	if( str[0] != '\0' ) {
		if( str[0] == 0x0d ) {
			if( str[1] != '\0' ) {
				if( str[1] == 0x0a ) {
					//	2文字改行
					return 2;
				}
			}
		}
	}
	//	0x0aだけでも改行。
	if( str[0] != '\0' ) {
		if( str[0] == 0x0a ) {
			//	1文字改行
			return 1;
		}
	}
	
	//	改行ではない。
	return 0;
}
●ProhibitionCheck
これも序章で説明したとおり、禁則文字か判定しています。
2バイト文字と1バイト文字で二重にチェックしています。
禁則文字も不十分だと思いますので必要の合わせて増やす必要があります。

CODE:

//----------------------------------------------------------------------
//	禁則処理文字チェック
//----------------------------------------------------------------------
static int ProhibitionCheck(char *str)
{
	//	全角?
	if( SjisZenkaku(str) ) {
		//	禁則文字か?
		if( 0 == strncmp(str,"、",2) ||
			0 == strncmp(str,",",2) ||
			0 == strncmp(str,"。",2) ||
			0 == strncmp(str,".",2) ||
			0 == strncmp(str,")",2) ||
			0 == strncmp(str,"」",2) ) {
			//	禁則文字
			return TRUE;
		}
	} else {
		//	禁則文字か?
		if( 0 == strncmp(str,"、",1) ||
			0 == strncmp(str,",",1) ||
			0 == strncmp(str,"。",1) ||
			0 == strncmp(str,".",1) ||
			0 == strncmp(str,")",1) ||
			0 == strncmp(str,"」",1) ) {
			//	禁則文字
			return TRUE;
		}
	}
	//	禁則文字ではない。
	return FALSE;
}
以上で内部関数も終わりです。
いよいよ次はゲーム本編に組み込んでみましょう。

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