• Advertisement
Sign in to follow this  

Structuring a games code...

This topic is 4588 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've made a complete mess of code thats completely unorganized while working on an Asteroids game, I am wondering if anyone has some tips to better organize the code?

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
Do read some books on OOP, this should help. (I presume ofcourse you are using a OOP language).

Share this post


Link to post
Share on other sites
You should firstly organize your ideas in your brain, and then start painting your code here and there. Try to break apart the game into smaller parts, possible unrelated to each other and work each of them one by one.

Share this post


Link to post
Share on other sites
Redo the same project many times

I used to be awefull when it came to "losing" sourcecode, I'd end up writing the same project 2 or 3 times -_-
But each time I did I noticed something - the code was getting smaller & more precise
Because I'd done it before my brain knew the design patterns it was going to follow
I was able to think 2 or 3 stages ahead & because of that real structure started to form

If you want to make the source better just throw it away & start again
Slowly the different design pattersn start to stick; you start generalising & structure emerges. It becomes automatic & you're able to think further ahead

There's no substitute for practice really, but generally the best way I've found to practice is to redo what you've just done - but from scratch

sorry if I'm repeating myself but it is totally true ;] trust meh

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Here's one strategy that I've found very helpful:

For every project I do, I link against a second project that contains all my general, reusable code. When I start a new gaming or graphics project, I've usually trying something new so the code gets a bit long and messy. Once I get everything working though, I try to go back and find common reusable pieces of code - for example, a generic functions for finding an intersection between a line and plane - and move that out of the gaming/graphics project and into my general coding library. And, very importantly, I clean up the code before putting it into my generic code library; no messy code in my common code base! Then I repeat this process on the game/graphics code until my project contains only code that's really specific to that project.

I use this generic libray in all my projects - so when I start the next project, I no longer have to rewrite those tedious bits of framework code. Of course, you might argue I should be using a third-party library for that type of code anyway, but since I wrote all the code, I know how it works, and I have complete freedom to change it - which can sometimes be a pain with third-party libraries even if they're open-source. (Not to mention I'm usually just coding this stuff for the learning/fun of it).

Another benefit is if I end up scrapping that initial gaming project and never manage to get it to compile again, it wasn't "wasted" time since all my other projects (existing and future) benefit from everything I added to the generic library. [I used to be really bothered about putting lots of time and effort into projects that died about 10-75% through...now, I don't feel so bad because later projects usually benefit from what I added during that development.]

I then also make a serious effort to keep the code in my general programming library organized, documented, and correct. I run doxygen on it, I browse old files I haven't looked at every once in a while, and even just go through purely to clean-up the formatting and comments from time to time. Keeping the code organized is actually a bit easier in a general programming library though, because the code going into this library is supposed to be general (i.e. no or few dependencies on other code, data structures, etc.) and I find it's easier to categorize general code. I'm working in C++, so I just drop the code into different namespaces, such as MyLibText, MyLibGui, MyLibGeometry, MyLibDirectX, etc. Also, there are lots of good generic gaming libraries out which you can use as a basis for how to organize your own code (i.e. browse their documentation and realize they have a really cool Image API and model yours after theirs).

Also, I will note that over time I've restarted my generic library several times from scratch because as I learn more, I realize better ways of doing and organizing things.

Maintaining an organized codebase of my own reusable code has been a huge help to the many small projects I like to occasionally throw together.

Share this post


Link to post
Share on other sites
Just a quick guide:

Reusable Code:

Rendering Engine
Texture Manager
Image Loader
Audio Engine
Math Libary
Utility Classes
Physics Engine
Scene Graph
Pathfinding
General AI Routines (fuzzy logic, state machines, etc).
User Interface
Game Object Manager
Configuration File
XML Loader

New Code:

