処理が重い

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

処理が重い

#1

投稿記事 by kloud » 7年前

今、DirectXで簡単なゲームを作っています。
シーン遷移をタイトル、ゲーム、リザルトとし、game.cpp内の関数でゲーム処理を一括管理しています。(InitGame内でInitObjectなどをしています)
そんな中ゲーム画面において、プレイヤー、オブジェクトなど色々な処理が多くなり、だんだんと処理が重くなってきました。
ここでお聞きしたいのですが、描画処理など少しでも軽くさせるようなことはできないでしょうか?(SetTextureの位置や頂点バッファなどが不適切?)
main.cpp以外にobject.cppだけ載せますが、他のプロジェクトも書き方はほとんど同じです。
どなたかよろしくお願いします。

<main.h>

コード:

#ifndef _MAIN_H_
#define _MAIN_H_

/*==============================*/
/*     インクルードファイル     */
/*==============================*/
#include <stdio.h>
#include <Windows.h>
#include <d3dx9.h>

#define DIRECTINPUT_VERSION ( 0x0800 )
#include <dinput.h>
#include <XAudio2.h>

#pragma comment ( lib , "d3d9.lib" )
#pragma comment ( lib , "d3dx9.lib" )
#pragma comment ( lib , "dxguid.lib" )
#pragma comment ( lib , "dinput8.lib" )
#pragma comment ( lib , "winmm.lib" )

/*====================*/
/*     マクロ定義     */
/*====================*/
#define CLASS_NAME     "サンプル"  
#define WINDOW_NAME    "Direct3D"     
#define NUM_VERTEX ( 4 )               
#define SCREEN_WIDTH ( 800 )            
#define SCREEN_HEIGHT ( 600 )          
#define FVF_VERTEX_2D ( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 )   

/*====================*/
/*     頂点構造体     */
/*====================*/
typedef struct 
{
	D3DXVECTOR3 pos;
	float rhw;
	D3DCOLOR color;
	D3DXVECTOR2 tex;
}VERTEX_2D;

/*========================*/
/*     画面遷移構造体     */
/*========================*/
typedef enum
{
	MODE_TITLE = 0 ,
	MODE_GAME , 
	MODE_RESULT , 
	MODE_MAX
}MODE;

/*==========================*/
/*     プロトタイプ宣言     */
/*==========================*/
LRESULT CALLBACK WndProc ( HWND hWnd , UINT uMsg , WPARAM wParam , LPARAM lParam );
HRESULT Init ( HINSTANCE hInstance , HWND hWnd , BOOL bWindow );          // 初期化処理
void Uninit ( void );                                                     // 終了処理
void Update ( void );                                                     // 更新処理
void Draw ( void );                                                       // 描画処理

#ifdef _DEBUG
void DrawFPS ( void );                                                    // デバック表示用関数
#endif

LPDIRECT3DDEVICE9 GetDevice ( void );     // デバイス状態取得
void SetMode ( MODE );                    // 画面モードセット
MODE GetMode ( void );                    // 画面モード取得


#endif     // _MAIN_H_

//==============================   EOF   ==============================//
<main.cpp>

コード:

/*==============================*/
/*     インクルードファイル     */
/*==============================*/
#include "main.h"
#include "input.h"
#include "sound.h"
#include "result.h"
#include "title.h"
#include "game.h"
#include "player.h"

/*========================*/
/*     グローバル変数     */
/*========================*/
LPDIRECT3D9 g_pD3D = NULL;
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL;
int g_nCountFPS = 0;          
MODE g_mode = MODE_TITLE;     
MODE mode;                   
#ifdef _DEBUG
LPD3DXFONT g_pFont = NULL;
#endif

