Best Way to Structure A Game

Started by
10 comments, last by Stainless 9 years, 11 months ago

Hey Guys, thanks for your time.

So I'm creating a game and I'm trying to figure out what sort of structure I'm going to go with. This is for a large school project, and it has to be fairly formalised, which is why I'm going to the effort of finding a structure and sticking with it. The following structures that I know of are:

  • Event Driven
  • Data Driven
  • Standard, traditional game loop thingy
  • Model-View-Controller

Any suggestions as to what would be appropriate would be welcome.

Advertisement

there are probably almost as many answers as there are coders. Everyone seems to have their own ideas on the subject.

technically speaking, most "games" are some sort of modeling and simulation software. the "game loop" is the traditional way to write modeling and simulation software. IE display the scene, get user input, run the simulation, repeat until quit game.

event driven is what i refer to as "deferred processing". an event occurs that requires processing. instead of immediately handling the event and continuing, you store the event for later processing. this adds the overhead and complexity of an event storage / message system. but there can be cases where deferred processing is preferred or necessary.

data driven means you load data (usually constants) from a data file instead of hard coding it - IE how many hit points a dragon has, etc. it requires a bit more coding to implement. it provides two advantages:

1. non-coders can change the data. only useful if you need non-coders to change the data.

2. no re-compile required to change the data. only useful for games with long compile times - like Caveman - 20 seconds to translate, and 55 seconds to link. since i knew Caveman would be big by the end, i probably should have made it more data driven in the first place. if constant values are determined early on and change little thereafter, data driven can be overkill, even with long build times. Also data driven runs a little slower than hard coded, as it must do additional disk reads to load the data.

MVC is a design pattern from business apps (but NOT modeling and simulation apps). out of all the non-game specific design patterns, it might be closest to what one typically does in games, although i suspect that games and MVC tend to divvy up display and input slightly differently. I became a fulltime gamedev before MVC was invented so i'm not overly familiar with it. perhaps others can expand on the similarities and differences.

right now, i'm starting on my....perhaps my 25th or 30th game, and i'm going game loop and data driven:

 
 
 
' player -------------------------------------------------
 
 
st playerrec
orientation o
' playership specific variables: energy, dmg, hp, etc.
i modelID
.st
 
 
 
 
 
'  star map ------------------------------------------
 
st moonrec
i active modelID size orbitrad
.st
 
#d MAXMOONS_PER_PLANET  10
 
st planetrec
i active modelID size orbitrad nummoons
moonrec moon[MAXMOONS_PER_PLANET]
.st
 
#d MAX_PLANETS_PER_STAR  20
 
st starrec
i active modelID size numplanets
planetrec planet[MAXPLANETS_PER_STAR]
orientation o
.st
 
#d MAX_STARS  1200
 
 
fn v drawmap
4 i MAXMAPOBJS
if is_nearby_mapobj(i)
c draw_mapobj(i)
.
.
.
 
 
' starports ---------------------------------------
 
 
st starportrec
i active type
i what_it_orbits  ORBITS_NOTHING. use orientation.
 ORBITS_STAR. use star index and orbit_rad.
 ORBITS_PLANET. use star_index, planet_index, and orbit_rad.
 ORBITS_MOON. use star_index, planet_index, moon_index, and orbit_rad.
i star_index      it orbits star[star_index] or one of its planets or its planets' moons.
i planet_index    it orbits planet[planet_index] or one of its moons. use orbit_rad.
i moon_index      it orbits moon[moon_index]. use orbit_rad.
i orbit_rad
orientation o
.st
 
#d MAX_STARPORTS 100
 
 
 
 
'  target types -----------------------------------
 
st ttyperec
i hp modelID
.st
 
 
#d MAX_TTYPES 20
 
 
ttyperec ttype[MAX_TTYPES];
 
 
 
' targets -------------------------------------
 
st tgtrec
i active type dmg
orientation o
.st
 
