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 e开发者_StackOverflow社区nemy1'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
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", []); ...]); ...]
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
).
精彩评论