2D Level Loading and Storing

Started by
11 comments, last by FrancisXavier 14 years, 1 month ago
I'm curious, what method do you typically use to store and load your 2D Levels or other game configuration data? I've typically used a simple .txt file with a bunch of coordinates and specs written out that my loader parses and builds the levels from. I've also used Java's Serializable interface to save fully loaded levels and objects. I'm currently experimenting with using a .xml file to store entries and attributes and loading the data through an xml parser. I know this is probably not the best way, but I'm experimenting. What does everyone think?
Advertisement
I just use xml myself usually - it's not as space efficient as a custom binary format, but I find it copes better with format changes which occur as you add new features and functionality. Most of the time you can just add new elements and attributes and make your level loader substitute defaults if they're not found.

If you're really worried about file size and loading time then you can always convert the xml files into a custom binary one when your game is nearly finished (or support both and keep the binary export as part of your build process for actual releases).
I'm developing a 3D gaming engine and I use XML as my file format for everything. I wrote a plug-in for MilkShape that exports all my geometry in XML. Sure I could do it in binary but there's nothing like being able to look at all your data if you need to. Using XML to hand code other types of information is very useful. Your really don't want to code data into your game. I may switch the geometry part over to binary in the future. But, at this point, speed is not an issue.

I wouldn't worry about file size. XML is a text file so it compresses well. Art and sound is what will fatten your game.
Quote:Original post by howie_007
You really don't want to code data into your game.

I got away from hard-coding data into the game rather quickly. The stuff is a nightmare to maintain and update.

I'm starting to like the xml method of storing data (even though I'm not even halfway done with the first game I'm building that uses it). It's tedious at first, but modular and easily altered, and file size was never an issue.

I was just wondered what methods other game programmers use.
Quote:Original post by joedono
I got away from hard-coding data into the game rather quickly...

...It's tedious at first, but modular and easily altered, and file size was never an issue.
That's what I like to hear.

Below is the output of a simple box from my MilkShape XML exporter

<?xml version="1.0" encoding="utf-8" ?><!-- Export: Left handed System --><mesh>	<vert_list count="8">		<vert x="-4.984375" y="5.015625" z="-5.015615" />		<vert x="-4.984375" y="-5.015625" z="-5.015615" />		<vert x="4.984375" y="5.015625" z="-5.015615" />		<vert x="4.984375" y="-5.015625" z="-5.015615" />		<vert x="4.984375" y="5.015625" z="5.015617" />		<vert x="4.984375" y="-5.015625" z="5.015617" />		<vert x="-4.984375" y="5.015625" z="5.015617" />		<vert x="-4.984375" y="-5.015625" z="5.015617" />	</vert_list>	<uv_list count="4">		<uv u="0.000000" v="0.000000"/>		<uv u="0.000000" v="1.000000"/>		<uv u="1.000000" v="0.000000"/>		<uv u="1.000000" v="1.000000"/>	</uv_list>	<vert_norm_list count="10">		<vn x="0.000000" y="0.000000" z="1.000000"/>		<vn x="1.000000" y="0.000000" z="0.000000"/>		<vn x="0.707107" y="0.707107" z="0.000000"/>		<vn x="0.707107" y="-0.707107" z="0.000000"/>		<vn x="0.000000" y="0.000000" z="-1.000000"/>		<vn x="-0.707107" y="0.707107" z="0.000000"/>		<vn x="-0.707107" y="-0.707107" z="0.000000"/>		<vn x="-1.000000" y="0.000000" z="0.000000"/>		<vn x="0.000000" y="1.000000" z="0.000000"/>		<vn x="0.000000" y="-1.000000" z="0.000000"/>	</vert_norm_list>	<face_group count="12">		<face_list count="12" mIndex="0">			<face v1="0" v2="2" v3="1" uv1="0" uv2="2" uv3="1" vn1="0" vn2="0" vn3="0"/>			<face v1="1" v2="2" v3="3" uv1="1" uv2="2" uv3="3" vn1="0" vn2="0" vn3="0"/>			<face v1="2" v2="4" v3="3" uv1="0" uv2="2" uv3="1" vn1="1" vn2="2" vn3="1"/>			<face v1="3" v2="4" v3="5" uv1="1" uv2="2" uv3="3" vn1="1" vn2="2" vn3="3"/>			<face v1="4" v2="6" v3="5" uv1="0" uv2="2" uv3="1" vn1="4" vn2="4" vn3="4"/>			<face v1="5" v2="6" v3="7" uv1="1" uv2="2" uv3="3" vn1="4" vn2="4" vn3="4"/>			<face v1="6" v2="0" v3="7" uv1="0" uv2="2" uv3="1" vn1="5" vn2="7" vn3="6"/>			<face v1="7" v2="0" v3="1" uv1="1" uv2="2" uv3="3" vn1="6" vn2="7" vn3="7"/>			<face v1="6" v2="4" v3="0" uv1="0" uv2="2" uv3="1" vn1="5" vn2="2" vn3="8"/>			<face v1="0" v2="4" v3="2" uv1="1" uv2="2" uv3="3" vn1="8" vn2="2" vn3="8"/>			<face v1="1" v2="3" v3="7" uv1="0" uv2="2" uv3="1" vn1="9" vn2="9" vn3="6"/>			<face v1="7" v2="3" v3="5" uv1="1" uv2="2" uv3="3" vn1="6" vn2="9" vn3="3"/>		</face_list>	</face_group>	<material_list count="1">		<material defuse="game_art/top.png" alpha=""/>	</material_list></mesh>


