処理が重いのですが

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
しーろう

処理が重いのですが

#1

投稿記事 by しーろう » 14年前

現在、ゲームを製作しているのですがソフト屋さんの講座(http://dixq.net/forum/blog.php?u=114)を参考にして列挙型でゲーム全体の状態を振り分けるという形をとっています。

そのタイトル画面においてエラーや警告はないのですがやたら動作が遅く、FPSも指定の半分も下がってしまいます。(自分の環境が悪いのかもしれませんが)
title.cppとtitle.h、それと関係ありそうなところのソースを貼りますがどこがいけないのでしょうか。お願いします。ちなみにVisualC++2008を使っています。

コード:

//title.cpp
#include "DxLib.h"
#include "main.h"
#include "Keyboard.h"
#include "title.h"

MenuElement_t MenuElement[3]=
{
	{ 20, 100, "ゲームスタート" },
	{ 12, 200, "ヘルプ" },
	{ 12, 300, "ゲーム終了" },
};

static int SelectNum = 0;
static void Title_Calc();
static void Title_Draw();

//	タイトル画面
e_GameState Title(){

	Title_Calc();

	Title_Draw();

	if( KeyGet(KEY_INPUT_RETURN) == 1 )
	{
		if(SelectNum == 0)
		{
			return Game_State_Main;		//ゲームメインへ
		}
	}

	return g_MainData.GameState;		//継続する

}

//タイトル画面の計算
static void Title_Calc()
{
	if( KeyGet(KEY_INPUT_DOWN) == 1 )
	{
		SelectNum = (SelectNum + 1) % 3	;	//下方向へループ
	}
	if( KeyGet(KEY_INPUT_UP) == 1 )
	{
		SelectNum = (SelectNum + 2) % 3	;	//上方向へループ
	}
	if( KeyGet(KEY_INPUT_DOWN) >= 1 || KeyGet(KEY_INPUT_UP) >= 1)
	{
		for( int i=0 ; i < 3 ; i++ )
		{
			if(i = SelectNum)
			{
				MenuElement[i].fontsize = 20;
			} else {
				MenuElement[i].fontsize = 12;
			}
		}
	}
}

//タイトル画面を描く
static void Title_Draw()
{
	CenterDrawString(GAME_TITLE_STR, 32, 30, GetColor(255,255,255));

	for( int i=0 ; i < 3 ; i++ )
	{
		CenterDrawString(MenuElement[i].name , MenuElement[i].fontsize , MenuElement[i].y , GetColor(255,255,255));
	}
}

コード:

//title.h
#ifndef	DEF_TITLE_H
#define	DEF_TITLE_H

typedef struct {
	int fontsize , y ;
	char name[128];
} MenuElement_t;

extern	e_GameState Title();

#endif	DEF_TITLE_H

コード:

//main.cpp
//	中央に文字を出す。
void CenterDrawString( char *str, int fontsize, int y, int color )
{
	SetFontSize( fontsize );									//文字の大きさ
	int StrSizeX = GetDrawStringWidth(str,(int)strlen(str));	//文字表示の幅を得る。
	DrawString( (640-StrSizeX)/2, y, str, color );			//センターに表示
}

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

Re: 処理が重いのですが

#2

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

ぱっと目についたのは
if(i = SelectNum)
が条件式ではなく代入になっているのでバグだと思います。

ただ、これで処理落ちすると思えませんので、ここのコード以外に原因が考えられます。
GetNowCount()などで処理時間を計測されてみてはどうでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

しーろう

Re: 処理が重いのですが

#3

投稿記事 by しーろう » 14年前

キー入力がされると処理が止まってしまうようです。

メインループで41ms、Title()が32msでした。

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

Re: 処理が重いのですが

#4

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

しーろう さんが書きました:キー入力がされると処理が止まってしまうようです。
メインループで41ms、Title()が32msでした。
メインループ自体が異様に重いですね。
幾つかの関数を抽出して、それぞれ時間を計測してみて下さい。
何処かに重い原因があります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

しーろう

Re: 処理が重いのですが

#5

投稿記事 by しーろう » 14年前

メインループ41ms = switch(ゲーム全体の状態振り分け)30ms + FPS表示関数10ms + その他の関数

という感じでした。
しかしゲーム状態がタイトル以外の時はメインループは12msで、switchは0ms、FPS表示関数12msとなりました。

FPS表示関数は

コード:

void DrawFps()
{
	//	平均フレーム時間が求まっていたら表示する。
	if(s_AveTime!=0){
		SetFontSize( 14 );//文字の大きさ
		DrawFormatString(0, 0,GetColor(255,255,255),"%.1fFPS",1000.0/(double)s_AveTime);
		DrawFormatString(0,20,GetColor(255,255,255),"%dms"	,s_AveTime);
	}
}
という感じです。正直いまいち理解できていないのですが。
試しにこの関数をコメント化してタイトル以外の状態を実行すると0msだったので、
結果から見るとやはりTitle()に問題があるように思えます。

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

Re: 処理が重いのですが

#6

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

この中で怪しいのはDrawFormatStringですね。DrawFpsだけでも重すぎです。
あと初期化あたりだけみせてください。画面関係のパラメータがなにか悪さしているかも。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

しーろう

Re: 処理が重いのですが

#7

投稿記事 by しーろう » 14年前

初期化は最初の本当に何も。最初のゲーム状態の指定だけです。

コード:

void Game_Init(){
	g_MainData.GameState = Game_State_Title;//タイトル画面で起動
}

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

Re: 処理が重いのですが

#8

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

私のとほとんど同じと考えて良いでしょうか?
だとするとDrawFormatStringの速度を検証してみてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: 処理が重いのですが

#9

投稿記事 by ISLe » 14年前

SetFontSizeだけコメントアウトしたらどうなります?

しーろう

Re: 処理が重いのですが

#10

投稿記事 by しーろう » 14年前

お久しぶりです。事情があってこの数日間書き込めませんでした。
申し訳ございません。

>>ソフト屋さん
1msでした。

>>ISLeさん
FPSはわずかに戻りましたが、やはりキー入力を受け取ると止まってしまうようです。

キーの入力をされると固まってしまうのは計算フェーズに問題があるのでしょうか?

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

Re: 処理が重いのですが

#11

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

私の指摘した
if(i = SelectNum)
は直されたんですよね?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

しーろう

Re: 処理が重いのですが

#12

投稿記事 by しーろう » 14年前

すみません。直していませんでした。
直したら通常に動作するようになりました。

しかし、FPSは指定の60よりも大きく下回って20のままです。

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

Re: 処理が重いのですが

#13

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

とりあえず1命令づつ怪しいところから削って(追記:コメントアウトして)そのたびに試して60fpsから低下させている原因を見つけるしかなさそうです。
この命令を削ったら60fpsになったというポイントを見つけて下さい。

たとえば、DrawFpsは10msでしたよね。

コード:

void DrawFps()
{
    //  平均フレーム時間が求まっていたら表示する。
    if(s_AveTime!=0){
        SetFontSize( 14 );//文字の大きさ ← 8ms?
        DrawFormatString(0, 0,GetColor(255,255,255),"%.1fFPS",1000.0/(double)s_AveTime); ← 1ms
        DrawFormatString(0,20,GetColor(255,255,255),"%dms"  ,s_AveTime); ← 1ms
    }
}
など推測を重ねて、怪しいところを燻り出すしか無いです。

で、ここの問題として時間計測自体が処理落ちの原因だと話しにならないので計測の仕方には十分注意して下さい。
ここでは、計測だけして表示は後でとか工夫してくださいね。

あと短めの再現コードができたら、ここに全ソースコードを貼ってもらったほうが話が早いです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

しーろう

Re: 処理が重いのですが

#14

投稿記事 by しーろう » 14年前

短めの再現コードができたら、ここに全ソースコードを貼ってもらったほうが話が早い
というのはどういうことでしょうか?関数ごとの時間計測の結果を書いて貼れば良いのでしょうか?

あと、検証方法についてですが

コード:

int StartTime = GetNowCount();
		//計測したい処理
int EndTime = GetNowCount() - StartTime;
DrawFormatString(0,400,GetColor(255,255,255),"%dms",EndTime);
という方法でいいのでしょうか。今更ですが計測方法が間違っていたら今までの全てやこれからのことが意味を持たないので。

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

Re: 処理が重いのですが

#15

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

>というのはどういうことでしょうか?関数ごとの時間計測の結果を書いて貼れば良いのでしょうか?

できるだけ短いソースコードで状況を再現できる全ソースコードのことです。
WinMainから全てのコードで1ファイルに収まっているものが望ましいです。

>という方法でいいのでしょうか。今更ですが計測方法が間違っていたら今までの全てやこれからのことが意味を持たないので。
DrawFormatString(0,400,GetColor(255,255,255),"%dms",EndTime);
が他の計測に影響を与えていなければOKです。つまり、多ポイント計測するならあとで纏めて表示されたほうが良いって事ですね。

それと
int StartTime = GetNowCount();
int EndTime = GetNowCount() - StartTime;
は何回挟んでも問題ないです。
この場合はEndTime と言うよりRunTimeですけどね。
まとめて計測・表示するなら、
#define RUN_TIME_PIONT 5
int RunTime[RUN_TIME_PIONT];
とかグローバル変数の配列にして使ったほうが良いですけどね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

しーろう

Re: 処理が重いのですが

#16

投稿記事 by しーろう » 14年前

なるほど。勉強になりました、ありがとうございます。

早速やってきます!

閉鎖

“C言語何でも質問掲示板” へ戻る