int APIENTRY WinMain ( HINSTANCE hInstance , HINSTANCE hPrevInstance , LPSTR lpCmdLine , int nCmdShow )
{
	UNREFERENCED_PARAMETER ( hPrevInstance );
	UNREFERENCED_PARAMETER ( lpCmdLine );
	
	WNDCLASSEX wcex =
	{
		sizeof ( WNDCLASSEX ) ,
		CS_CLASSDC ,                          
		WndProc ,                             
		0 ,                                   
		0 ,                                   
		hInstance ,                           
		NULL ,                                
		LoadCursor ( NULL , IDC_ARROW ) ,     
		( HBRUSH ) ( COLOR_WINDOW + 1 ) ,     
		NULL ,                                
		CLASS_NAME ,                          
		NULL
	};

	RegisterClassEx ( &wcex );

    static HWND hWnd; 
	static MSG msg;

	// ウィンドウスタイル定義
	const int wstyle = WS_OVERLAPPEDWINDOW &~ WS_MINIMIZEBOX &~ WS_MAXIMIZEBOX &~ WS_THICKFRAME;

	RECT cr = { 0 , 0 , SCREEN_WIDTH , SCREEN_HEIGHT };
    AdjustWindowRect ( &cr , wstyle , FALSE );

	int ww = cr.right - cr.left;     // 画面(ウィンドウ表示)幅
	int wh = cr.bottom - cr.top;     // 画面(ウィンドウ表示)高

	// 初期ウィンドウ位置を真ん中に設定
	RECT dr;

    GetWindowRect ( GetDesktopWindow() , &dr );

    int dw = dr.right - dr.right;
    int dh = dr.bottom - dr.top;
    int wx = ww > dw ? 0: ( dw - ww ) / 2;
    int wy = wh > dh ? 0: ( dh - wh ) / 2;

    // ウィンドウを作成
	hWnd = CreateWindowEx ( 0 ,                       
		                    CLASS_NAME ,              
							WINDOW_NAME ,             
							wstyle ,     
							wx,           
							wy,           
		                    ww ,            
							wh ,           
							NULL ,                    
							NULL ,                    
							hInstance ,            
							NULL                      
							);

	// ウィンドウの表示
	ShowWindow ( hWnd , nCmdShow );     
	UpdateWindow ( hWnd );              

	Init ( hInstance , hWnd , TRUE );     // 初期化

	// 分解能の設定
	timeBeginPeriod ( 1 );

	// 各カウンターの初期化
	DWORD dwFrameCount = 0;
	DWORD dwCurrentTime = 0;
	DWORD dwExecLastTime = timeGetTime ();
	DWORD dwFPSLastTime = dwExecLastTime;

	// ゲームループ
	while ( GetMessage ( &msg , NULL , 0 , 0 ) )
	{
		for ( ;; )
		{
			if ( PeekMessage ( &msg , NULL , 0 , 0 , PM_REMOVE ) != 0 )
			{
				// Windowsの処理
				if ( msg.message == WM_QUIT )
				{
					break;
				}
				else
				{
					// メッセージの翻訳と送出
		            TranslateMessage ( &msg );
		            DispatchMessage ( &msg );
					break;
		  		}
			}
			else
			{
				dwCurrentTime = timeGetTime ();          // システム時間の取得

				if  ( ( dwCurrentTime - dwFPSLastTime ) >= 500 )
				{
					g_nCountFPS = ( dwFrameCount * 1000 ) / ( dwCurrentTime - dwFPSLastTime );
					dwFPSLastTime = dwCurrentTime;
					dwFrameCount = 0;
				}

				if ( ( dwCurrentTime - dwExecLastTime ) >= ( 1000 / 60 ) )
				{
					dwExecLastTime = dwCurrentTime;      // 処理した時間を保存

				    // DirectXの処理
				    Update ();          // 更新処理
				    Draw ();            // 描画処理

					dwFrameCount++;
				}
			}
		}
	}

	timeEndPeriod ( 1 );                // タイマ終了
	Uninit ();                          // 終了処理

	return msg.wParam;     
}