The xml is much more manageable when you make use the attribute's tags.

Below is a hand coded xml for loading my light information

<?xml version="1.0" encoding="utf-8" ?><lightList>  <light name="point" type="point" castShadow="yes">    <defuse r="0.6" g="0.6" b="0.6"/>    <specular r="0.0" g="0.0" b="0.0"/>    <ambient r="0.0" g="0.0" b="0.0"/>    <position x="-30.0" y="0.0" z="-25.0"/>    <direction x="0.0" y="0.0" z="0.0"/>    <properties range="500" falloff="0"/>    <attenuation attenuation0="1.2" attenuation1="0.0" attenuation2="0.0"/>    <spotlight theta="0" phi="0"/>  </light>  <light name="dir" type="directional" castShadow="no">    <defuse r="0.6" g="0.6" b="0.6"/>    <specular r="0.5" g="0.5" b="0.5"/>    <ambient r="0.0" g="0.0" b="0.0"/>    <position x="0.0" y="0.0" z="0.0"/>    <direction x="1.0" y="-1.0" z="1.0"/>    <properties range="300" falloff="150"/>    <attenuation attenuation0="1.5" attenuation1="0.0" attenuation2="0.0"/>    <spotlight theta="0" phi="0"/>  </light>  <light name="spot" type="spot" castShadow="no">    <defuse r="0.5" g="0.5" b="0.5"/>    <specular r="0.5" g="0.5" b="0.5"/>    <ambient r="0.3" g="0.3" b="0.3"/>    <position x="20.0" y="0.0" z="60.0"/>    <direction x="1.0" y="0.0" z="0.0"/>    <properties range="40.0" falloff="5.0"/>    <attenuation attenuation0="1.0" attenuation1="0.0" attenuation2="0.0"/>    <spotlight theta="1.0" phi="0.5"/>  </light></lightList>


Just to show you some examples.

[Edited by - howie_007 on March 10, 2010 11:44:47 AM]
I moved from flat files to SQLite database files a while ago for everything and never looked back. It is fast, portable, easy to embed into just about any program (bindings to C/C++/C#, java, perl, ruby, php and more) and uses very little resources.

I would imagine it has some performance gains over an XML file for reading and writing in particular since it doesn't always have to rewrite the entire file when you add more data.

I use SQL daily at my job so this was an easy transition for me. I never liked traversing XML documents and a database just makes sense to me. It takes a little planning to get right (think of columns as attributes for a class/struct and rows as instances) but in the end it is worth it.

One argument I usually get for suggesting this is that it isn't a human readable format. I usually point them towards one of the many SQLite GUI apps such as SQLite Studio or SQLite Administrator that allow you to browse and modify the schema and data in a way that is much easier and safer than notepad and XML IMHO.
Evillive2
Quote:Original post by joedono
I'm curious, what method do you typically use to store and load your 2D Levels or other game configuration data?


My current project is heavily scripted in Lua (the gameplay portions anyhow) so for configuration data, i just use a lua file that looks something like the below:

--------------
--Graphics
--------------

ScreenWidth=1024
ScreenHeight=768

--------------
--Input
--------------

MouseSensitivity = 0.8

Believe it or not, my map files are also just lua files. I have an editor, and my game is a 3rd overhead view RPG, but to load a map file it executes the lua script, and to save a map file, it just loops through the objects of the world and writes out the lua commands to load them and set all their properties correctly. So a portion of my map files might look like this:

Music_Play("./Audio/Music/Intro.mp3");

ChairModel = Model_Load("./Art/Models/Furniture/Chair.ms3d");
Model_SetScale(ChairModel,0.5,0.5,0.5);
Model_SetPos(CharModel,100,200,50);
Model_SetRot(ChairModel,0,13,0);

etc (:
I'd use a format like this

Map_namesize of map(x and y dimensions)Layer                Position               Image001                  0x0                    "./gfx/tile.bmp"001                  0x1                    "./gfx/tile.bmp"


That is how I'd do it simple, and easy to understand
In my current project I have a single interface for loading levels and animation data and my current implementation is a simple "plain text" loader. I have used XML previously and it works quite well even though it bumps the file sizes up a little bit.

If you want to have something that has structure (like XML) but less weight I'd suggest you look at using JSON. It's a little bit leaner than XML and can easily support name/value pairs as well as arrays.
for level files I have a custom xml looking format

objectname{  x = 123.0;  y = 300.0;  vel = {2.0,3.0};  varname2 = 4|[2,1,3,1];  varname3 = "Hello World";}


so far it supports separate objects, nested objects, arrays of any type (from objects to strings to arrays of arrays), and strings without any character restriction, also C-style comments .
I prefer it over xml mainly because xml has certain restrictions about what characters may appear in a a string or other places, I can also create other types of data that the default parser wouldn't be able to parse as long as it's encased in a pair of matching < > (the custom parse function must return the offset of the > that ends the custom object/data, that way it can allow for ANYTHING to be stored inside without limitations) eg:

objectname{  custom = < "this is a string":varname=var1:  var2><var1>>;//the parser function must return the offset of the > ending the custom data};


Of course it has a limitation: the variable names aren't really used but are necessary, and are there only for the purpose of viewing. I use this only when testing the game. Later I move onto the binary format following the same rules but discarding all the unused information.

This topic is closed to new replies.

Advertisement