#d MAXTGTS   100
 
 
fn v add_tgt i type mat *orientation
i i
i=1st_inactive_tgt
= tgt[i].type type
= tgt[i].orientation *orientation
' init tgt variables like damage=0
.
 
 
 
 
 
 
 
fn v drawtgt i i
' draw tgt i
c drawmodel tgttype[tgt[i].type].model tgt[i].ani_player tgt[i].orientation
.
 
 
 
 
fn v drawtargets
i i
4 i MAXTARGETS
== target[i].active
c drawtgt i
.
.
.
 
 
 
 
fn v update_tgt i
' move tgt
' model energy, damage control, etc
.
 
 
 
 
 
' projectiles --------------------------------
 
 
 
st projectilerec
i active type
orientation o
.st
 
#d MAX_PROJECTILES 100
 
 
 
 
 
 
' particles -------------------------------
 
 
 
st particlerec
i active type
orientation o
.st
 
#d MAX_PARTICLES 500
 
 
 
 
 
 
 
 
 
fn v drawparticle i i
'  draw particle i 
.
 
 
 
 
fn v drawparticles
i i
4 i MAXPARTICLES
c move_particle i
c draw_particle i
.
.
 
 
 
 
 
 
 
 
'  galaxies ---------------------------------------
 
 
st galaxyrec
i texID
orientation o
.st
 
#d MAX_GALAXIES 10
 
 
 
 
fn drawgalaxies
4 i MAXGALXIES
c draw_galaxy i
.
 
 
 
 
' render --------------------------------------------
 
 
 
 
 
 
 
fn v drawbridge_interior
' draw bridge interior using 3d meshes and 2d sprites
.
 
 
 
 
 
fn v drawbridgeview
c Zbeginscene
c drawskybox           
c drawgalaxies
c drawmap 
' (nearby stars, planets, moons, starports, 
'              and other map objects).
c drawtargets 
' (ships etc)
c drawprojectiles (torpedos, laser beams, etc)
c drawparticles 
' (streaming stars, debris, etc)
c drawbridge_interior
c showscene
.
 
 
 
 
 
fn v render
sw view
ca bridge
c drawbridgeview
brk
ca mattermover_view
brk
ca transport_bay_view
brk
.
.
 
 
 
 
 
' input ------------------------------------
 
 
 
 
fn v input 
? Zkeypressed(VK_whatever)
' do some shit with player ship
.
c getmouse &x &y &b
? isin x y <some area>
' do whatever with player ship 
.
' etc
.
 
 
 
 
 
 
' update -------------------------------------
 
 
 
 
 
fn v update
4 i MAXTGTS
update_tgt i
.
.
 
 
 
 
 
 
 
 
'  runmission ------------------------------
 
 
 
 
fn v runmission
do !quitmission
render
input
update
.do
 
 
 
 
 
 
' initmission ---------------------------
 
 
 
 
fn v initmission
' choose mission
' show orders
.
 
 
 
 
 
'  rungame -----------------------------
 
 
 
rungame
do !quitgame
initmission
runmission
endmission
.do
 
 
 
 
'   runprog ----------------------------
 
 
 
fn v runprog
menu simspace 8.0...
continue
tutorial
new game
load game
tools
quit
.
 
 
 
 
 
 
 
'   initprog ----------------------------
 
 
initprog
Zinitall
.
 
 
 
 
'  main --------------------------------
 
 
 
void main
initprog
runprog
endprog
 
 
 
' ----------------------------------------------
 
 

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

You need a book to answer this question, a single forum post just won't do.

For that, there's a couple books I recommend. The first is Game Coding Complete, 4th Edition. It presents and nicely explains an architecture that covers all the topics you mentioned (events, data-driven configuration and actor creation, a process-based main loop, and a very MVC-like architecture).

The source code is freely available here: https://code.google.com/p/gamecode4/ if you want to have a look. Note this is actually a pretty sophisticated engine, and has the drawback of using a little "throw-away" for example purposes. Compared to the next recommendation, this engine goes further (especially in the scenegraph, editor and data-driven areas) but is also a tougher read for beginners.

