グローバル変数は外部参照すべきか?
突然ですが、グローバル変数をやもえず外部参照する場合、
以下のような方法が考えられると思います。
// ヘッダファイルの記述(key.h)
extern ST_KEY Key;// ソースファイルの記述(key.c)
2008-07-31 - GBA homebrew日記
ST_KEY Key;
これは慣例らしく、色々なところに普及されているっぽいです。
慣習化されているのは確かなのですが、
今回の件で言えばキーの構造体を直に見るのはあまりいただけないかなぁ、とか。
コードの可読性、即ち「Keyがグローバルであると気がつくか?」とはちと外れますが、
Keyの場合の問題点いくつか。
- キーカスタマイズの問題
- ゲームだとたまにオプションで「操作タイプA」「操作タイプB」なんてのが選べますが、こういうのに対応できない。(構造体操作時にいれるデータをボタン名称ではなく機能名称単位にすれば良いんだけれど、管理しにくい)
- ゲームだとよくあることに開発中にキーが変更になることがよくありますが、こういうのに対応しにくい。
- 可読性の問題
- ゲームだと「Trigger(今押された)」「Press(押されている)」「Release(離された)」「Repeat(リピート入力)」みたいなキーの状態を扱いますが、そういうのが分かりづらい。構造体のメンバ名で表すこともできますが。
- 複数のコントローラの問題
- GBAとかDSだとコントローラは一つですが、複数のパッドがあった場合、結局面倒なことに。Key[PORT1].btnとか。
- リプレイ機能やデモ再生の問題
- アクションゲームとかプレイをリプレイでみせたり、デモ再生するさいにキー入力エミュレーションを使うことが多いでしょうが、構造体だとちょっと面倒ですよね。
で、やっぱりグローバル関数で、
// キャンセルボタンが放されたら(ポート指定版? if (IsPadRelease(PORT1, PAD_CANCEL)) { ... } // 特殊攻撃ボタンが押されたら if (IsPadTrigger(PAD_SPECIAL_ATTACK)) { ... } // 補助ボタンを押しつつ、攻撃ボタンが押されたら if (IsPadButton(PAD_ASSIST)) { if (IsPadTrigger(PAD_ATTACK)) { ... } }
とかでしょうかねえ。
PAD_SPECIAL_ATTACKとかにするのは、
同時押しなどを|で表記するより別定義の方が良いので。
何をしようとしているのかが明白になって可読性もあがりますし、
何よりKeyとはなんぞや? なんてことを思う必要はありません。
キーカスタマイズをする場合は、|定義ではなく、別enumとかにしておいて、
関数内で変換をかませばいいです。
PAD_SPECIAL_ATTACK -> PAD_A|PAD_L
のときもあれば、
PAD_SPECIAL_ATTACK -> PAD_B
のこともあるでしょう。
もちろんデバッグで簡易に扱いたいことも多いので
if (GetPadButton() & PAD_A) {
...
}
なんてこともありますけれど。
あとは、数フレーム前の入力が欲しいこともあるので、
Record(履歴)化したりとか?
(格闘ゲームなんかのキー入力はそういう必要がありますね、先行入力があるゲームもそうかな。
と、構造体を直接みるのは問題が色々と多いので、
関数化推進派です。
面倒でも煩雑になるよりは関数にしちゃうのがLoveです。
でも、簡単なゲームだと構造体参照で済むこともありますけどね。(^_^;
元々がCの話題のようなので関数にしてますが、
C++だったらクラスにしてポートを隠蔽したりするかも。