ページ 11

ノベル風文字表示が処理落ち?

Posted: 2011年5月26日(木) 11:46
by ヤット
初めまして、ヤットと申します。最近ゲームプログラミングを始めたばかりなのですが、どうしてもうまくいかない件で相談しにきました。

でんさんラボというサイトで公開されているサンプルを参考にして、ノベルゲーム風の文字表示を行いたく以下のようなコードを作成しました。
下記のコードのMes_Drawをメイン関数のループから毎回呼び出すと、一見うまく動作するのですが、表示が100文字を超えた辺りから急に表示が遅くなります。
FPSを確認したところ、62.5FPSから下がり始め、20FPS程度まで落ちてしまいます。(PCはXP,PEN4 3GHz)

参考にしたサンプルではメイン関数のループ中にSleepを入れており、Mes_Draw関数の呼び出し頻度は文字を進める時のみなのに対し、
当方ではループ毎に呼び出しています(引数で文字を進めるか否かを判定)
これは、文字表示処理と同時に、他のグラフィックなどのアニメーション表示もしたい時のためを思ってのことなのですが……おそらくうまくいかない原因はこれだと思っています。
ただ、どのように改善して良いのかわからず。。。そもそも参考にしたサンプルが、バックグラウンドでのアニメーションを想定してないのかもしれませんが、うーん。。。と唸っている状態です、お知恵をお借りできますでしょうか?

コード:


#include "DxLib.h"
#include <string.h>
//メッセージフォントのサイズ
#define MESSAGE_FONT_SIZE 28
//メッセージの最大文字数
#define MESSAGE_MAX_LENGTH 25
//メッセージの最大行数
#define MESSAGE_MAX_LINE 12


char g_Mes[ MESSAGE_MAX_LENGTH * MESSAGE_MAX_LINE ];
char g_MesBuffer[MESSAGE_MAX_LINE][MESSAGE_MAX_LENGTH * 2];
static int g_CurrentMes;	//現在何文字目まで表示しているか
static int g_CurrentLine;	//現在何行目の文字を表示しているか

void Mes_init()
//動作テスト用の文字列を用意
{
	strcpy( g_Mes, "財務省が25日発表した4月の貿易統計速報(通関ベース)によると、輸出額から輸入額を差し引いた貿易収支は、東日本大震災の影響で輸出が停滞、4637億円の大幅な赤字となった。赤字は3カ月ぶりで、4月としては第2次石油危機に見舞われた1980年以来31年ぶり。震災による部品供給網の寸断が響き、自動車などの生産が滞り、輸出額が前年同月比12.5%減と3月(2.3%減)から落ち込み幅が拡大。一方、エネルギー資源を中心に輸入が増加、赤字に転落した。");
}

//日本語かどうかチェックする 戻り値1:日本語 戻り値0:日本語ではない
int CheckJapanese( unsigned char code )
{
	if ( (code >= 0x81 && code <= 0x9F ) ||
		 (code >= 0xE0 && code <= 0xFC ) ){
			 return 1;
	}
	return 0;
}


// char* messageで指定した文章を start の位置から len 文字分表示する
// 表示座標は int x,y 表示色は col で指定
void writeString(char* message, int start, int len, int x, int y, int col, int bufferLine)
{
	int i;
	int MaxLen = strlen (message);	//メッセージの長さを取得


	// startの位置を調整
	// startの指定位置までに日本語があったら、その分1足す
	
	for ( i=0; i < start && message[i] != '\0'; ) {
		if( CheckJapanese( message[i] ) ) {
			//日本語 2プラス
			i += 2;
			//start位置+1
			start ++;
		}else{
			//半角文字 1プラス
			i ++;
		}
	}
	
	if ( start >= MaxLen){
		return;
	}


	//指定位置(start +- 調整分)からlen文字分表示
	for ( i=0; i < len && message[ start + i ] != '\0'; ){
		if ( CheckJapanese( message[start+i] ) ) {
			//日本語表示(バッファーに入れる)
			g_MesBuffer[bufferLine][ i     ] = message[ start + i    ];
			g_MesBuffer[bufferLine][ i + 1 ] = message[ start + i + 1];
			//len(長さ)は 日本語なので1バイト分追加
			len ++;
			// iを2進める
			i += 2;
		}else{
			//半角文字・1文字表示(Bufferに格納)
			g_MesBuffer[bufferLine][i] = message[ start + i ];
			i ++;
		}
	}
	g_MesBuffer[bufferLine][i] = '\0';

	//実際に描写します
	DrawString( x, y, g_MesBuffer[bufferLine], col );

}

