プログラミングの難しいところ
ゲームをプレイしてると、表面上は簡単そうに見えることでも、実際に開発者の立場で見ると意外と難しい部分がある。今回はその一つをわかりやすく説明してみる。
HPのクールダウンシステム
簡単に言うと、このシステムはオブジェクト(例えばキャラクター)がダメージを受けた後、次にダメージを受けるまでの時間を設定するものだ。例えば、俺は0.1秒という時間を設定した。つまりパンチを一度当てたら、次のパンチが当たるまでに0.1秒待たなければならないという仕組みだ。
でも、このシステムの何が問題なのか
このシステムを作った時、俺は1対1のバトルを想定していた。しかし現実的には2対1とか、もっと複雑な状況もあるかもしれない。 その場合、このHPクラスは一応機能するけど、例えば複数のキャラが同時に一人のキャラを攻撃した場合、片方の攻撃だけが無効になってしまう。
めちゃくちゃもどかしい動きである。
開発者としての考え方
この例から何が言えるかというと、ジェネリック(汎用的)なクラスを作る時には、あらゆる状況に対応できるように設計する必要がある。
解決策
この問題には2つの解決策が考えられる:
-
HPクラスを拡張する方法:
攻撃してきたオブジェクトとその時の時間を保存する辞書フィールドを作る。これにより、それぞれの攻撃者に対してクールダウンを個別に管理できるようにする。 -
アタッククラスを拡張する方法:
HPクラスからクールダウンシステムを削除して、アタッククラスにその機能を移す。この場合、攻撃が確認されたら、次の当たり判定関数が呼び出されるまで、当たり判定を無効にする。
実際の実装と試行錯誤
さて、上で紹介した解決策のうち、どちらを選ぶべきかはプロジェクトの要件や開発者の好みによる。俺の経験を語ると、最初はHPクラスを拡張する方法を選んだ。攻撃者とそのタイミングを管理する辞書を追加して、複数の攻撃を受けても個別にクールダウンを処理できるようにした。
この実装は、シンプルな仕組みながらも非常に効果的だった。だが、コードが複雑になりがちだという問題もあった。攻撃が増えるにつれて、辞書の管理や時間の計算が意外と面倒だった。
そこで、次にアタッククラスを拡張する方法を試してみた。このアプローチでは、HPクラスの処理をシンプルに保ちつつ(クールダウンシステムを入れない)、攻撃の当たり判定をアタッククラスでコントロールすることにした。この方法のメリットは、攻撃に関する処理が攻撃側に集中するため、HPクラスが軽くなり、他のシステムと干渉しにくくなる点だ。
アタッククラスの拡張では、攻撃が成功した後、一定時間当たり判定を無効にするフラグを設定し、次の攻撃が当たるまでの時間を待つようにした。これにより、同時攻撃があってもフェアに処理され、どちらの攻撃も正しく判定されるようになった。
最適な選択は状況次第
どちらの方法も一長一短だ。プロジェクトの規模や複雑さ、あるいは他のシステムとの連携を考慮して、どの方法が最適かを選ぶ必要がある。例えば、シンプルなゲームであれば、HPクラスを拡張して対応するのが手っ取り早いかもしれない。しかし、複数の敵が同時に攻撃してくるようなシチュエーションが多いゲームでは、アタッククラスを拡張する方が理にかなっているだろう。適材適所である。
まとめ:プログラミングは常にトレードオフ
このように、プログラミングは常にトレードオフ(妥協点)の連続だ。どの方法を選んでも、それぞれのメリットとデメリットを理解し、最適な解決策を選ぶのが開発者の腕の見せ所だ。実装がうまくいけば、それは大きな達成感につながる。逆に、失敗から学ぶことも多い。折り合いのセンスというのも大事なものだ。
だからこそ、プログラミングは面白い。どんな小さなシステムでも、深く考え抜いて最適な方法を見つける過程がある。それが、ゲーム制作の醍醐味でもある。