Where does game play come in?

Started by
9 comments, last by GameDev.net 11 years ago

So over the past couple days I have learned a lot about design patterns and game architecture but now another mountain has appeared.

Using a lot of resources(books, articles) I have created a project that implements objects that have components (completely de-coupled) from each other, a rendering manager that draws all my objects and physics system that detects collisions etc.. Now this is good and all but I am missing the most important piece of this puzzle: where should game play specifics be implemented then? I mean for it to be a game somewhere there must be rules that define the game.

Where in this whole process will I code: If the player is near the tree, the squirrel must fall out.

Is there some crucial part I am missing? It seems completely illogical for me to have these behaviors defined inside the classes because that would couple all of my entities and make it impossible to re-use them. Or am I misunderstanding the re-usability thing. Should it be that the classes themselves such as Player and Squirrel know about each other and can then be thrown away in terms of future use (then only the systems and components are re-used).

Please don't tell me to just try and "finish" the game. This is not an attempt to finish a game. I am trying to understand how the core of a game is supposed to work and how all of these different patterns and systems work together to produce a finished product. I really hope this post makes sense.

Thank you.

Advertisement
Maybe create a game logic function within the game class? This is because your main loop should be something like WndProc stuff, get input, do things with input, update all your objects, draw all your objects if you don't have a multi-threaded approach.
what

So over the past couple days I have learned a lot about design patterns and game architecture but now another mountain has appeared.

Using a lot of resources(books, articles) I have created a project that implements objects that have components (completely de-coupled) from each other, a rendering manager that draws all my objects and physics system that detects collisions etc.. Now this is good and all but I am missing the most important piece of this puzzle: where should game play specifics be implemented then? I mean for it to be a game somewhere there must be rules that define the game.

This is actually a more common question than you may imagine. You have built all the pieces using what seem to be best practices, now how do you use them to actually make the game. It's not as obvious as you would think.. :)

Where in this whole process will I code: If the player is near the tree, the squirrel must fall out.

This is a very good example to start with. Restating it in a simplified manner: Player nears a tree, result a squirrel falls out.

Is there some crucial part I am missing? It seems completely illogical for me to have these behaviors defined inside the classes because that would couple all of my entities and make it impossible to re-use them. Or am I misunderstanding the re-usability thing. Should it be that the classes themselves such as Player and Squirrel know about each other and can then be thrown away in terms of future use (then only the systems and components are re-used).

What "I" would do:

1. Attach a trigger volume around the tree. Anything which enters the volume triggers an event which can be piped to functions or other components.

2. Attach the trigger event to a 'filter' which only passes the event if it is caused by the player object. Could be another component or a customized event/message proxy system.

3. Attach the filtered event to a spawner. Set the spawner to spawn a squirrel when triggered. Attach this to the tree also and route the event to trigger this spawner.

So, your "logic" is built up from simple concepts which can be reused and combined in many ways for other things. You have avoided putting any of this case specific logic into the player, so it gets to remain a nice focused object. You have attached the trigger to a static item so it is actually pretty low cost (moving trigger volumes are considerably more expensive). And the squirrel is the only "specific" item in the whole solution. Obviously to "spawn" a squirrel, you need a squirrel to spawn. :)

Basically the trick is to look at this from a "smart environment" viewpoint and don't think of the player as something special so much as just another thing in the world. The filter which limits events to the player could just as easily say to only spawn a squirrel when a nut falls from the tree and stops rolling within x-range. The trigger volume in that case would only be triggered if something became stationary within the area.

You can't treat game logic as totally abstract. Depending on the type of game, you might need a level editor in which you can create arbitrary objects such as trees and squirrels in a totally data driven way, and link them through mechanisms as described in the previous post.

Or you might be looking for a scripting system. Is it a very specific case that a squirrel appears? Will there be many different behaviours like that in the game?

Writing tree and squirrel classes might make sense if these are very common concepts throughout the game and you always want them to behave the same way. Still, you would want to minimise the responsibility of these classes and make them work as much as possible using other, more generic systems.

I think of it sort of like this:

the game/engine is sort of like a pyramid.

at the base, there is all the general-purpose functionality and infrastructure. this may often represent the bulk of the code in the game, and at this level we generally want to keep things general purpose.

but, as one moves up the pyramid, the amounts of code begin to shrink and become much more specialized, first to general architecture, then to game mechanics, then to specific gameplay elements (such as the squirrel and the tree).

so, at the same time we don't want low-level infrastructure sufficiently specialized to constrain subsequent development, we also don't want the high-level game logic to be sufficiently generalized as to hinder getting stuff done.

sometimes it is itself a hard balance though.

1. Attach a trigger volume around the tree. Anything which enters the volume triggers an event which can be piped to functions or other components.
2. Attach the trigger event to a 'filter' which only passes the event if it is caused by the player object. Could be another component or a customized event/message proxy system.
3. Attach the filtered event to a spawner. Set the spawner to spawn a squirrel when triggered. Attach this to the tree also and route the event to trigger this spawner.

