Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Geek Culture / Keeping your code orgainsed

Author
Message
The Zoq2
15
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 6th Mar 2012 16:34
Hi, I recently decided to rewrite the code for my game, mostly because of some major bugs and the fact that I know better ways of doing things now. But allso because my code is realy un organised.

So do you have any tips on keeping the code organised?
Pincho Paxton
22
Years of Service
User Offline
Joined: 8th Dec 2002
Location:
Posted: 6th Mar 2012 17:24
Just always do things the same way. Always use the same letter like...

For n = 1 to 100
next n

So I always use n as my most common loop.

For n1 = 1 to 100
For n2 = 1 to 100
For n3 = 1 to 100
next n3
next n2
next n1

Nested loops are always like that.

Mind you apart from always using the same letters my code isn't indented or anything, so I am the last person to care.

Seppuku Arts
Moderator
20
Years of Service
User Offline
Joined: 18th Aug 2004
Location: Cambridgeshire, England
Posted: 6th Mar 2012 17:29 Edited at: 6th Mar 2012 17:35
This is a detailed explanation of how I organise my code...it might look confusing because I'm being descriptive, but I've found this approach has been the most useful for me. And of course Pincho is spot on with the consistency, my letter for those kind of loops is always 'x', but to each his own. Always good to be consistent without how you approach things to avoid confusing yourself later, "was that 'x' or was it 'z'?"


1. User Defined Types

Basically your UDT's can work like a database for your variables. Before I used them I'd have loads of different variables and arrays. With UDTs you're still dealing with the same data, but they're tidier.

For example:


2. FreeObject(), FreeImage() etc
You will have spotted 'freeobject()' above. These sort of functions mean you're not keeping track of your object numbers, instead you'll just use the lowest free number and store it into a variable. You just need that variable, 'steve.object' is LOT more memorable than '364'.

3. Turn everything into a function.

I've completely eliminated all gotos in my code. But have some structure to your functions. I've taken some inspiration from XNA on this.

I try to section my main code out into section and each section is a function.

Intitialize()

I stick all global variables and arrays in here.

System()

I stick all system start-up stuff in here. Resolution, fullscreen, load options, fonts and I've even stuck shaders in here (I only load them once, so I don't make them a part of my main Load function)

LoadContent()

All of the content loading goes in here. So you 'load objects' and 'load images' and so on.

Update()

This is the game loop. You may wish to use functions inside of it to cut down the code. For example I use a separate function called 'UpdateCharacter(obj)', which keeps stats up to date and his control methods.
Then I have a function for managing scene cameras and other functions to keep the main loop code tidy.


Of course, I may introduce other functions to keep it tidy. For example I might have an inventory menu that calls a second loop and I want to return to the game, of course I could just call 'Update()' and put me back in that loop, but what if I wanted to reset a variable everytime I return to the update loop without looping? I just introduce 'Initiate' to go in between 'LoadContent' and 'Update'. You may wish to add more functions depending on how you've designed the game. But on start, the game just calls these functions:

Initialize()
System()
LoadContent()
Initiate()
Update()

Well, I actually have more, but that's just a structure to build from. Now, the advantage here is, you can use LoadContent() and the functions you use inside handle multiple levels in your game. So you can call these functions when you finish a level but with different variables. So you load a different scene, place different enemies in different places and so on.

4. Source File structure. I prefer to have multiple source files and each covers a specific purpose making it easier to point to each individual purpose of your game engine. A basic structure for me would be:

Source.dba -> this is your main

Purpose: make UDT's, call the game functions:
initialize(), System(), LoadContent(), Initiate(), Update() in that order.

GameManager.dba

Purpose: This is where your game functions (above) as stored) These functions will point to the different parts of your game engine, hence it is the 'game manager'.

Characters.dba

Purpose: to store all character data. This includes stats, which may be called in 'initialize()' or data to load, which may be called in 'LoadContent()'.

Scene.dba