// メッセージ表示
void Mes_Draw( int Flag )
	// Flag == 0 で文字を進める。メイン関数のループカウントを文字表示速度で割った余りを引数にする 例:Mes_Draw( count % 10 ) 
{
	int i;

	// 文字を1進める
	if ( Flag==0 && g_Mes[g_CurrentMes] != '\0' ) {
		g_CurrentMes ++;
	}

	//MESSAGE_MAX_LENGTHまで描写したら段落を進める
	if ( Flag==0 && g_CurrentMes % MESSAGE_MAX_LENGTH == 0 ){
		if ( g_Mes[ g_CurrentMes ] != '\0' ){
			g_CurrentLine ++;
		}
	}

	//メッセージ描写
	for ( i = 0; i < MESSAGE_MAX_LINE ; i++ ){
		if ( i == g_CurrentLine ){
			//メッセージ風
			writeString( g_Mes, i*MESSAGE_MAX_LENGTH, g_CurrentMes - MESSAGE_MAX_LENGTH * i, 0, 0 + MESSAGE_FONT_SIZE * i, GetColor(255,255,255), i );
			break;
		}else{
			//一度に表示
			writeString( g_Mes, i*MESSAGE_MAX_LENGTH, MESSAGE_MAX_LENGTH, 0, 0 + MESSAGE_FONT_SIZE * i, GetColor(255,255,255), i );
		}
	}

}


Re: ノベル風文字表示が処理落ち?

Posted: 2011年5月26日(木) 12:27
by softya(ソフト屋)
参考にされたのはこちらでは無いのでしょうか?

「ゲーム作りで学ぶ! 実践的C言語プログラミング - karetta.jp」
http://karetta.jp/book-cover/game-programming

Re: ノベル風文字表示が処理落ち?

Posted: 2011年5月26日(木) 12:41
by ヤット
参考にしたのはそちらのゲーム作りで学ぶ! 実践的C言語プログラミング で間違いありません。

http://densan-labs.net/tech/game
当方はこちらから閲覧していたのですが、内容は同じ物のようですね

Re: ノベル風文字表示が処理落ち?

Posted: 2011年5月26日(木) 12:54
by softya(ソフト屋)
とりあえず、
for ( i = 0; i < MESSAGE_MAX_LINE ; i++ ){
でぐるぐる回しているのがまずいと思います。

メッセージ表示のサンプルと設計の仕方が私日記にありますので、参考にしてみてください。
※ RPG講座の一環なので長いですが。
「マイ 日記 • C言語交流フォーラム ~ mixC++ ~ RPG講座」
http://dixq.net/forum/blog.php?u=114&sd=a&c=2
「ちょー簡単RPG講座 設計・製作の手順公開」 on 2010年11月18日(木) 17:41 カテゴリ: 講座
からがメッセージウィンドウの設計と表示の仕方を解説しています。

[追記]
あぁ、わかりました。
今のままでも少し改造すれば良いかも知れません。
ちと考えてみます。ちょっとまってください。

Re: ノベル風文字表示が処理落ち?

Posted: 2011年5月26日(木) 13:31
by ヤット
お手数をおかけしますがよろしくお願いします。

ちょー簡単RPG講座があったことを知りませんでした
ためになりそうなのでこの機会に読み込もうと思いますっ

Re: ノベル風文字表示が処理落ち?

Posted: 2011年5月26日(木) 13:44
by softya(ソフト屋)
コードを理解しました。問題点を列挙しましす。
・g_CurrentMesがバイト文字の位置として扱われているところとマルチバイト文字の位置として扱われているところが混在している。
writeString()内ではマルチバイト文字の位置として扱っているが、Mes_Draw()ではバイト位置として使っているので処理に矛盾が生じていある。
・g_CurrentLineが実際にMESSAGE_MAX_LENGTHを超えてもガードしていない。
・(g_CurrentMes%MESSAGE_MAX_LENGTH) == 0が改行位置と仮定するのは無理がある。
その例:半角と全角が混在したとき、改行文字が途中にあった時。

Re: ノベル風文字表示が処理落ち?

Posted: 2011年5月26日(木) 16:40
by ヤット
問題点のご指摘ありがとうございます。
文字列の取り扱いに対する理解が足りていないですねorz
勉強します。

講座のウィンドウシステム編が、やりたかった事がズバリ説明されているのでそちらを参考にして、もう一度コードを書きなおそうと思います。

また質問することもあると思いますがその時はよろしくお願いします。