受歧视的工会和继承

发布于 2024-09-16 06:55:48 字数 768 浏览 7 评论 0原文

我正在寻找为我的 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

I'm looking to create a scene-graph for my F# project somthing like:

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

etc,etc.

Each item needs to hold a collection of game objects to represent it's children.

e.g enemy1's list contains a cat and a hat and the cats list contains fleas and a fur ball

So I plan to make them all inherit from a class that contains a collection that describes that objects children.

Now to my question:
Should I down-cast child objects to GameObject's and store them in a list of the "GameObject" base class
OR create a discriminating union e.g

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

And store objects as a list of "SceneObjects" to avoid any problems/overheads with up-casting them, etc. As well as allowing me to describe special cases where the object isn't rendered and/or not used in collision detection e.g: sound emitters, trap triggers, etc.

The discriminated union + inheritance combo is my initial thought; though, as I'm new to FP, I thought it wise to ask the pro's for the best, functional, way of approaching this.

Thanks,

JD

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ぶ宁プ宁ぶ 2024-09-23 06:55:48

您可以递归地使用可区分联合。

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

像这样使用它

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

You can use the discriminated union recursively.

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

And use it like this

let root = [Character("Bob", [Item("Torch", []); ...]); ...]
病毒体 2024-09-23 06:55:48

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 进行模式匹配,所以你不需要需要包含所有情况(例如 ItemCharacter)。

An alternative to what Dario suggest is to declare a separate type for actual objects in the game (such as items and characters) and wrap it in another object that adds a list of child objects. This would look like this:

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

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

Both of the options are correct functional design, but I would prefer this version, because it makes certain kinds of processing easier. For example, if you wanted to traverse all objects in the game tree, you can write something like:

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

In this version, you don't need to pattern match on SceneObject at all, so you don't need to include all the cases (such as Item and Character).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文