Sign in to follow this  
mlegend

project structure help needed

Recommended Posts

Hey I face a bit of a "project structure" problem and i hoped one of u could help me out. I dont know if this is the right topic, sorry if its not but since i just started game programming i post it here. Before u understand my problem i have to tell u a bit how my project is build up. My project has 3 states: Menu, Worldmap and Ingame (if u are playing a level). U need to think of it like mario a bit. In the menu nothing special, in the worldmap it initialize all levels with default values, which never should be disposed (like if the level is completed, how much % its completed etc). Now if u start a level, it passes the current level to the ingame state, and in that state the level is added with extra info like enemys, backgrounds, char start position etc etc. (If u go back to the Worldmap state this extra level info is disposed again). For so far so good. But now i add extra levels, i face a problem. In the ingame state i have 2 functions (well a bit more but.. its about these 2), UpdateRunning() and RenderRunning(). Anyway every level has different enemys and objects. Most of them are stored in Lists (List<Enemy1>, List<Object1> etc etc). Now i could just check for every list if its empty or null and not render or update the info in it. But then my 2 functions get very very large with all list checking, since there are more lists in a level that dont get used, then that there are lists that get used. Now my first tought was to make a different GameState for each level, but this isnt effective, since there is a lot of info in the InGame class that is "a need" for each level. Also all gamestates are defined on game startup, this means all objects in it are also defined, even if most of them have value null.. if i would have 20-30 levels then theres a gigantic of double objects in memmory which makes no sence. How should i face this problem? (If i was bad at explaining things, or if u dont understand what i mean, dont hestitate to ask) --edit Sorry i forgot to say that i program in the language C# and in vs2005

Share this post


Link to post
Share on other sites
I don't really get what you are saying but have a look at creational design patterns (Abstract factory and builder design patterns more specificaly and singleton for ingamestate). Those might be the solution to your problem.

And instead of allowing ingamestate object to update your levels, levels can have their own render or update methods. Sth like:

class Level // base class
{
virtual void UpdateLevel(Ingamestate* state) = 0;
virtual void Render();
...
}

class Level1 : Level
{
// implements virtual & Level specific functions
}

Share this post


Link to post
Share on other sites
What you want is to have a single game state that represents playing a level, and then have your levels saved to different files. This will make it easy to load what you need, when you need it, and not have a lot of unused stuff in memory.

Even just saving the levels to text files would be fine for a start.

Share this post


Link to post
Share on other sites
Hey

first of all thnx for ure quick replys.. To answer on endar first, i currently got my level data saved into different classes which are called
LevelData1
LevelData2
Etc

Then i got 1 level class which has a constructor, that initialize the default data.. (completed, % completed etc), since thats for all levels the same. The level class also has an initialize function, that get the data for the InGame state, it look something like this (dunno how to write it in a code block in this forum)

Initialize(LevelEnum Level) <-- which is an enum
{
switch(Level)
{
case Level1:
{
this.objects = LevelData1.GetObjects();
this.enemys = LevelData1.GetEnemys();
etc..
etc..
break;
} //close case

for all levels an case of course

} //close switch
} //close function


Where LevelData1 is an static class that contains the info (Each level has one). Where u say use eventually a text file to get the info.

Anyway, that still give me the same problem that i got a lot of lists that dont contain info and still need to check all.

------------------

Anyway to answer on cabbar, I understand how base classes work, virtual and override also. Now i dont understand something in ure code, like ermm:

"virtual void UpdateLevel(Ingamestate* state) = 0;"

= 0? I didnt even know u can put an equal sign behind a function, what does it do?

Anyway, i think i get ure idea, u mean like the ingamestate has some checking whats the current level and then initialize the good level and let the Level Class do the updating and rendering right? Please tell me if i understand u wrong?

//edit
or do u mean more like an interface class.. since u say the base class but how u explain it look a bit like an interface.. anyway i have a look at google at Abstract factory and builder design patterns

Greets

[Edited by - mlegend on August 3, 2007 4:46:54 AM]

Share this post


Link to post
Share on other sites
Hey

I took a look at it and yes this is what iam looking for.
I will have to edit my project kinda much tho but that ok.

thnx a lot,
Greets

Share this post


Link to post
Share on other sites
To expand on what Endar wrote, the more levels your game will have, the more reason you have to make levels data-driven.

All your levels have things in common. They all have a map, some objects here, some enemies there, and so on. You could, as you're doing right now, write that all in code. However, that means you'll have to write a lot more code, and every time you change a level, you'll have to recompile your game. When tweaking levels, that can get tedious pretty quickly, depending on the compile times.

You could also create level files that contain the same object and enemy data, and load them into your game at run-time. This means you don't have to recompile your game - this also means you can modify your levels on any other computer, so if you ever need someone else to do level-design for your game, he doesn't need to bother with the code. This also keeps your code smaller, cleaner, easier to maintain and to manage.