Purpose: to set up the data for scenes/levels. This contains data for loading (LoadContent()) and things like 'LoadWayPoints'. I don't use this to set up individuals levels, these just contains things like:
Scene(object).map.num = freeobject()
load object scene(object).map.file, scene(object).map.num

The 'filename' for it is actually set up in a different function. This is where I stick a file called:

SetScene.dba


Purpose: This is where I create conditions for each individual scene and that's prepared for the 'LoadScene(obj)' function. So it could be:

if obj = bedroom
Scene(bedroom).map.file = "bedroom.x"

(you'll see that UDT is being used as an array. Just 'dim scene(number of scenes) as level' if you're unfamiliar with UDT's.)

An alternative approach is to have all of your data input via a script system, which requires more work, but it least it means not having to compile every time you change a variable.

My entire list of source files is fairly long, but that's because I've just built on top of that structure. But at least imeans I know what points to what and nothing is too generalised for it to not make sense later.

5. Comment your code

I find it's very important, particularly when things build in complexity. Whilst you can understand programming, you need notes to remind yourself what the purpose of each piece of code and why it's there. This means less stopping and asking yourself, "so what does this do again?"


The Zoq2
15
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 6th Mar 2012 20:05
Thanks for the tips! Unfortunley though, I allready do most of these things...

Quote: "For n1 = 1 to 100
For n2 = 1 to 100
For n3 = 1 to 100
next n3
next n2
next n1"


I didn't think about using numbers for the loops, that could help a lot!
Seppuku Arts
Moderator
20
Years of Service
User Offline
Joined: 18th Aug 2004
Location: Cambridgeshire, England
Posted: 6th Mar 2012 21:21
Have a friend with a bunny rabbit and a gun and have him threaten to shoot it if you don't keep your code organised?

If you don't like bunny rabbits, then replace it was something you do like.


Perhaps plan your code before you do it so you're not continuously experimenting as you go through. Get an idea of structure before you write it. I wouldn't say my code is perfectly organised, in fact it still needs improving.

One approach I saw from the 3DBuzz C#/XNA tutorials was to go into your code and map out 'hypothetical' methods to make up each part of the main code, but not actually write in the functionality of each method and then after that gradually work those methods in. Of course you may find yourself adding more as you build up, but it's one approach that may or may not work.


Kevin Picone
22
Years of Service
User Offline
Joined: 27th Aug 2002
Location: Australia
Posted: 6th Mar 2012 22:02
Lots of good stuff has been covered and i don't have much time.. so some random bullet points..

* Function() are good, use them. So wrap up those repetitive bits of code and slap them in function.

* Group common themes of code into separate files. You might have a source totally devoted to player functions, another for Bag guys.. One for loading the media.. whatever..

* Use Meaningful Names for variables/arrays/types/ functions etc.. Keeping a consistent naming convention can go a long way to avoiding those little subtle slip ups.

* Enable Explicit Declarations (in your IDE) where ever you can, so rather than using Global Variables and risking a typo here and there. Wrap groups of properties into Types.

So rather than doing this,


we can do this,


Now if we make a typo, the compiler will pick this for us..


* Keep a keep clean structure. The easier the flow of execution is to read, the easier it should be to find logic errors.

TheComet
17
Years of Service
User Offline
Joined: 18th Oct 2007
Location: I`m under ur bridge eating ur goatz.
Posted: 6th Mar 2012 22:04 Edited at: 6th Mar 2012 22:06
May as well post this...



Just to add to the topic, my code is based a lot on the C++ style. For every instance in my game I have a Create(), Destroy(), and Control() function. I wrote a guide of how I write code. If you're interested, you can check it out here : http://forum.thegamecreators.com/?m=forum_view&t=190485&b=1

TheComet

Agent Dink
21
Years of Service
User Offline
Joined: 30th Mar 2004
Location:
Posted: 7th Mar 2012 00:09
Comment EVERYTHING. This is number 1. If you ever abandon a project, or leave it for awhile and come back, you'll be glad you did. Even if you don't think you need to now, just remember it's fresh on your mind.

http://lossofanonymity.wordpress.com
Zotoaster
20
Years of Service
User Offline
Joined: 20th Dec 2004
Location: Scotland
Posted: 7th Mar 2012 00:20
I do everything in layers and components. You start at the bottom and try and organise everything there, the simple stuff. For instance, programming a game in DBPro, the bottom layer would be a system for managing your objects, assigning them numbers automatically, maintaining a list of live objects, deleting them when necessary, etc. Once you've made this layer and tested it well and you know it works, you can treat that as a black box and use it to build the next layer, for instance, level loading, players and AI, vehicles, etc. Once this layer is done and tested, treat it as a black box, and use it to build the next layer, your actual game.

There's a software engineering term called 'high cohesion, low coupling', which basically means that components that are related are kept close together, and components that aren't related at all don't rely on each other and can operate independently of each other. Using this model/the one I described above, you can make all your components, and if they work, you don't have to worry about what happens inside (they're 'black boxes').

TLDR; Make small building blocks, and use these to make bigger building blocks, which you can assemble to make bigger ones, etc..

"everyone forgets a semi-colon sometimes." - Phaelax
Seppuku Arts
Moderator
20
Years of Service
User Offline
Joined: 18th Aug 2004
Location: Cambridgeshire, England
Posted: 7th Mar 2012 00:53
Basically code like Lego.


Diggsey
19
Years of Service
User Offline
Joined: 24th Apr 2006
Location: On this web page.
Posted: 7th Mar 2012 03:33
Also, for large projects use version control. Aside from all the obvious benefits like never losing code, if you accidentally introduce a bug you can very easily do a diff against the previous version and see exactly which lines have changed.

As people have said, creation and destruction of entities should always go through common code paths, and it also helps if you organise your functions by the type of entity on which they operate. Having seperate files for your more complex entity types means you can instantly find code you are looking for.

Use constants and globals rather than literals where it makes sense. You may think you're never going to change them but you almost certainly will at some point, and it saves you having to go through the code looking for places to change and likely missing some, causing hard-to-track-down bugs.

Remember that globals can be declared anywhere, the program doesn't have to execute a variable declaration for it to exist. This lets you group your globals together with the set of functions which operate on those globals rather than having a massive block of globals at the top of your code. Also, where you have lots of globals which are related it makes sense to make a UDT instead and have a single global variable of that UDT.

[b]
old_School
15
Years of Service
User Offline
Joined: 29th Aug 2009
Location:
Posted: 7th Mar 2012 06:38
Number of things you can do to keep code organized:

Use regions
#Region “Name Here”
End Region

Use Standard prefixes
Str = String
Int= Integer
Bol = Boolean
Pb = Picture Box
Etc

Use arrays or lists
Use lots of classes
Comment code for future use
BatVink
Moderator
22
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 7th Mar 2012 10:15
Quote: "Use regions
#Region “Name Here”
End Region

Use lots of classes
"


This doesn't help someone coding in AppGameKit T1 (or DBP)

If I had to pick the elements from above that will make the biggst impact it would be:

Put related functions into one file, other related functions into another file.

Used typed variables to prevent typos that aren't picked up by the compiler.

Put global variables into the include file with their related functions.

For every Init*() function, have a DeInit*() function, and maintain them simultaneously.

Seppuku Arts
Moderator
20
Years of Service
User Offline
Joined: 18th Aug 2004
Location: Cambridgeshire, England
Posted: 7th Mar 2012 11:31
Some IDE's for DBP allow you to collapse code, but of course we can't do regions, but we can collapse things like functions, REMs, loops and so on. I use Indigo and it's probably the best DBP IDE I've ever used - it even has something similar to intellisense for user defined types. Plus it has a few others things that may help keep code organised. It also stores back ups of your project, so that might be useful in doing Diggsey's suggestion.


Login to post a reply

Server time is: 2025-05-19 16:27:09
Your offset time is: 2025-05-19 16:27:09