GameDevの最近のブログ記事
こんな構造体より、
/**
* ジョイスティックの入力状態
*/
struct ST_JOY_STATE
{
unsigned char ucJoyUp; ///< 上キー
unsigned char ucJoyDown; ///< 下キー
unsigned char ucJoyLeft; ///< 左キー
unsigned char ucJoyRight; ///< 右キー
unsigned char aryucJoyBtn[6]; ///< 数字キー
};
ST_JOY_STATE _stJoyState; ///< ジョイスティックの入力状態
こんな列挙型と配列使ったほうが、
/**
* ジョイスティック用キーコード
*/
enum E_JOY_CODE
{
JOY_UP, ///< ボタン上
JOY_DOWN, ///< ボタン下
JOY_LEFT, ///< ボタン左
JOY_RIGHT, ///< ボタン右
JOY_BTN1, ///< ボタン1
JOY_BTN2, ///< ボタン2
JOY_BTN3, ///< ボタン3
JOY_BTN4, ///< ボタン4
JOY_BTN5, ///< ボタン5
JOY_BTN6, ///< ボタン6
JOY_CODE_END, ///< 最終メンバ(メンバ数取得用)
};
unsigned char _aryucJoyState[JOY_CODE_END]; ///< ジョイスティックの入力状態
管理しやすいような気がした。
上のE_JOY_CODE列挙型があれば、ボタンの情報を関連付けやすいし、そんで構造体より配列の方がコードがシンプルになる。
※「///<」はDoxygen用のコメント
ゲーム処理クラスがDirectX処理クラスを直接使ってるけど、ゲーム処理も、描画エンジンとかに依存せずに独立したプログラムにしたい。ということで、一つクラスをラップすることにした。[]はクラス。
[DirectX Graphics処理]←――[描画] ←┐
[DirectX Audio処理] ←――[サウンド再生] ←+―[ゲーム処理]
[DirectInput処理] ←┬―[入力制御] ←┘
[Keyboard入力] ←┘
ゲーム処理クラスはDirectXなんて知らない。だから、描画クラスだけいじれば、ゲームプログラムを一切変更せずに描画エンジンが切り替えられる。
共通処理クラスCCommonっていうクラスを作ってて、その中でエラーログ出力関数みたいなどこでも使うような関数を用意して、いろんなとこで使ってたんだけど、DirectX処理クラスでこの共通処理クラスを使うのは、ちょっと変な気がしてきた。
というのも、DirectX処理クラスは、完全にゲームとは別に独立したものっていう考えで、本来はDLLとして存在するべきものにしてある(DLLにすると逆にめんどいことがあるんで、今は敢えてDLLにしてない)。だから、今作ってるゲームに限らず、このDirectX処理クラスは汎用的に使えるようにしてある。
本来独立して存在するものが、ゲーム処理クラスと同じ共通処理クラスを使用してるのは変。だから、DirectX処理クラスは、共通処理クラスを使わない方がいいな。
そもそも共通処理クラスっていうのが抽象的すぎた。ゲーム処理用の共通クラスとでもしておくか。
共通処理クラスに、デバッグトレースの関数を作った。
/**
* デバッグトレース
*
* @param[in] a_pszFormat 書式
*/
void CCommon::Trace(const char* a_pszFormat, ...)
{
#ifdef _DEBUG
va_list pcParam; // 引数リスト
char szTrace[512]; // 出力文字列// 可変引数の取得開始
va_start(pcParam, a_pszFormat);
// 出力文字列の作成
_vsnprintf(szTrace, sizeof(szTrace),
a_pszFormat, pcParam);
// 可変引数の取得終了
va_end(pcParam);// デバッグトレース
OutputDebugString(szTrace);
#endif
}
この関数はエラー発生時とかに使う。
// エラー発生時
if (! bRet)
{
CCommon::Trace("Errror: %s %s\n",
__FUNCTION__, pszErrorMessage);
}
上のフォーマットだと、例えば、
「Errror: CDI::Init DirectInput8オブジェクトの作成に失敗」
って文字列が出力されるんだけど、いろんなとこでこのトレースは使われるわけなんで、出力フォーマットは必ず統一されるようにした方がいい。
それで、直接トレース関数を使うわけじゃなくて、エラー発生用に使うトレース関数を別に作っといた。
/**
* エラー用デバッグトレース
*
* @param[in] a_pszFunction 関数名
* @param[in] a_pszError エラーメッセージ
*/
void CCommon::TraceOfError(char* a_pszFunction, char* a_pszError)
{
CCommon::Trace("Errror: %s %s\n",
__FUNCTION__, pszErrorMessage);
}
とりあえず、エラー発生した関数名とエラーメッセージだけ出力すればいいかな。ということで、エラー発生時に書く処理はこれ↓。
// エラー発生時
if (! bRet)
{
CCommon::TraceOfError(__FUNCTION__, pszErrorMessage);
}
ゲームプログラムで使うデバッグトレース、ログ出力、エラーメッセージ表示について。それぞれどういうタイミングで使用するべきか、どういう位置づけで使用するべきか、決めてみた。
[デバッグトレース]
- ファイル読み込みや、シーンの切り替えなど、重要処理や全体の処理フローがわかるようにトレースする
- エラー発生時に、そのときの関数の名前や行数などをトレースする
[ログ出力]
- エラー発生時に、そのときの関数の名前や行数などを、エラーログとして出力する
[エラーメッセージ表示]
- エラー発生時に、そのことがプレイヤーにわかるよう、メッセージダイアログにて、エラーメッセージを出力する
- 基本的には、ゲーム起動時に出力する
例)「DirectXの初期化に失敗しました」
「画像ファイルの読み込みに失敗しました」
重要度でいくと、
エラーメッセージ表示 > ログ出力 > デバッグトレース
っていう順番かな。