LRESULT CALLBACK WndProc ( HWND hWnd , UINT uMsg , WPARAM wParam , LPARAM lParam )
{
	switch ( uMsg )
	{
	   case WM_KEYDOWN:
	   	   if( wParam == VK_ESCAPE )
	   	   {
	   	      UINT nID = MessageBox ( NULL , "ウィンドウを閉じますか?" , "Message" , MB_YESNO );

	   	      if ( nID == IDYES )
	   	      {
	   	          DestroyWindow ( hWnd );
	   	      }  
	   	   }

	   	   break;
	   	   
	   case WM_DESTROY:
	   	   PostQuitMessage ( 0 );

	   	   break;
	}

	return DefWindowProc ( hWnd , uMsg , wParam , lParam );
}

/*====================*/
/*     初期化関数     */
/*====================*/
HRESULT Init ( HINSTANCE hInstance , HWND hWnd , BOOL bWindow )
{
	D3DPRESENT_PARAMETERS d3dpp;

	D3DDISPLAYMODE d3ddm;

	g_pD3D = Direct3DCreate9 ( D3D_SDK_VERSION );

	if ( g_pD3D == NULL )
	{
		return E_FAIL;
	}

	if ( FAILED ( g_pD3D -> GetAdapterDisplayMode ( D3DADAPTER_DEFAULT , &d3ddm ) ) )
	{
		return E_FAIL;
	}

	ZeroMemory ( &d3dpp , sizeof ( d3dpp ) );

	d3dpp.BackBufferWidth = SCREEN_WIDTH;
	d3dpp.BackBufferHeight = SCREEN_HEIGHT;
	d3dpp.BackBufferFormat = d3ddm.Format;
	d3dpp.BackBufferCount = 1;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;                           
	d3dpp.EnableAutoDepthStencil = TRUE;                                
	d3dpp.AutoDepthStencilFormat = D3DFMT_D16;                         
	d3dpp.Windowed = bWindow;                                          
	d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;         
	d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;           

	// Direct3Dデバイスの作成
	if ( FAILED ( g_pD3D -> CreateDevice ( D3DADAPTER_DEFAULT ,
		                                   D3DDEVTYPE_HAL ,                         
										   hWnd ,                                   
										   D3DCREATE_HARDWARE_VERTEXPROCESSING ,    
										   &d3dpp ,                                 
										   &g_pD3DDevice ) ) )                      
	{
		if ( FAILED ( g_pD3D -> CreateDevice ( D3DADAPTER_DEFAULT ,
		                                   D3DDEVTYPE_HAL ,                         
										   hWnd ,                                   
										   D3DCREATE_SOFTWARE_VERTEXPROCESSING ,  
										   &d3dpp ,                                 
										   &g_pD3DDevice ) ) )                      
	    {
			if ( FAILED ( g_pD3D -> CreateDevice ( D3DADAPTER_DEFAULT ,
		                                   D3DDEVTYPE_REF ,                         
										   hWnd ,                                   
										   D3DCREATE_SOFTWARE_VERTEXPROCESSING ,   
										   &d3dpp ,                                 
										   &g_pD3DDevice ) ) )                      
	        {
				return E_FAIL;
			}
		}
	}

	#ifdef _DEBUG
	D3DXCreateFont ( g_pD3DDevice ,
		             18 ,                         
					  0 ,                         
					  0 ,                         
					  0 ,                         
					 FALSE ,                     
					 SHIFTJIS_CHARSET ,           
					 OUT_DEFAULT_PRECIS ,
					 DEFAULT_QUALITY ,
					 DEFAULT_PITCH ,
					 "Terminal" ,                 
					 &g_pFont
					 );
    #endif // _DEBUG
	
	//g_pD3DDevice -> SetRenderState ( D3DRS_CULLMODE , D3DCULL_CCW );

	g_pD3DDevice -> SetRenderState ( D3DRS_ALPHABLENDENABLE , TRUE );
	g_pD3DDevice -> SetRenderState ( D3DRS_SRCBLEND , D3DBLEND_SRCALPHA );
	g_pD3DDevice -> SetRenderState ( D3DRS_DESTBLEND , D3DBLEND_INVSRCALPHA );

	//g_pD3DDevice -> SetSamplerState ( 0 , D3DSAMP_MINFILTER , D3DTEXF_LINEAR );
	g_pD3DDevice -> SetSamplerState ( 0 , D3DSAMP_MAGFILTER , D3DTEXF_LINEAR );
	
	SetMode ( g_mode );

	InitKeyboard ( hInstance , hWnd );
	InitSound ( hWnd );
	InitGame ();

	return S_OK;
}

