The SceneGraph that got developed in the book was oriented around making more or less fix joints between multiple entities. It sounds like you guys are doing something different, thus such a fixed approach is not very wise. So I guess you need to think of a different way to approach the scene graph.
I have only ever worked with SceneGraphs as they were implemented in to book. Besides the "tree" implementation, what are other ways they can be done? Do you know of any literature that discusses this type of thing? I've searched all over for 2D game development books, but all of the ones I've found don't really discuss what I'm looking for.
While the command system of the book is quite nice, it can also be a bit limiting. You could think about implementing a message bus instead. That way you can just send messages and only the one interested in the message and react to it. Tank wrote a nice article about it.
I've never heard of this design pattern, thanks for sharing! In the context of the SFML book, does this mean that every entity needs its own ID? If this is the case, then I feel like I run into the same problems that I would trying to get the category system to work with my project. Does every entity created get the next available ID? After an entity is destroyed, does the next new entity get the newly-freed ID?
However, our first main problem was that each one of our enemies needs different changes in velocity, so the category system wouldn't work for us, unless we somehow gave assigned an enemy a unique category.
But the actions didn't really differ logically, there was only a different value for the velocity? Wouldn't it be possible to use one category, but in the command, you differentiate cases depending on the enemy (ideally not explicitly, but through some kind of map or a property in each enemy)?
As it was implemented in the book, we need to pass the arguments to our command's function at the time we create the command, right? Like so:
Command moveLeft;
moveLeft.category = Category::PlayerAircraft;
moveLeft.action = derivedAction<Aircraft>(AircraftMover(-playerSpeed, 0.f));Obviously, steering behaviors are dependent on current position, surrounding entities and obstacles, and whatnot. Ideally, I would have loved to use commands like so:
Command wander;
wander.category = Category::Wandering;
wander.action = derivedAction<Enemy>(Wander());... and then have the wander function take care of everything. But like I said, the command wouldn't have access to the data it needs to.
My slap-dash fix to this was editing the command object to, instead of a category, take a SceneNode& as an argument.
I don't think that's meaningful, SceneNode& is the type on which the command executed -- you don't know it beforehand. However, you can use another type than the Category::Type enum to identify entities. If you don't need to combine different flags, just use int. Otherwise, something like std::bitset might be a possibility, or a dynamic list of receivers.
My thought process was that, if the command had access to the reference to the SceneNode it was executing the action on, then I would be able to use commands like I wanted to above. Clearly, this defeats the purpose of the command system in a way, and I don't like what we did at all. If I extracted the wander function somehow and then set the command action like so:
sf::Vector2f newVel = wander(SceneNode&);
wanderCommand.action = derivedAction<Enemy>(EnemyMover(newVel));then I would need a category for each enemy, and the categories would have to update and change as new enemies were spawned, similar to the ID questions I asked above. I didn't know how to deal with that, and it didn't sound optimal, but perhaps in retrospect, that would have been better than needing every command to know the SceneNode it is executing on beforehand.
But as eXpl0it3r mentioned, don't try to force the design of our book to any application. As emphasized in the book, there are always trade-offs. It doesn't mean you have to throw away everything; for example, scene graph and command system are orthogonal concepts and can be used independently. It's also possible to have additional data structures to reference entities directly, or to create groups/hierarchies which are not related to rendering (e.g. for collision or flocking behavior).
There are also a lot of threads about game design on this forum, don't hesitate to search. For example, there was recently a discussion about integrating more sophisticated collision detection and response into the design of the SFML book.
Thanks for the link, I'll definitely be frequenting these forums now. I know that I shouldn't be forcing any design onto something it isn't optimal for. However, at this point I feel like I'm lacking for literature discussing these things, so I don't know the concepts that would help me design my own classes. I learn well through example, normally through tinkering with working code, and I figured that would be enough to help me in this project but it didn't
. In my head, I imagine some
CurGameState struct that would have all the data about everything on the screen, which would get updated per tic and all of my controller classes can access it to do their functions, but I don't know how I would go about doing that. These are the things that make me wish I had more books.
Thanks both of you for taking the time to answer me.