The next is Beginning Android C++ Game Development. Don't worry too much about "Android" in the title if that's not what you're after, it's completely trivial to implement the code on desktop SDL2.

Heartily recommended as it is the best educational game engine I have ever seen. It really distills down advanced concepts to their simplest form (including entity/component, task-based main loop, events etc), allowing you to build up from a complete, AAA-style foundation, rather than the "throw-away" approach most educational engines take.

You can grab the code here: http://www.apress.com/9781430258308.

I became a fulltime gamedev before MVC was invented so i'm not overly familiar with it.


O_o

MVC was invented in the 70s. And implemented in the 80s with Smalltalk.

Beginner in Game Development?  Read here. And read here.

 

(IMHO) Challenges that I found in the past:
Resources (data management and duplication avoidance);
Composition over Inheritance;
Single Responsability Principle;
Assuming that you have a good knowledge of the various technical aspects, try to think on the size of your project and how much time you have to invest on it in a way that you learn how things works the same time you produce.

These sorts of topics just turn into a cavalcade of buzzwords, and it's difficult to escape that. Keep in mind that games are typically written and then analyzed for patterns, rather than vice-versa.

One commonly important thing to think about is game state management. There's a number of ways to do this. I remember one mod (though for the life of me I can't remember who) bring up the Run and return successor pattern to handle this. Note that this works better in some languages than in others, and a simple State Pattern may be more appropriate.

I once read an article several years back saying traditional game loops were on the way out. I'm not sure how true that is, and more veteran people can pipe in if they want, but it's been said for what that's worth.

Events are usually bolted on to existing paradigms as a method of asynchrony. Whether this is asynchronous input, dynamic resource reloads, or extra-gamey UI changes on some platforms (i.e. Android).

One of my biggest shames is that I've never really grokked MVC to an appreciable level, but much like Norman Barrows says, I've mostly seen it (at least explicitly) referenced in enterprisey contexts.

As for Data Driven Design, use it. It takes time to make the scaffolding to implement it, but for all but the most trivial of games, it pays off in spades. The only real drawback (outside of the relatively small up-front development time cost) is the performance penalty from file IO. You can mitigate this via resource caching/blobbing schemes or, if developing for a more limited hardware platform like an embedded device, converting everything to code as a build step for release builds.


data driven means you load data (usually constants) from a data file instead of hard coding it - IE how many hit points a dragon has, etc. it requires a bit more coding to implement. it provides two advantages:
1. non-coders can change the data. only useful if you need non-coders to change the data.

A non-coder can edit a C struct just as easily as he can edit a JSON object. The big difference is that it's generally easier to find/edit the data, programmers or otherwise, all of the other benefits to DDD not withstanding.

I think that starting out by thinking about game structure is the wrong way to approach the problem.

First thing to do is look at your target platform and work out what problems you are going to have, then come up with a game structure that can cope with those problems.

Knowing about the "standard" design patterns is useful, but there are times when you have to invent your own.

I'll give you an example.

Say you decide to use a common design. You create little subroutines to handle all your display states. DrawMenu() DrawCredits() DrawGame() etc. Each of those contains it's own event handling based on polling system flags and is a self contained program.


  int selection = 0;
  while (1)
  {
    displayMenu(selection);
    if ((isKeyDown(Keys.Enter))&&(selection==0))
    {
      DrawCredits();
    }
  }

This makes it very easy to work on when developing. Instead of having to go through several screens, press keys, do this do that, you just make your start-up code call the routine you are working on.

You are happy with this and write your game on the PC and love it.

You then move to a platform which is based on callbacks, and your design becomes a problem.

You can't just call a new display handler, you have to respond to callbacks and suddenly you have a hell of a lot of recoding to do. Not difficult coding, but lots of it.

That while(1) kills you.

So I would advise you to look at the target platforms first and then think about game structure.