/*==================*/
/*     終了処理     */
/*==================*/
void Uninit ( void )
{
	if ( g_pD3DDevice != NULL )
	{
		// Direct3Dデバイスの解放
		g_pD3DDevice -> Release ();
		g_pD3DDevice = NULL;
	}
	
	if ( g_pD3D != NULL )
	{
		// Direct3Dインタフェースの解放
		g_pD3D -> Release ();
		g_pD3D = NULL;
	}

	UninitKeyboard ();
	UninitSound ();
	UninitGame ();

	#ifdef _DEBUG
	if ( g_pFont != NULL )
	{
		// フォントの解放
		g_pFont -> Release ();
		g_pFont = NULL;
	}
    #endif
}

/*==================*/
/*     更新処理     */
/*==================*/
void Update ( void )
{	
	UpdateKeyboard ();

	switch ( g_mode )
	{
	    case MODE_TITLE:
	    	
			UpdateTitle ();
			
			if ( GetKeyboardPress ( DIK_RETURN ) )
			{
			    SetMode ( MODE_GAME );
			}
	    	break;
	    
	    case MODE_GAME:
	        
			UpdateGame ();
			
			if ( GetKeyboardPress ( DIK_RETURN ) )
			{
			    SetMode ( MODE_RESULT );
			}
	    	break;
	    
	    case MODE_RESULT:
	    	
			UpdateResult ();
			
			if ( GetKeyboardPress ( DIK_RETURN ) )
			{
			    SetMode ( MODE_TITLE );
			}
	    	break;
	}
}

/*==================*/
/*     描画関数     */
/*==================*/
void Draw ( void )
{
	g_pD3DDevice -> Clear ( 0 , 
		                    NULL , 
		                    D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER ,      
		                    D3DCOLOR_RGBA ( 255 , 255 , 255 , 0 ) ,   
		                    1.0f ,                                    
		                    0                                        
							);
	// 描画の開始
	if ( SUCCEEDED ( g_pD3DDevice -> BeginScene () ) )
	{	
		switch ( g_mode )
		{   
		    case MODE_TITLE:
		    	
				DrawTitle ();
		    
		    	break;
		    
			case MODE_GAME:
				
				DrawGame ();

				#ifdef _DEBUG
		        // FPS表示
		        DrawFPS ();
                #endif

		    	break;
		    
		    case MODE_RESULT:
		    	
				DrawResult ();

		    	break;
		}

		if ( g_mode != mode )
	    {
		    SetMode ( g_mode );
	    }

		// 描画終了
		g_pD3DDevice -> EndScene ();
	}

	g_pD3DDevice -> Present ( NULL , NULL , NULL , NULL );
}

LPDIRECT3DDEVICE9 GetDevice ( void )
{
	return g_pD3DDevice;
}

/*=====================*/
/*     FPS表示関数     */
/*=====================*/
#ifdef _DEBUG
void DrawFPS ( void )
{
	char aStr [256];
	RECT rect = { 0, 0 , SCREEN_WIDTH , SCREEN_HEIGHT };

	// FPS表示
	sprintf ( &aStr [0] , "FPS:%d\n" , g_nCountFPS );

	g_pFont -> DrawText ( NULL ,
		                  &aStr [0] , 
						  -1 , 
						  &rect ,
						  DT_LEFT ,
						  D3DCOLOR_RGBA ( 255 , 0 , 0 , 255 ) );
}
#endif // _DEBUG

/*================================*/
/*     画面モード状態取得関数     */
/*================================*/
MODE GetMode ( void )
{
	return g_mode;
}