So, your "logic" is built up from simple concepts which can be reused and combined in many ways for other things. You have avoided putting any of this case specific logic into the player, so it gets to remain a nice focused object. You have attached the trigger to a static item so it is actually pretty low cost (moving trigger volumes are considerably more expensive). And the squirrel is the only "specific" item in the whole solution. Obviously to "spawn" a squirrel, you need a squirrel to spawn.

So basically I will have like 100+ events specified in a very generic way? Then I set up some observer / listener messaging system so that every object only registers for certain events and then respond on it? I must say thinking about this in such an abstract way seems alright but I guess it will be a nightmare to implement in reality :/

You can't treat game logic as totally abstract. Depending on the type of game, you might need a level editor in which you can create arbitrary objects such as trees and squirrels in a totally data driven way, and link them through mechanisms as described in the previous post.

Or you might be looking for a scripting system. Is it a very specific case that a squirrel appears? Will there be many different behaviors like that in the game?

I don't know enough about level editors or data driven development to implement something like that. Is it absolutely necessary to script game play behavior or can it be hardcoded?.

So basically I will have like 100+ events specified in a very generic way? Then I set up some observer / listener messaging system so that every object only registers for certain events and then respond on it? I must say thinking about this in such an abstract way seems alright but I guess it will be a nightmare to implement in reality :/

This is fairly accurate, although in reality, you probably won't have quite as many events as you fear. Look at the example AllEightUp posted. A trigger area will be useful in lots of places and not just in the spawning of squirrels. Some events will be reused, or used by different components. As an example from my own project, say you hand an event ApplyDamage to an object for combat purposes. The object's Vitals component will listen for ApplyDamage and when it is received, it will apply the specified amount/type of damage to current HP, in turn possibly generating events to send to the owner object (LifeLow, Dead, etc...). However, a FloatingCombatTextQueue component attached to the object ALSO listens for ApplyDamage, and upon receipt will spawn a floating combat text entity to drift above the object indicating the damage received. A CombatLoggingComponent will listen for it and generate a text entry to log in the scrolling combat log ("Orc's incandescent strike hits Jim for 17(Fire). Jim is badly wounded."

If you find yourself writing a whole lot of special case or one-use events, then you might be getting too specific in your design and you might want to step back and see if you can figure out how to use existing events to accomplish your goal. If there is just no way, then go ahead and implement a new event but try to make it as general as you can so that other functionality can listen for it and do different things as well.

I don't know enough about level editors or data driven development to implement something like that. Is it absolutely necessary to script game play behavior or can it be hardcoded?.

You don't necessarily need to script. At some point within your code, though, certain behaviors are actually going to have to finally be implemented, whether they be in script or otherwise. The goal, though, is to write each component of code with the general-case in mind, rather than coding toward a single specific instance. For example, you don't want there to be in your code somewhere a function called MakeSquirrelSpawnWhenPlayerGetsCloseToTree. That is getting too coarsely grained with your design, and will be an absolute mess. All of that macro behavior should emerge as a result of the interaction of simpler, more general parts such as AllEightUp's trigger+filter+spawner combo. That same combo, by tweaking the data given to it, could be used to trigger an arrow trap when the player steps on a certain dungeon floor switch, or to start a plot-required dialog or cutscene when the player draws near a waiting NPC. They use the same basic structure (proximity trigger, filter to select player from other objects and ensure the event triggers only for the player, spawner to generate a new object, spell/trap effect, or dialog conversation).

Where an editor would come into play is in providing a visual tool for stringing these pieces together and tweaking the data to feed to them to get the desired behavior.

Thank you for clearing that up for me Jtippets. I really appreciate all the advice you guys have given me. It seems I will be doing a lot more research concerning event systems and behaviors the next few days.

All of the examples have been used in terms of a reasonably complex game where the game needs to be broken in pieces to fit into our heads. But what about small games like pong or snake. Surely the event based system is complete overkill. Would it be better in these situations to have a universal Game class that handles all the specifics? For example if the ball hits the paddle in pong you would have this in Game.update():


if world.collide(paddle,ball)
{
  soundManager.playSound(ball_hit);
  ball.physics.bounce();
}
 

I can see this will become a huge problem if you don't know the exact boundaries, scope and specifics of the game. Are there any alternative methods that could be used when dealing with smaller games?

Even in small games, you should make an effort to hold to good design principles. Small games, after all, are where you learn the skills necessary to make larger games. While a large universal Game class that handles everything might be okay (probably not optimal) for Pong, it simply won't translate well to larger or more complex games. In essence, you're leading yourself down a dead-end by using a universal know-it-all class.

Okay, I guess the only way to separate the game play then would be to delve into data driven development. But one thing I have been wondering is - you know all those tutorials on the internet on creating a game, they all create their entities and then the functions inside are specifically tailored for certain situations. Then everything just gets updated and checked inside the main loop.

Why do these guys promote programming based on bad design principles?

This topic is closed to new replies.

Advertisement