Level creation, management, loading etc.

Started by
7 comments, last by Asheh 18 years, 8 months ago
Hey everyone. I'm currently working on a BreakOut clone or something similar as a next step up from Pong. The main hurdle that I have yet to overcome is how to deal with levels. For example, say I wanted three separate levels with different layouts, backgrounds, colors etc. How would I be able to store this information in another file and then load it into my main program? I'm assuming you would use the file I/O system to somehow read in the information and then process the game based upon that information, but I'm not quite sure how that would work. Any help would be appreciated. Thanks,
Advertisement
Look at your level structure: you want to represent the level when it starts:

Level +-> BrickList |    +-> Number of bricks |    \-> Bricks (varying number) |         +-> Initial position |         +-> Color (or texture, or whatever) |         +-> Solidity |         \-> Contents (the powerup that is dropped) +-> Player |    +-> Initial position |    \-> Initial size +-> Game information |    +-> Filename of next level |    +-> Background texture/color |    +-> Music |    \-> Other housekeeping information \-> Misc values      +-> Ball speed      \-> Name/Description of level


The above picture represents the data structure of your game when it is running and about to give control to the player.

Loading/saving is therefore a simple matter of reading/writing data to/from the file.

The "bottom" data, such as Level->BrickList->Brick(18)->Solidity, can be read/written using existing functions (for instance, if solidity is an integer, read or write it as an integer.

Once you have a function to save/load all the data contained in a node (such as Player, or Brick(18)), you can write the function to save/load that node. For instance, to save BrickList:

write(Number of Bricks)write(Brick[1])write(Brick[2])...write(Brick[Number of Bricks])


And to load, use the symetrical code:

read(Number of Bricks)read(Brick[1])...read(Brick[Number of Bricks])


After a few code writing, you'll end up with a function to load/save the level. That's it: create a level in memory (maybe using an editor), write it to file using the function, the read it when you want and let the game start.
What I'm not understanding is how to represent a level, with all of it's attributes, in a separate file. For instance, if I want to keep track of the bricks through an array, how would I initialize that array in a separate file? If I'm just using the main program to first write the level information to a file and then loading back from it, what's the point? I would understand how to do this if I was just writing to a file and then loading the information back, but that's not what I'm trying to do here. I could always store the level information in an instance of a Level class, but that is missing the point of loading and saving files.

Basically what I'm not understanding is how to represent a level, with all of it's attributes such as the array of bricks, background color etc, in a separate file. Take the array of bricks example from before. How would I represent this array, which is already initialized with the layout of it's particular level, in a separate file and then load that file in and be able to act on it?

Sorry that I'm not understanding here, but thank you for taking the time to help. I really appreciate it.
In a file, there's nothing but raw bit data. You don't initialize arrays, you don't find classes or other data: it's just bits. You could open the same file as a text file and it would display the data as text (although it would be gibberish) or as raw bitmap data or as whatever. As a matter of fact, you don't represent something in a plain binary file.

What you store in the file isn't a level, or an array of bricks. It becomes a level, or an array of bricks, when you load it from the file. But in the mean time, it's just a series of bytes.

When you hear about "file formats", it is not related to the data inside the file, simply because the data in a file can correspond to several file formats (plain text, html...). What people describe with file formats is the saving and loading procedures used to write and read human-understandable data (levels, arrays of bricks) to and from a file.

Quote:If I'm just using the main program to first write the level information to a file and then loading back from it, what's the point? I would understand how to do this if I was just writing to a file and then loading the information back, but that's not what I'm trying to do here. I could always store the level information in an instance of a Level class, but that is missing the point of loading and saving files.


Why limit yourself to reading/writing a level class? I never even mentioned the word "class" in my post. What is important is not the actual implementation in your game, but rather the structure of the data that you manipulate. Look at the data hierarchy in my previous post: in the game, this hierarchy is represented by classes that interact with each other and actually make the game work: bricks break, the pad picks up powerups, and so on. But this is not apparent in the data hierarchy, which only represents data, not interaction. In the level editor, you would have the same data hierarchy, but it would be represented by different classes: bricks can be created, moved, painted, the player can't move and neither does the ball.

What ensures you that the same data that is written to a file by the editor will also be read from the file during the game is the fact that you used in both cases the same hierarchy. Same hierarchy of data means that you access the data to the file in the same way in the editor and in the game, same way of access means that the same data is present in both places.
If you want to create something fairly basic and simple, you can just store your levels as text. In the future you'll probably want to move on to something more advanced, but using text is fine for a beginner, and is something a lot of people do. It will of course depend on exactly how your game is set up, but I'll discuss a brief little example and hopefully that will give you some ideas to try out.

Now, first we think about what information needs to be stored for a level. For a simple clone of BreakOut this could include:
-Background colour (or alternately an image you'd like to display)
-Locations of bricks
-Locations of powerups

Now we need to think about how to store this in a file. The background colour only needs to be stored once (or the path to the image if you wanted to do that), and the locations of the bricks could be stored as coordinates. Each entry for a brick could have a variable saying what type of powerup it contains (if any).

So, the background colour or image path is unique for a level and only needs to be read in once. We'll probably want to know this before we draw any bricks in any case, so we'll put it up the top of the file. If it's a colour, we could simply write the 3 RGB components of the colour to the file:
255 0 0

With this example, the background of the level is red. We just write out the colour in the simplest fashion possible. If colours are represented in your game differently than this then you could instead use whatever method your game uses. For example, if your game uses Hex colour codes for example (I know it probably doesn't, but just as an example...), you could write the following to the first line of your file:
#FF0000


Again, we have a level with a red background. If you had an image as the background of the level in your game, you could instead write the path to the file into the first line of your level file.

Now, onto the bricks. For each brick, we want to store a pair of coordinates, as well as a variable telling us what type of powerup (if any) the brick contains. That information could be layed out in a file as follows:
x y powerup


Where x represents the x-coordinate of the brick in question, y represents the y-coordinate, and powerup is an integer representing the type of powerup contained in the brick (if the value is 0, there is no powerup). So an example brick at coordinates (10,17) containing a powerup of some description could be:
10 17 1


Onto reading this data in. We'll obviously have multiple bricks, and we may not know how many there are on the level before we open the file, so we need to store that as well. It's a single value we can store as an integer, so we'll put it at the top of the file after the background colour (or image path). This leads to the following potential design for the file format:
<background colour><number of bricks><data for each brick>


As a sample level, with a solid blue background and 3 vertically aligned bricks (with the center one containing a powerup of some sort, the second type in this case) we could have something like the following:
0 0 255310 10 020 10 230 10 0


Which just to make sure you understand what I'm saying is:
0 0 255   < The background colour of the level, stored as RPG values (in this case blue)3         < The number of bricks on the level10 10 0   < brick #1, at position (10,10), with no powerup20 10 2   < brick #2, at position (20,10), with a type-2 powerup30 10 0   < brick #3, at position (30,10), with no powerup


If you do something along those lines (but adapted for whatever other/different values you might need to store) you should have a simple file detailing the layout of your level that can be read in and out of your game and/or a map editor and even modified/created by hand if you'd like (saves the effort on creating a map editor if you only want a few levels).

When you export this type of data (from your map editor after creating the map, BrickOut normally doesn't have a save function in game), you simply write the data out as text with each seperate piece of information on it's own line, and spaces (or some kind of marker such as a comma if you'd like) dividing data stored on the same line (such as all the information for an individual brick).

To load the data in, you retrieve the data in the expected order. Load in the RGB values from the first line as text, convert the text back to a numerical datatype, and use it when you're drawing your level. Load in the number of bricks from the second line and use it to size the array (or whatever you're using) to store the bricks in, as well as in a for-loop which reads in the remaining lines containing the brick data.

Sorry for the long and somewhat rambly post, but hopefully I've explained that well enough to give you an idea of what to try out. It's a very simple method of storing level data, but it should suit your needs for now. Good luck with it, and feel free to ask if you need more help. [smile]

- Jason Astle-Adams

Ok, I understand much better now. The only thing that I'm unsure about is the level editor you guys keep mentioning. I know I should probably know this, but the level editor is something that I create, correct? And how does this level editor relate to my level data files and my main program? For example, the level editor reads the data from the data files and then creates the needed classes and variables and background colors and whatever else is needed for the program. Then how is the information from the level editor used in my main program?

Sorry for being such a newb here, but I think I almost understand it all now. Thanks for all your help guys, I really appreiciate it.


EDIT: Also, do you guys have any resources you could recommend that deal with this topic? I would love to have some kind of tutorial to refer to if one exists.
Your level editor would be a utility program which you program yourself, yes. There are some generic general-purpose level editors out there which you can adapt to suit your game (Mappy for example), but this are generally better suited for slightly more complex games such as overhead or side scrolling games. Aside from which, it's good practice and a good learning excersize to write your own level editor at least once.

Alright, so first you design how you want your file format for levels to work, which I talked about in my post above. Your level editor is a utility for creating those files, so the requirements for it are something along the lines of:
-Display an empty level
-Edit an empty map (i.e. create a new level)
-Save your level to file
-Optionally load in saved level files for further editing

If you have a simple level format stored as text like I described above, you could actually just create levels using a plain text editor (notepad!), but if your levels are going to be fairly complex then it might be a lot of work to type in all the values by hand -- this is where a level editor comes in. Your level editor must have some way of creating new bricks and modifying thier position. It must be able to set what powerups are contained in a brick (if any). It must also be able to set the background colour (or image if you chose) of the level somehow.

Once the user (which is probably you) has created a level using the editor, it writes out all the values to the file as plain text. When the game is played, it loads in the plain-text file for whatever level the player is currently up to, puts the values into the appropriate variables, and displays the level for the player to play.

Hope that helps you - try to create something based on that and see if you can get it working, but if you have trouble keep asking for help until you understand.

- Jason Astle-Adams

Oh, ok, I understand it now :) It seems so simple now that you've explained it to me. I guess it was one of those things that just "clicked." Thanks again for all your help, I really appreciate it.
For my breakout clone, my levels were as follows:

2
2 2
6
2 2 2 2 2 2
6
2 3 3 3 3 2
8
2 3 0 3 3 0 3 2
6
2 2 2 2 2 2
6
2 3 3 3 3 2
2
2 2

each line contained
------
number of bricks
brick index.

The file loading code was about 5 lines =)

Real simple.

This topic is closed to new replies.

Advertisement