Game Logic
Game Objects/Characters
Model Manager (could be standardised with good planning)
Level Loader (never has a project where the file format hasn't changed!)

Share this post


Link to post
Share on other sites
I apologize for the lack of info, I am using C++ with SDL and OpenGL, and i've made a real mess of my asteroids code.
http://rafb.net/paste/results/6O2hU981.html

Thanks for the articles, and information, I won't be buying any books though.

Edit: I wanted to know about like what to store in functions and stuff like that...

Share this post


Link to post
Share on other sites
Woah, that's a severe lack of abstraction you have in your code there son! :)

A good heuristic is for each function to do only a single thing. For example, you could break your code up and have an UpdatePlayer function, as well as a HandleInput function as well as a RenderPlayer function etc. Don't make your UpdatePlayer function render your player as well.

Share this post


Link to post
Share on other sites
I know what you mean. But the more you code, the better your structure will be. Take my word for it. In the mean time, here are a few tips to help you:

-When you get an idea, don't immediately sit down and code it. Look at Steven Spielberg. Did you know that for every scene he directs, he shoots from MULTIPLE camera angles to determine the best view for for the final cut? Not a surprise, but take his advice. Look at your problem from multiple angles and decide on an approach that will work best.

-Formalize your code. Give yourself a standard coding paradigm. Make yourself put that space after every parenthesis. Make yourself place a g_ before each global variable. This structure will propagate throughout your code and you will find that even your design will benefit from it.

-Read professional code like a book and learn from it. Yes, it is a bit overwhelming when you are trying to look through 400,000 lines, but get over it and just pick a spot and begin. For example, I opened up the quake source one day and chose a random document. It just happened to be one of the header files that redefined int to qint and float to qreal IIRC. I went searching online and found that the reason for this is to allow for compatibility across multiple platforms in the future. There we go - one more technique from the pros. Learn from them.

Best of luck.

Share this post


Link to post
Share on other sites
Some tips based in the source code you posted (sorry if I sound a bit harsh here and there, my intentions are to give you useful feedback, no flaming):

- break up the functions into sets of smaller functions with meaningful names. For example:

if (keys[SDLK_SPACE]){
if (shoot){
shoot = false;
shoottime=SDL_GetTicks();
for (int i=0;i<BULLET;i++){
if (barray.used==0){
barray.x=player.px;
barray.y=player.py;
barray.radians=player.radians;
barray.xv=cos(player.radians)*10;
barray.yv=sin(player.radians)*10;
barray.angle=player.angle;
barray.time=SDL_GetTicks();
barray.used = 1;
break;
}
}
}
}


This snippet is part of a huge function. If you would replace it by:

if (keys[SDLK_SPACE])
{
if (shoot)
{
ShootBullet();
}
}

// and obviously move the shooting code to the ShootBulletFunction


It would be much more readable already. If you apply this principle consistently thoughout your code, eventually your main function should look something like this:

int main(int argc, char **argv)
{
InitSDL();
InitOpenGL();
InitGameData();
RunGameLoop();
ShutdownSDL();
return 0;
}


Which is much more readable IMO.
You can help yourself into doing this by forcing yourself not to use functions with more than, say, 10 lines of code (this rule is not flexible enough for most cases, but you should break it as little as possible).

- Use meaningful names. I do not consider 'barray' a meaningful name. Assuming it is a an array with bullets 'bullet_array' would be more descriptive. 'drawobj()' is also not very good. I have no idea what it's supposed to draw. If it daws the player you could call it DrawPlayer(), for example.

- Use constants variables instead of hard-coded numbers (you already did this for some variables, like SCREEN_WIDTH and SCREEN_HEIGHT). You frequently use constant numbers in your code:

glVertex2f(-5+player.pos[0],-10+player.pos[1]);
glVertex2f(-5+player.pos[2],-10+player.pos[3]);
glVertex2f(-5+player.pos[4],-10+player.pos[5]);


I have no idea what the -5 and -10 constants are supposed to be. If I assume here that they are some sort of borders, I could replace it by:

glVertex2f(PLAYER_LEFT_BORDER_OFFSET + player.pos[0],
PLAYER_RIGHT_BORDER_OFFSET + player.pos[1]);
glVertex2f(PLAYER_LEFT_BORDER_OFFSET + player.pos[2],
PLAYER_RIGHT_BORDER_OFFSET + player.pos[3]);
glVertex2f(PLAYER_LEFT_BORDER_OFFSET + player.pos[4],
PLAYER_RIGHT_BORDER_OFFSET + player.pos[5]);

// and of course you should define the constants somewhere in the top of your file:
const int PLAYER_LEFT_BORDER_OFFSET = -5;
const int PLAYER_RIGHT_BORDER_OFFSET = -10;


Note that this also has the advantage that if the left border changes, you need to change only in one location (instead of many; the -5 turns up alot in your code).

- And finally, what FReY said: you could go for a bit more abstraction. This is the hardest part, and can probably only be introduced by starting from scratch with a new design (on paper; one that shows every object in the game and how they relate).

Tom

Share this post


Link to post
Share on other sites
An easy way to keep code well structured and designed is to jot it down in Pseudo code (Structured English). It’s a lot clearer than many actual languages and allows you to get your head around the code before you go ahead and actually implement it.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Jeff Plummer's thesis:
http://www.jeffplummer.com/Writings/Writings.htm


Kyle Wilson's website:
http://www.gamearchitect.net/


Gamasutra.com article:
http://www.gamasutra.com/features/20050414/rouwe_01.shtml



// ville

Share this post


Link to post
Share on other sites
As far as specific design patterns: MVC. Model-View-Controller. I use this pattern on every game I write. Usually I end up mashing the Model and Controller into one class though.

The way it works is: "model" code takes care of the game logic. "view" code takes care of drawing.

Here's the rules you have to follow:
The model knows as little about the view as possible. In the best case, the model doesn't have a link to the view at all.
The view can know pretty much everything about the model.
The model contains all the important data.
The view can contain data, but only data relevant to drawing. None of the view's data is persisted. All of the view's data can be generated from scratch using only a model.

Also, you don't have to restrict yourself to one model class and one view class. Typically there will be several model classes and several view classes. Here's the important thing: every class must either be a model class or a view class. Really. There have been times when I've tried to have a single class work as both a model & view class simultaneously, and it always ends in disaster. It may be more work in the short-term to keep the model & view seperate, but trust me, it will make you happier in the long term.

Share this post


Link to post
Share on other sites
I use MVC for some simple java games i write when im bored. the model would contain the data and the game logic. the viewport would actually be an interface, so i could implement it any way i want.

this is important, because you can create, say, a console view of your game, and a swing/awt version of your view, all you need to do is make different implementations. same thing with the controller, you could abstract it out, get input from keyboard, joystick, network. abstraction is the best part of game design.

Share this post


Link to post
Share on other sites
Quote:
Original post by ScottC
I apologize for the lack of info, I am using C++ with SDL and OpenGL, and i've made a real mess of my asteroids code.
http://rafb.net/paste/results/6O2hU981.html

Thanks for the articles, and information, I won't be buying any books though.

Edit: I wanted to know about like what to store in functions and stuff like that...


It doesn't look so messy to me... and it looks like C to me...

but I mean why do you really need much abstraction for a 100 line program? Isn't that kind of overkill? You can do it but I mean.. 100 lines of code isn't very hard to manage.

Share this post


Link to post
Share on other sites
Quote:
Original post by Name_Unknown
It doesn't look so messy to me... and it looks like C to me...


The language should be somewhat irrelevant, many of the concepts in a C program can be applied to C++.

Quote:
but I mean why do you really need much abstraction for a 100 line program? Isn't that kind of overkill? You can do it but I mean.. 100 lines of code isn't very hard to manage.


Abstracting in a 100 line app is a bit overkill, but it will make later code reuse easier. For example, if you abstract the code to create a window it's easier to copy and paste the abstracted code into a later project without having to worry about breaking anything.

It's also good practice for when you start writing larger programs. When it comes time to write a 10,000 line program you'll have some experience abstracting things (and probably have a better idea of some pitfalls you can avoid).

Share this post


Link to post
Share on other sites
Quote:
Original post by Name_UnknownIt doesn't look so messy to me... and it looks like C to me...


How can you tell a differance?

Quote:
Original post by Will F
Quote:
Original post by Name_Unknown
It doesn't look so messy to me... and it looks like C to me...


The language should be somewhat irrelevant, many of the concepts in a C program can be applied to C++.

Quote:
but I mean why do you really need much abstraction for a 100 line program? Isn't that kind of overkill? You can do it but I mean.. 100 lines of code isn't very hard to manage.


Abstracting in a 100 line app is a bit overkill, but it will make later code reuse easier. For example, if you abstract the code to create a window it's easier to copy and paste the abstracted code into a later project without having to worry about breaking anything.

It's also good practice for when you start writing larger programs. When it comes time to write a 10,000 line program you'll have some experience abstracting things (and probably have a better idea of some pitfalls you can avoid).


That was the idea, being able to reuse the code, and to practice for writing larger programs.

Share this post


Link to post
Share on other sites
I found its best to structure you code according to a timeline of events, and sort things according to when they should happen. For instance, lets pretend its a fixed frame system.

void MainLoop()
{
while (!game.terminate)
{
ReadKeyControls();
RunGameLogic();
RenderGameGraphics();
}
}

Then, break up the 3 timeframes into "states", so that both would probably use the same switch structure.

void RunGameLogic()
{
switch( game.state )
{
case GAME_STATE_TITLE:
{
if (keypressed(ENTER)) game.state = GAME_STATE_PLAY;
}
break;
case GAME_STATE_PLAY:
{
if (keypressed(UP))
{
if (game.ship.speed < 100)
game.ship.speed += 1;
}
else if (keypressed(DOWN))
{
if (game.ship.speed > 0)
game.ship.speed -= 1;
}
}
break;
default: break;
}
}


The exact structure here does have the flaw that it'll render PLAY 1 frame before it should, but thats gotten around by giving video it's own state variable that synchronizes at the end of the game loop.

This will help some for simpler games, what I used for bACMAN. As for larger games, the ideas carry, but the exact structure it way different.

Share this post


Link to post
Share on other sites
Pen & paper is a great tool.

Thing about naming your methods for what they do. If the names end up like "CreateAPlayerAndGiveHimAGunAndLoadTheLevel()" then it should be broken down into separate methods to do each part - think of each method as doing one job.

Re-using code in libraries is a good practice to get into - saves you time and also you have to make the shared code flexible or you can't share it.

I don't generally use design patterns deliberately, but having a well-structured design on paper first is my top tip. Then implementing it in an OO fashion where each entity/thing is a class, and operations on a thing are methods of its class.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement