Дискриминационные союзы и наследство - PullRequest
3 голосов
/ 29 августа 2010

Я хочу создать граф сцены для моего проекта F #, например:

root
->player_bob
-->torch
->enemy_1
-->extravagant_hat
-->enemies_cat_jess 
--->fleas
--->fur_ball
->loot

и т. Д. И т. П.

Каждый элемент должен содержать коллекцию игровых объектов, чтобыпредставьте, что это дети.

например, список врага1 содержит кошку и шляпу, а список кошек содержит блох и меховой шарик

Поэтому я планирую сделать так, чтобы все они наследовали от класса, содержащего коллекциюэто описывает объекты потомки.

Теперь на мой вопрос: Должен ли я понижать дочерние объекты до GameObject и сохранять их в списке базового класса "GameObject" ИЛИ создавать различающее объединениенапример,

type SceneObject = 
        |Character of Character //e.g player, enemy, cat
        |Item of Item //e.g hat, torch, furball

И сохранять объекты в виде списка «SceneObjects», чтобы избежать каких-либо проблем / накладных расходов при их приведении и т. д., а также позволить мне описать особые случаи, когда объект не отображаетсяи / или не используется при обнаружении столкновений, например: звуковые излучатели, триггеры-ловушки и т. д.

Дискриминационное объединение "объединение + наследование" - моя первоначальная мысль;хотя, поскольку я новичок в FP, я подумал, что стоит спросить у профессионалов лучший, функциональный способ решения этой проблемы.

Спасибо,

JD

Ответы [ 2 ]

9 голосов
/ 29 августа 2010

Вы можете использовать выделенный союз рекурсивно .

type SceneObject = 
    | Character of <characterData> * (SceneObject list) 
    | Item      of <itemData>      * (SceneObject list)

И используйте это так

let root = [Character("Bob", [Item("Torch", []); ...]); ...]
7 голосов
/ 29 августа 2010

Альтернативой тому, что предлагает Дарио, является объявление отдельного типа для реальных объектов в игре (например, предметов и персонажей) и перенос их в другой объект, который добавляет список дочерних объектов. Это будет выглядеть так:

type SceneObject =
  | Character of <characterData>
  | Item of <itemData>

type ObjectWithChildren = 
  { Object : SceneObject
    Children : ObjectWithChildren list }

Оба варианта имеют правильный функциональный дизайн, но я бы предпочел эту версию, потому что она облегчает определенные виды обработки. Например, если вы хотите пройти все объекты в дереве игры, вы можете написать что-то вроде:

let rec traverse tree = 
  // Do something with tree.Object
  for child in tree.Children do traverse child

В этой версии вам вообще не нужно сопоставлять шаблоны с SceneObject, поэтому вам не нужно включать все случаи (например, Item и Character).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...