There are more things you can do, too, such as storing the name of each level in it's own file, and storing the filename of the next level, and many more things. This gives you a lot of flexibility. It may cost more work from the start, but usually pays off in the end.


As for having many different lists of objects, why not create an uniform object interface, and store all objects in a single list? Say, Enemy1, Enemy2, Object1 and Object2 all implement the GameObject interface (or derive from a base class, whatever is more appropriate in this case). You can then have a list of GameObjects and simply manage that list only. Voila.

Share this post


Link to post
Share on other sites
Hey,

To go in onto what u say again. I was wondering if i put all objects in one list and manage that. It look good at the first hand, but on the other hand it give me a question.

Lets say i have 2 enemy objects, EnemyNinja and EnemyBomb stored in 1 list. Then i still need to do the check for every object to see if its a ninja or a bomb. And then after do the cast on that object to do the objects specific functions right?

So it might save up memmory from initializing a lot of different lists but the code still need to do the checks and now even object casts so my game will go run slower or not?

like if you do

-- List<EnemeyNinja> ninjas;
-- List<EnemyBomb> bombs;

if(ninjas != null)
{
foreach(EnemyNinja ninja in ninjas)
//do object specific functions
}

if(bombs != null)
{
foreach(EnemyBomb bomb in bombs)
//do object specific functions
}

which might give memmory problems soon or late, probably late since its just a hobby game but anyway..

or if you do it your way.. dont really know how to do it exact but i think u have to go perform a check and casts like

-- List<Enemys> enemys;

class Enemy
{
internal IObject object;
internal ObjectEnum objectKind;
}

foreach(Enemy enemy in enemys)
{
if(enemy.objectKind == ObjectEnum.Ninja)
{
EnemyNinja ninja = (EnemyNinja)enemy.object;
//do ninja specific functions
}
}

something like that it would be in my eyes right?
well this is ermm saving up memmory maybe but it make my game slower?..

I think its like that at least, if not then i am glad if u help my wrong thinking out of it :)

greets

Share this post


Link to post
Share on other sites
Why would you need to cast? Those objects should know what to do themselves, that's why you wrote a class for them in the first place. Memory and performance aren't really the issue here. Unless you've got proof that they're an issue, and that this is the cause, it's not something you should worry about. The design of your program is what's troublesome right now. If you treat every different object in a different way, then you're duplicating things, because both that objects class, and the list update code contain code specific to that object. It'll make your code harder to manage, and messy code isn't fun to poke around in - at least I've found it to be demoralizing sometimes. ;)

The idea is to create an uniform interface for all these objects. A few functions, like Update() and Render() should probably suffice. Within these functions, each object executes it's own specific code.

Share this post


Link to post
Share on other sites
Take a look at this structure (I'll write it in java pseuco code, haven't used C#):


public interface WorldObject {
public void update();
}

public class Ninja implements WorldObject{
public void update() {
// Ninja specific code.
}
}

public class Bomb implements WorldObject{
public void update() {
// Bomb specific code.
}
}

// Then in game loop:
List<WorldObject> list; // Has all world objects.
for (WorldObject obj: list) {
obj.update();
}



This will run the specific code for each type of object and (Someone correct me if I am wrong) C# will find the correct implementation of the function.

- David

Share this post


Link to post
Share on other sites
Hello again,

i understand what u mean and i tought this wouldnt possible because the ninja throws shurikens and the bomb dont. (shuriken is just a kinda star that ninja use as weapon, for the ones dont know)

Now i had the list<shurikens> in the ingame state class itself. And added the shurikens fromout there. Also checked if he had to throw a shuriken with a function in the ninja class. like:

foreach(ninja in ninjas)
{
ninja.update();
if(ninja.hasToThrow())
{
shurikens.add();
}
}

foreach(shuriken in shurikens)
shuriken.update();

So i was a bit stuck in my mind that i had to cast the objects to get this all done. but while i was reading the java code i was thinking i could just add the shuriken class in the ninja class itself and update fromout the ninja class itself.

I really notice i got a lot to learn from how to design/build up/structure (dunno how to say hah) my code.

Thanx in advance guys you rly helped me out
Greets Martin

Share this post


Link to post
Share on other sites
Assigning functions to 0 is for enforcing derived classes to implement those methods in C++. (c# uses interfaces for that functionality if i'm not mistaken)

Making the base base level class abstract or concrete depends on your needs. Each derived class updates/renders itself, so there's no need to do the checks.

Changing your code to use design patterns is definitely worth it. It makes your code more readible (by those who know about design patterns and by you - a week later ;) )

Share this post


Link to post
Share on other sites
If game objects can create other game objects, then they might want to know about your object manager (the Ingame state class). Give Ninjas a reference to this manager when you construct them, and whenever your Ninja throws a Shuriken, it calls the object managers AddGameObject(...) function, passing in the new Shuriken instance. The object manager adds it to the list of game objects, and voila, the new shuriken is live and kickin'.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this