2010-08-29 59 views
3

我期待创造一个场景图我的F#项目的财产以后这样的:识别联合和继承

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

等等,等等。

每个项目需要保存一个游戏对象的集合来表示它的孩子。

e.g enemy1的列表中包含一只猫和一顶帽子和猫列表包含跳蚤和毛球

所以我打算让他们都从包含描述对象的子对象的集合类继承。

现在我的问题: 我应该向下转换子对象游戏对象的,并把它们存储在“游戏对象”基类 的清单,或建立一个识别工会如

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

和存储对象作为“场景对象”的列表以避免任何问题/开销的上演,等等。以及允许我描述在碰撞检测中不呈现和/或不使用对象的特殊情况,例如:声音发射器,陷阱触发器等。

歧视的工会+继承组合是我最初的想法;不过,因为我是FP新手,所以我认为向专业人士提供最好的,实用的解决方法是明智的。

感谢,

JD

回答

9

可以使用识别联合递归

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

而且使用这样的

let root = [Character("Bob", [Item("Torch", []); ...]); ...] 
+1

太棒了!这消除了对继承的需求:¬) 谢谢Dario,我的一半学习FP的问题正在把我的脑袋从OO土地中拉出来。 – jdoig 2010-08-29 11:29:46

7

什么达里奥建议另一种方法是申报在游戏中的实际对象单独的类型(如项目和字符)和另一对象把它包它添加了一个子对象列表。这应该是这样的:

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模式匹配好,所以你不需要包括所有的案例(如ItemCharacter)。

+0

有趣。这就是我对Character类及其状态机进行建模的方式。 保存所有原始数据(位置,健康等)的字符记录(CharacterRecord)。 一个邮箱处理器作为状态机(CharacterStateMachine)。 然后将它们包装在“Character”记录中,该记录包含{state:CharacterStateMachine;数据:CharacterRecord}。 然后使用的成员,使一些用户友好的getter和setter ... 所以这种解决方案很适合我目前的模型。 我将不得不给这两个尝试, 非常感谢。 – jdoig 2010-08-29 21:53:16