テラリウム徹底攻略ガイド(改訂版) オブジェクト・モデルのクラス構造 デジタルアドバンテージ2003/05/10 |
|
|
オブジェクト・モデルのクラス構造
オブジェクト・モデルのクラスの項には、16のクラスが定義されている。これらのクラスの親子関係を整理して列挙すると次のようになる。
Organism | 生物クラス |
Animal | 動物クラス |
Plant | 植物クラス |
OrganismState | 生物の状態を表すクラス |
AnimalState | 動物の状態を表すクラス |
PlantState | 植物の状態を表すクラス |
Action | アクション・クラス |
AttackAction | 攻撃アクション・クラス |
DefendAction | 防御アクション・クラス |
EatAction | 摂食アクション・クラス |
MoveToAction | 移動アクション・クラス |
ReproduceAction | 生殖アクション・クラス |
AntennaState | アンテナの状態を表すクラス |
EngineSettings | ゲーム設定クラス |
MovementVector | 移動ベクトル・クラス |
Vector | ベクトルの演算用クラス |
テラリウムで使用する16のクラス |
動物(肉食動物あるいは草食動物)をプログラミングする際に重要となるクラスは、Animalクラスと、動物の状態を表すAnimalStateクラスだ。草食動物にとっては、植物の状態を表すPlantStateクラスも重要になる。
■Animalクラス
テラリウムで動物プログラムを作成するには、Animalクラスのサブクラス(子クラス)としてクラスを作成する。Animalクラスは、上記の表からも分かるように、Organismクラス(Organismは「生物」の意味)のサブクラスであるため、自分の動物プログラムでは、OrganismクラスやAnimalクラスで定義されているメソッドやプロパティの機能を使用することができる。Organismクラスは、動物と植物に共通する特徴(機能)を実装したクラスだ。
例えば、動物が可能な5つの基本行動(生殖(出産)、攻撃、防御、摂食、移動)には、それぞれAnimalクラス(BeginReproductionメソッドはOrganismクラス)の次のメソッドを使用する。
- 生殖 : BeginReproductionメソッド
- 攻撃 : BeginAttackingメソッド
- 防御 : BeginDefendingメソッド
- 摂食 : BeginEatingメソッド
- 移動 : BeginMovingメソッド
■AnimalStateクラス
一方、AnimalStateクラスは、ある瞬間の(正確には次の項で説明する各ターンにおける)動物の状態を表すクラスである。「Organismクラス−Animalクラス」の関係と同様に、このクラスはOrganismStateクラスのサブクラスとなっている。
自分自身の現在の状態を示すAnimalStateオブジェクトは、AnimalクラスのStateプロパティから取得することができる。これを利用すると、例えば現在の自分のエネルギー量は、
State.StoredEnergy
として取得でき、また自分が受けたダメージ量は、
State.Damage
として取得することができる。ここで、StoredEnergyプロパティはOrganismStateクラスのプロパティだが(動物も植物もいくつかの量のエネルギーを持っている)、スーパークラス(親クラス)のメンバにはキャストなしで参照することができる。ちなみに、DamageプロパティはAnimalStateクラス特有のプロパティだ(植物はダメージを受けないが、代わりに食料値(OrganismStateクラスのFoodChunksプロパティ)が下がっていく。
同様に、自分以外の生物についての状態は、その生物のOrganismStateオブジェクト(あるいはそのサブクラスのオブジェクト)を得ることによって調べることができる。自分の周りにいる生物を取得するAnimalクラスのScanメソッドでは、AnimalStateオブジェクトの配列を得ることができる。
OrganismStateオブジェクトやAnimalStateオブジェクトなどの状態オブジェクトは、自分以外の生物を指し示す場合にも使用される。例えば上記のBeginAttackingメソッドでは、攻撃する相手のAnimalStateオブジェクトをパラメータとして指定する。これらの状態オブジェクトはそのときどき(各ターンごと)に生成されるオブジェクトであるが、その中にある生物を一意に識別可能なIDプロパティにより生物が識別されているようだ。逆にいうと、一度取得した状態オブジェクトの内容が更新されることはない。ただし、状態オブジェクトはAnimalクラスのLookForメソッドなどにより更新することができる。
イベントとターン
テラリウムでは、すべての生物は1つの「ターン」において1回だけ攻撃、防御、移動、摂食を行うことができる。そして、ターンは0.5秒間隔で次々とやってくる。
例えば、あるターンで肉食動物が草食動物に対して攻撃を仕掛けるとしよう。すでに述べたように、これにはAnimalクラスのBeginAttackingメソッドを使用する。メソッド名の頭が“Begin”なっていることからも分かるように、この時点で攻撃処理が即座に行われるわけではなく、これによって攻撃開始が指定される。つまりこのターンでは、攻撃を行うということを「セット」するわけだ。実際には、このメソッドが呼び出されることによりAttackActionオブジェクトが生成される。一方、草食動物が同じターンで、BeginDefendingメソッドにより防御していたとすると、攻撃と同様にDefendActionオブジェクトが生成される。そしてこのターンが終了後、テラリウムのシステム側で両者の戦闘が処理され、もし攻撃が防御に勝っていれば、次のターンでは草食動物のダメージ量が増えていることになる。
■AttackCompleted、DefendCompleted、EatCompletedイベント
テラリウムで発生するイベントは、このターンと深く関連している。次に列挙したイベントは、攻撃、防御、摂食を“Begin〜”メソッドで行った次のターンで発生する。
- AttackCompletedイベント
- DefendCompletedイベント
- EatCompletedイベント
これら3つの行動は、それぞれイベントが発生した時点ですでに完了している。しかし攻撃対象の生物が1回の攻撃で死ぬとは限らないし、1回の“噛み付き”でエサを完食するとは限らない。このような場合は、イベント・ハンドラに渡されたイベント引数をチェックして行動がどのような結果で完了したかをチェックしたり、あるいは対象としている生物の状態を再取得したりして、必要とあらば攻撃や摂食を続行する必要がある。
■MoveCompletedイベント
MoveCompletedイベントは、上記の3つのイベントと少し異なり、移動が完了するまで発生しない。つまり1度BeginMovingメソッドにより移動先を指定しておけば、移動が完了するまで、複数のターンにわたって生物は移動を続けることになる。このためすでにセットした移動を取り消すためのStopMovingメソッドも用意されている。また、BeginMovingメソッドには移動先を示すMovementVectorオブジェクトをパラメータとして指定するが、移動中のいずれかのターンで、再度BeginMovingメソッドを呼び出せば、移動先を変更することができる。なお同じターン内で複数のBeginMovingメソッドを呼び出した場合には、最後の呼び出しが有効となる。これはほかの“Begin〜”メソッドでも同じだ。
■Attackedイベント
ほかの生物から攻撃を受けたときに発生するAttackedイベントは、1つのターンで複数回発生する点で、ほかのイベントとは異なっている。ただし攻撃も防御も、1回につき1つの生物に対してしか行うことができないため、自分を攻撃している生物のうちどの生物を相手にするのか、あるいはどれも相手にせずにとっとと逃げるのかは戦略次第だ。AttackedEventArgsのAttackerプロパティからは、攻撃をしている生物のAnimalStateオブジェクトを取得することができる。
■LoadイベントとIdleイベント
プログラムで何の動作も起こさなくても、毎ターンごとに発生するイベントが2つある。ターンの最初に発生するLoadイベントと、ターンの最後に発生するIdleイベントだ。
Loadイベントは、すべてのイベントに先立って発生するので、このタイミングでは、ほかのイベントで共通して利用するような変数の設定や初期化などをあらかじめ行っておくことができる。
一方、Idleイベントは、ほかのすべてのイベントが発生したあとに発生する。生物プログラムによっては、このイベントのみを処理し、そこで自分と、自分の周りの生物の状態を取得して、すべての行動を決定しているものもあるようだ。
このLoadとIdle以外のイベントについては、1つのターン内での発生順序は明記されていないが、プログラムを書いて少し調べてみたところ、ここまでに説明したイベントは、それぞれの次のような順序で発生するようである。
- Loadイベント
- MoveCompletedイベント
- AttackCompletedイベント
- EatCompletedイベント
- DefendCompletedイベント
- Attackedイベント(複数発生する可能性あり)
- Idleイベント
“Begin〜”メソッドによりセットされたそれぞれの行動は、ターン終了後にシステム側で一括して処理されるようなので、上記2〜6までのイベントがどのような順番で発生したとしてもさほど問題にはならない。ただし前述したとおり、“Begin〜”メソッドでセットした行動は最後のものだけが有効となる。このため、例えばMoveCompletedイベントの発生時にBeginAttackingメソッドを呼び出してセットした攻撃を、それ以降の別のイベント発生時に上書きしないようにしなければならない。すでに行動がセットされているかどうかは、IsAttackingプロパティなどの、“Is〜”プロパティにより調べることができる。
■ほかのイベント
ここまでに挙げたイベント以外にも、生物が生まれた時点で1回だけ発生するBornイベント、生物がテレポートされたときに発生するTeleportedイベント、自分の子を産んだ直後に発生するReproduceCompletedイベントがある。出産という行動は、BeginReproductionメソッドにより開始されるが、これが完了してReproduceCompletedイベントが発生するまでには、最短でEngineSettings.TicksToIncubate(現在の設定では10)のターンが必要となる(途中エネルギーが少なくなってくると、この期間は長くなる)。
最後にテラリウムでの時間の単位であるティック(Tick)について触れておこう。ティックは1ターンで1ずつ増えていく。例えば、今述べたように出産を開始してから10ターン後に子供が生まれるが、これは出産に10ティックかかるというのと同義だ。
また、例えば生物が生きていられるティック数(すなわち生物の寿命)は、種によってあらかじめ決まっていて、プログラムからは“Species.LifeSpan”で取得することができる。また、“State.TickAge”は生物が誕生してからのティック数(すなわち現在の年齢)を表している。
INDEX | ||
テラリウム徹底攻略ガイド(改訂版) | ||
第3回 オブジェクト・モデルと生物テンプレート | ||
テラリウムのオブジェクト・モデル概要 | ||
オブジェクト・モデルのクラス構造 | ||
生物テンプレートの詳細(1) | ||
生物テンプレートの詳細(2) | ||
「テラリウム徹底攻略ガイド(改訂版)」 |
- 第2回 簡潔なコーディングのために (2017/7/26)
ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている - 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう - 第1回 明瞭なコーディングのために (2017/7/19)
C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える - Presentation Translator (2017/7/18)
Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
|
|