/*==================================*/
/*     画面モード状態セット関数     */
/*==================================*/
void SetMode ( MODE mode )
{
	// 終了処理
	switch ( g_mode )
	{
	    case MODE_TITLE:
	    	UninitTitle ();
			break;

	    case MODE_GAME:
	    	UninitGame ();
	    	break;
	    
		case MODE_RESULT:
	    	UninitResult ();
	    	break;
	}

	// 初期化処理
	switch ( mode )
	{
	    case MODE_TITLE:
	    	InitTitle ();
	    	break;
	    
	    case MODE_GAME:
	    	InitGame ();
	    	break;
	    
	    case MODE_RESULT:
	    	InitResult ();
	    	break;
	}

	g_mode = mode;
}

//==============================   EOF   ==============================//
<object.cpp>

コード:

//==============================//
/*     インクルードファイル     */
//==============================//
#include "object.h"
#include "main.h"
#include "player.h"

//====================//
/*     マクロ定義     */
//====================//
#define OBJECT_TEXTURENAME "data/TEXTURE/Coin.jpg"

// ポリゴン表示位置X
#define OBJECT_POS_X ( 400 )

// ポリゴン表示位置Y
#define OBJECT_POS_Y ( 480 )

// ポリゴン幅
#define OBJECT_WIDTH ( 100 )

// ポリゴン高さ
#define OBJECT_HEIGHT ( 100 )

// プレイヤーのポリゴン数
#define NUM_OBJECT ( 2 )

//==========================//
/*     プロトタイプ宣言     */
//==========================//
HRESULT MakeVertexObject ( LPDIRECT3DDEVICE9 pDevice6 );          // 頂点作成関数

//========================//
/*     グローバル変数     */
//========================//
VERTEX_2D g_aVertex8 [ NUM_VERTEX ];
LPDIRECT3DTEXTURE9 g_pTextureObject = NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVtxBufferObject = NULL;
float g_PosPlayer;

//====================//
/*     初期化処理     */
//====================//
void InitObject ( void )
{
	LPDIRECT3DDEVICE9 pDevice = GetDevice();

	MakeVertexObject ( pDevice );

	// テクスチャの設定
	if ( FAILED ( D3DXCreateTextureFromFile ( pDevice , OBJECT_TEXTURENAME , &g_pTextureObject ) ) )
	{
		MessageBox ( NULL , "テクスチャファイル(オブジェクト)読み込み失敗" , "ERROR" , MB_OK );
	}
}

//==================//
/*     終了処理     */
//==================//
void UninitObject ( void )
{
	if ( g_pTextureObject != NULL )
	{
		// テクスチャポリゴンの解放
		g_pTextureObject -> Release ();
		g_pTextureObject = NULL;
	}
}

//==================//
/*     更新処理     */
//==================//
void UpdateObject ( void )
{
	VERTEX_2D* pVtx;

	g_pVtxBufferObject -> Lock( 
		                        0 , 
								0 , 
								( void** )&pVtx , 
								0 );

	g_pVtxBufferObject -> Unlock();
}

//==================//
/*     描画処理     */
//==================//
void DrawObject ( void )
{
	LPDIRECT3DDEVICE9 pDevice = GetDevice();
	
	pDevice -> SetStreamSource ( 0 , 
		                         g_pVtxBufferObject ,      
		                         0 ,                     
		                         sizeof ( VERTEX_2D )     
		                       );
							   
	// 頂点フォーマットの設定
	pDevice -> SetFVF ( FVF_VERTEX_2D );
	
	// テクスチャセット
	if ( FAILED ( pDevice -> SetTexture ( 0 , g_pTextureObject ) ) )
	{
		MessageBox ( NULL , "ポリゴンへのテクスチャ設定失敗" , "ERROR" , MB_OK );
	}

        // プレイヤーの座標取得
	g_PosPlayer = GetPlayer ();
	
	if ( g_PosPlayer < OBJECT_POS_X )
	{
	    // ポリゴン描画
	    pDevice -> DrawPrimitive ( D3DPT_TRIANGLESTRIP ,        
		                          0 ,                             
							      NUM_OBJECT                    
							     );
	}
}