I remember one mod (though for the life of me I can't remember who)

SiCrane.


Any suggestions as to what would be appropriate would be welcome.

The things you listed aren’t mutually exclusive.
Every professional game has a game loop. For most platforms this is a while loop, but on iOS it is a callback handler for a display link triggered systematically by the operating system on v-blank.

So “standard game loop” basically applies no matter what.
Next you have to consider how much you focus on the remaining 3.

Events: Events should be avoided as much as possible. Games are not event-driven. Events can exist inside games but they are not at all how a game is “set up” or driven. The only practical uses for events in games are map triggers, timed triggers, AI, and similar.
Not input. Not the game loop or message pump.

Data: Games should be as data-driven as possible and feasible. Reusable frameworks are the only reason the game industry is sustainable. Frameworks take whatever data you give them and play them back, render them, animate them, or whatever. What data you give to the engine defines the game you are making.
Rules of gameplay are logic, not data, and must be coded.
I mentioned “feasible” for a reason. In the best-case scenario you would make even the renderer data-driven. Files similar to the Effects Framework would tell you how to render things and with what states, and a higher-level layer could control the entire high-level rendering flow. This is best-case, but perhaps not feasible for a first-time attempt.

In other words, find your own balance between perfectly data-driven and your ability/desire to actually make it so.

MVC: This is not widely used in video games. This is appropriate for regular event-driven desktop and mobile applications, but due to the way professional games are designed, it’s not really appropriate.


Say you decide to use a common design. You create little subroutines to handle all your display states. DrawMenu() DrawCredits() DrawGame() etc. Each of those contains it's own event handling based on polling system flags and is a self contained program.

The only reason this is “common design” is because people aren’t born automatically knowing any better. It’s inappropriate to say this is “common” without proper context: It is typical of ultra-beginners, and since most people are ultra-beginners it is thus “common”.
It’s like the use of magic numbers. Extremely far from anything you would ever want to advise someone to do, but common.
General Game/Engine Structure


You then move to a platform which is based on callbacks, and your design becomes a problem.

You can't just call a new display handler, you have to respond to callbacks and suddenly you have a hell of a lot of recoding to do. Not difficult coding, but lots of it.
That while(1) kills you.

On any desktop:
while ( !bQuitCondition ) {
    m_pgGame->Tick();
}
On iOS:
- (void) displayLinkHandler:(CADisplayLink*)displayLink {
    m_pgGame->Tick();
}
It’s really nothing.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

The only reason this is “common design” is because people aren’t born automatically knowing any better. It’s inappropriate to say this is “common” without proper context: It is typical of ultra-beginners, and since most people are ultra-beginners it is thus “common”.

It's how a hell of a lot of SDL games are written, and I have had to port a lot of them. They just called get event in each subroutine.

Changing this isn't trivial, it requires a lot of restructuring

You have also completely ignored the point I was trying to make.

Designing your game structure before you have identified platform issues is just wrong. You have to know issues you are going to face on all platforms you wish to support before you start designing game structure.

I have come across this so many times, mainly with relatively new studios in places like China and India. They start off with one platform, they find a coder that has written for that platform and make him the lead, he just codes for that platform with no regard for others. Then the business decision is made to port it to another platform and they have major problems.

You need to consider cross platform issues if you are going to support multiple platforms, and in this day and age doing multiple versions for multiple platforms is the norm rather than the exception.

You are really making something out of nothing.

The original poster likely already has a target platform in mind. 1. The exact amount you should have in mind when you are trying to learn game development.

Let’s not explode his head with other concerns and let him or her just work on the platform of his or her choice until he or she is ready to move to another.

It's how a hell of a lot of SDL games are written

I don’t see how that makes a case for what you want to prove. Ultra-beginners tend to use wrappers such as SDL, and lots of magic numbers. The majority of all programmers are beginner level, making whatever they do “the most common”.
Does that mean it is right? Should we all go around telling people to use magic numbers then?
General Game/Engine Structure


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

This topic is closed to new replies.

Advertisement