6

我正在为我的 F# 项目创建一个场景图,例如:

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

等等等等

每个项目都需要保存一组游戏对象来代表它的孩子。

例如,enemy1 的列表包含一只猫和一顶帽子,而猫列表包含跳蚤和一个毛皮球

所以我打算让它们都继承自一个类,该类包含一个描述该对象子对象的集合。

现在我的问题是:我 是否应该将子对象向下转换为 GameObject 并将它们存储在“GameObject”基类的列表中,或者创建一个有区别的联合,例如

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

并将对象存储为“SceneObjects”列表,以避免任何问题/开销与向上转换它们等。以及允许我描述对象未渲染和/或未用于碰撞检测的特殊情况,例如:声音发射器、陷阱触发器等。

区分联合+继承组合是我最初的想法;不过,由于我是 FP 的新手,我认为向专业人士寻求最好的、实用的方法来解决这个问题是明智的。

谢谢,

京东

4

2 回答 2

11

您可以递归地使用有区别的联合。

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

并像这样使用它

let root = [Character("Bob", [Item("Torch", []); ...]); ...]
于 2010-08-29T11:23:11.403 回答
9

Dario 建议的替代方法是为游戏中的实际对象(例如物品和角色)声明一个单独的类型,并将其包装在另一个添加子对象列表的对象中。这看起来像这样:

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,因此您不需要包含所有情况(例如Itemand Character)。

于 2010-08-29T15:39:20.180 回答