//======================//
/*     頂点作成関数     */
//======================//
HRESULT MakeVertexObject ( LPDIRECT3DDEVICE9 pDevice6 )
{
	// 頂点バッファの生成
	pDevice6 -> CreateVertexBuffer ( sizeof ( VERTEX_2D ) * NUM_VERTEX ,     
		                            D3DUSAGE_WRITEONLY ,                   
									FVF_VERTEX_2D ,           
									D3DPOOL_MANAGED ,               
									&g_pVtxBufferObject ,         
									NULL
		                           );
	
	if ( FAILED ( pDevice6 -> CreateVertexBuffer ( sizeof ( VERTEX_2D ) * NUM_VERTEX , D3DUSAGE_WRITEONLY , FVF_VERTEX_2D , D3DPOOL_MANAGED , &g_pVtxBufferObject , NULL ) ) )
	{
		return E_FAIL;
	}
	
	VERTEX_2D* pVtx;

	g_pVtxBufferObject -> Lock ( 0 ,
		                          0 ,
								  ( void** )&pVtx ,  
								  0 );

	// 頂点座標の設定
	pVtx [ 0 ].pos = D3DXVECTOR3 ( OBJECT_POS_X , OBJECT_POS_Y , 0.0f );
	pVtx [ 1 ].pos = D3DXVECTOR3 ( OBJECT_POS_X + OBJECT_WIDTH , OBJECT_POS_Y , 0.0f );
	pVtx [ 2 ].pos = D3DXVECTOR3 ( OBJECT_POS_X , OBJECT_POS_Y + OBJECT_HEIGHT , 0.0f );
	pVtx [ 3 ].pos = D3DXVECTOR3 ( OBJECT_POS_X + OBJECT_WIDTH , OBJECT_POS_Y + OBJECT_HEIGHT , 0.0f );
	
	pVtx [ 0 ].rhw = 1.0f;
	pVtx [ 1 ].rhw = 1.0f;
	pVtx [ 2 ].rhw = 1.0f;
	pVtx [ 3 ].rhw = 1.0f;

	// 頂点色の設定
	pVtx [ 0 ].color = D3DCOLOR_RGBA ( 255 , 255 , 255 , 255 );
	pVtx [ 1 ].color = D3DCOLOR_RGBA ( 255 , 255 , 255 , 255 );
	pVtx [ 2 ].color = D3DCOLOR_RGBA ( 255 , 255 , 255 , 255 );
	pVtx [ 3 ].color = D3DCOLOR_RGBA ( 255 , 255 , 255 , 255 );

	// テクスチャ座標の設定
	pVtx [ 0 ].tex = D3DXVECTOR2 ( 0.0f , 0.0f );
	pVtx [ 1 ].tex = D3DXVECTOR2 ( 1.0f , 0.0f );
	pVtx [ 2 ].tex = D3DXVECTOR2 ( 0.0f , 1.0f );
	pVtx [ 3 ].tex = D3DXVECTOR2 ( 1.0f , 1.0f );
	
	g_pVtxBufferObject -> Unlock();
	
	return S_OK;
}

//==============================   EOF   ==============================//

sadora3
記事: 175
登録日時: 11年前

Re: 処理が重い

#2

投稿記事 by sadora3 » 7年前

こんにちは。PG歴が浅く、間違ったことを言ってしまっていたら申し訳ありませんが、回答させて下さい。

>>ゲーム画面において、プレイヤー、オブジェクトなど色々な処理が多くなり、だんだんと処理が重くなってきました。
でしたら、問題は「UpdateGame ();」か「DrawGame ();」辺りが怪しいのではないでしょうか。
object.cppの処理ですが、私には問題ないように見えます。

それと、気になったことがございます。
main.cppの19行目に
MODE mode;
このような記述があり、同じくmain.cppの435行目に
void SetMode ( MODE mode )
とありますが、これはあまり良くないと思います。
理由は以下のページの通りでございます。
http://www.kishiro.com/programming/c/va ... flict.html

今言えることは上記のことくらいです。
これ以上のことは他のファイルも見せて頂かないと分かりません。
出来ればプロジェクトを丸々上げてもらうのが一番です。

閉鎖

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