Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have a level class that does all of the updating and drawing and everything pertaining to the level. My question is, what would be the best approach to creating different levels? Should I just write them all in this single class which just chooses what to load and do depending on the level, or should I write each level in its own class that inherits from a base level class?

My code handles switching levels through the game's state manager...

void Game::change(GAMESTATE changeTo) {
  state = changeTo;
  load(state);
}

void Game::load(GAMESTATE loadState) {
  while(!currentState.empty()) {
    delete currentState.back();
    currentState.pop_back();
  }
  if(state == TITLE) {
    currentState.push_back(new Title());
  }
  else if(state == LEVEL) {
    currentState.push_back(new Level(&levelNumber));
  }
  else if(state == CUTSCENE) {
    currentState.push_back(new Cutscene());
  }
  else if(state == GAMEOVER) {
    currentState.push_back(new GameOver());
  }
}

[edit] For this question, let's assume I want to hard code the levels and don't want to use external files.

share|improve this question
3  
The best way would be that levels aren't defined by code, but by external files that can be loaded when requested. You're level class would just load the level file and based on that create the required objects and handle the logic during play. –  Roy T. May 5 '12 at 7:46
    
Why don't you want to load from external files? –  Azaral May 5 '12 at 13:04
    
@Azaral I suspect that he wants to focus tightly on code design and doesn't want extraneous details to cloud the answers. Also, he may want to preemptively stop people from mucking around with his game flow with a quick XML edit... –  Patrick Hughes May 5 '12 at 15:34
    
@pat OK, that makes some sense. –  Azaral May 5 '12 at 15:46
    
What kind of level are we talking about? What is your gameplay? That changes what the answer is. –  Nicol Bolas May 5 '12 at 16:55
show 4 more comments

4 Answers 4

Instead of hard coding them into the game, write a routine that would load your level from an external file such as a text file. This is the best way to do it and the way you really should do it. If you are worried about your level files being changed then encrypt them or something.

However, if you really want them to remain coded into the game itself then you would not want to make separate classes. Each level acts like a level so they don't need different classes, they should all just be instances of your level class, perhaps a vector. vector<level> levels would be one example. Then you could have another variable, say int currentLevel that would be used to access the level vector (I guess it could be a regular array if you wanted).

Upon further thinking, that would also create a huge quagmire. Inheriting from a level base class would probably be better for making a hard coded level. You would declare the level stuff in a base class, then inherit this and use that to fill in the numbers. class LevelOne : public LevelTemplate something like that. You could then use the default constructor to have the program initialize all the values.

Then have an array of pointers or a vector of pointers and utilize new to make the levels.

This throws other problems into the mix though. You should really consider loading from external files.

share|improve this answer
add comment

reasons to treat each level as a separate class:

  • each level has special events in it (these usually relate to special effects sequences)
  • some abilities are not allowed in specific levels even if the character doesn't lose them (the character can double jump in level2, but in level3 they can only single jump) explanation is a story thing.

problems with treating each level as a separate class:

  • if the logic behind the levels is all the same (the 2 points above are not in effect) then all your doing is using inheritance to control construction which violates OOP practices.
  • having to worry that the correct child is being used (though this can be a moot point if polymorphism is understood)

for the actual implementation unless your game uses either of the 2 points at the beginning you can just treat the loading of each level as a different method called by your constructor. for example

// in fileIO
ifstream input; // input stream
switch (map){
case 0:
    input.open("maps/Map0.txt", ios::in);
    break;
case 1:
    input.open("maps/Map1.txt", ios::in);  
    break;
case 2:
    input.open("maps/Map2.txt", ios::in);  
    break;
case 3:
    input.open("maps/Map3.txt", ios::in);
    break;
case 4:
    input.open("maps/Map4.txt", ios::in);
    break;
default:   // generate map
    break;
}
// parse file
// construct level based on parsed file

for without fileIO: it would look about the same, but instead the input.open(...) would be replaced with a method calls that performed the creation of the objects.

I have done this conversion in a project where I was paranoid about distributing my level files, but I realized that even though yes someone could go in and modify the files, and cheat in that regard I was not selling the game, and if they broke it trying to cheat that's their dumb fault.

Though this process does work, whenever I look back at that program it just feels like overkill paranoia, and possibly even breaking object-orientation

share|improve this answer
add comment

Definitely make subclasses that inherit from the base level class. This gives you full flexibility over what happens in each level without the code becoming exceedingly complex.

While you are building this game, always take note of all code duplication and other code smells you might encounter. It might make sense for some code to be part of the base class, or perhaps some levels subclass each other or really start reading in files for level data.

Depending on how different the levels are from each other, it might make sense to do like most game studio's do and have the levels run scripts. A powerful scripting language like Lua, Ruby or Python can significantly increase your versatility when building a level. They all have libraries that make it easy to embed them in your c++ project and have access to the objects therein. Since level-loading and basic level operations don't have real performance constraints, scripting language performance is not an issue.

Also, I'm not sure what your reasons are from being averse to loading files, but are you aware that it is possible to embed files in your .exe's and .dll's? This also goes for the script files, which can even be pre-parsed to further tamper-proof them.

share|improve this answer
add comment

I assume that the level is not too complicate, but very straight forwards enough to let this to flexibly happens. The level itself should not be a type of platformer-level, or angry bird-like level. That's it, the other things in a level can be easily done through normal approach.

Then for my thought, I would go for writing specific level in its own class but inherits from the base level class. Surely each level would have something different from others such as events, new enemies, background images, available weapons / items to use, etc, in order to tackle this we should allow for specific class to override the normal (or empty) behavior of the base class through virtual function. We added these kind of functions to cover differentiation that might happens. Those virtual function usually be provided for the following cases

  • Initialization (different enemies via point info such as health point or spawn position or others AI/Gameplay related variables, different kind of resource to be used in such a level such as sfx or background image)

  • Winning/Losing condition (1st mission needs to acquire 2 coins, but 2nd needs 3)

  • Availability of weapons / items (1st mission, we won't allow to use rocket, but 2nd we're allowed)

  • Events

Last thing is that be sure to put common / core things into a base class that allow flexible use for inherited classes.

Anyway, please be warned that if one of your team or yourself have already finished creating several level-specific classes, and right after that something is changed in a base class. It may effect all its child to be updated and corrected! (I think that the approach to load a level from external file usually needs only 1 main class file and handle everything inside, so it's trading off.)

share|improve this answer
    
not just modifications to the base class, but changes to AI behaviors, GameObjects, and in some cases abilities themselves. I would think that each level being its own class should be a last resort. –  gardian06 May 5 '12 at 18:12
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.