views:

609

answers:

12

Hi all. For some time I've been making a 2d tile based sim game, and it's going well! Thanks to this site and its kind people (You!), I have just finished the path-finding part of the game, which is fantastic! THANK YOU!... Anyway, to the question.

At present, the test level is hard-coded into the game. Clearly I need to re-work this. My idea was to have all variables in my Game class saved to a text file in various ways. I could also write the details of each level into a file to be loaded for a level. My question is, should I be using just a text file, or using XML? I understand what XML is basically, but I don't really know how I would use it in conjunction with JAVA, or why it's preferable or not over a plain text file. I had a bit of a google, and there are WHOLE books on XML and JAVA! I can't see I need to know EVERYTHING about how to use XML with JAVA to make this work, but I do need to know more than I do.

Thanks in advance for your help with this.

Edit: I will try several of the ideas here until I find the one that works the best, and then that will be chosen as the answer.

Edit: Chose xStream. Easy and simple!

A: 

It depends on how much data you need to save, and how do you need to retrieve it.

XML can be easily translated to java POJO's with several libraries, so that is an advantage. Also, you will find that it's easy to learn and use, just try some tutorials.

But if you need to save a lot of data, you can consider using an embedded database, or a separate sql server, depending on your application.

Mercer Traieste
Not alot of data being saved really, its a small 2d tile based sim game.
Relequestual
+2  A: 

You're using files for an internal purpose. The short answer is, as long as the file format fits your purpose, it's fine. You do want to do what you can to insure that the format is clear, as simple as possible, and extensible. The most important bit here is to extract the data reading and writing to a single point in the code that's responsible for reading and writing the file format.

The common formats are common because they're simple and well supported - you don't need to write special code to parse files (properties files, basically just a list of key-value pairs, and xml files -think of xml files as a way of writing arbitrarily deep nested dictionaries).

Steve B.
Thanks for this. I know how to read data in and out of text files, have been learning over the last year or so. Thing I have no problem in building up such a file, saving it and then loading it back in again... I hope.
Relequestual
+2  A: 

If it's purely a tile based game, a straight text file is probably the way to go.

You're probably going to want fixed width ints, space-delimited with newlines after each row. Easily readable, and easy to parse without the need for an XML library.

Edit:

One important piece of advice:

Whatever you decide to do, encapsulate it! Make a reader interface that takes generic input stream and returns (or populates) whatever your grid structure is. Have a writer interface that takes a grid structure and a generic output stream and dumps the data to that output stream. You'll thank yourself later should you ever change your mind about how you want to implement the file, or if you want to add network play, etc.

patros
yeh, I think I agree with you. I was talking it over with a friend who suggested XML, just had to see what Stack had to say about it.
Relequestual
+1  A: 

It depends on your needs of course, but XML format gives you many benefits and I would probably chose XML myself in such a project.

  • It can be automatically checked/verified by tools to make sure it is correct and according to the rules you set up.
  • There are existing libs for Java to parse, read and update XML-documents.
  • The format is easily extendible for future versions of your program but still easy to keep backwards compatibility
  • Its easy for others to read and understand your files if they are XML rather than some specially adapted text-format
Brimstedt
+4  A: 

For a 2D tile-based game, XML is probably overkill. XML is good for storing hierarchical data and/or marked-up text, but it sounds like you just need a way of encoding a 2D grid of tile settings, which is far easier to do with a plain old text file.

Just have each line be a row of tiles, and decide how many characters you want per tile (probably one or two would be fine). Then decide how to represent the objects in your 2D world with characters in the text file.

In SokoBean (a game I wrote over 10 years ago, so not what I'd call my best work, but whatever) I used text files like this one. In addition to being easier to parse than XML, you can also use a plain old text editor as a level editor.

Laurence Gonsalves
Thanks for this, interesting little game!I don't think I could implement the same sort of text file for a game this complex. This is my second game in any programming language, so I'm learning a lot as I go!
Relequestual
+1  A: 

If you have the game state in an object (e.g. a HashMap, or perhaps an object of your own design), then you can write it out as an XML file trivially using XStream, and then read it back to a new object using XStream again.

There's a two minute tutorial to show you how to serialise/deserialise. It'll handle most objects without any difficulty - you don't need to implement or specify any particular interface. Nor do you need JAXP, SAX, DOM etc.

Brian Agnew
wow, this looks really interesting! If it works as you say, I think this may be the answer! My intensions were to include everything in an object I created called Game.
Relequestual
That should work fine. The only problems I've encountered are w.r.t serialising inner classes, at which point it blows up. But otherwise it's pretty trivial
Brian Agnew
I'm not sure what you mean by w.r.t serialising inner classes... could you explain please?
Relequestual
If you serialise an inner class, there's an implicit (hidden) reference to the outer class. So when you serialise the inner class, the serialiser then tries to serialise the outer class too (which isn't what you expect). It only messes you up if you inadvertently try and serialise something that you thought was outer, but is in fact (inner).
Brian Agnew
ok thanks for explaining.I've been reading up on serialization.Am I right in understanding that if I'm using an object class that I made, it can't be auto serialised? Do I have to add the method for each class I wish to use? Or is the whole point of XStream so you can use your own objects and don't need to write code for serialization?
Relequestual
You can serialise your own objects without any further work. You don't need to implement interfaces etc. You *can* override how it creates XML tags, but you don't need to.
Brian Agnew
That looks awesome :) ty
Relequestual
A: 

If you are the only person who is going to modify the file, use any format you want. However, if you expect users or testers or other people to modify it, use XML. One big advantage of XML is that it's a standard format that a lot of people (even a lot of non-programmers) know how to code in.

eeeeaaii
A: 

I only consider using XML if there's some part of the XML ecosystem I need: validation, transformation, automatic serialization/deserialization, etc. But I know what all those things are, and I know how to use them to pretty good effect.

If you don't - and from the tenor of this question I'm guessing you don't - then the real question is "should I learn all this stuff just so that I can save my information in an XML document?" and the answer is "You almost certainly should not."

Robert Rossney
+1  A: 

In terms of your own stuff, especially games, XML is overrated. If you were working in a large company where other people need to view the text of your files, XML might make sense, but even in that case you would probably have a level editor written that would do everything for you.

I would recommend either having a simple text file with your own convention, or using java.io.ObjectOutputStream and java.io.ObjectInputStream to just write your data directly to a data file (if you have a lot of information or objects) or java.util.Properties to write your data (if you only need to write primitives).

A lot of the people above reference how XML is nice because it has "automatic serialization," but I really don't think that's worth mentioning when working in Java, because both methods I listed above are also automatic, but on a much more advanced level.

Also don't forget that representing a 2D tile map using XML tags is very unintuitive, whereas just writing them line by line in a character file is fairly easy to read and write.

ex.)

WWWWWWWWWW  
WSWWWWW EW  
W W K WW W  
W W   WW W  
W WW WWWDW  
W  X     W  
WWWWWWWWWW

You could do something like the above, where W is a Wall, S is Start, E is Exit, K is Key, D is Door, and X is a monster. Exactly where everything lies and how the level should be set out is very obvious, even as a text file.

I've used text files among plenty of professional game projects. In fact, I've only used XML when I've done contracting work for somebody, because XML looks "more professional" even though in the majority of cases it's used it is unnecessary and just a waste of space that overcomplicates things.

Another example:

SpawnFrequency 0.1 20.5
HealthPoints 5
Stats 12 500 30 10 11

You can imagine whatever else might happen. Then as you read the file into Java, simply use BufferedReader.readLine() to get each parameter, then String.split() to get an array of all the values for that parameter. Then a large switch statement or if/else grouping comparing the first value in the split array will determine which parameter you've actually read. When you get to this point, you're approaching XML's usefulness, but it still might be overly bloated for this use. XML, however, could help to explain what some of those mysterious values could be:

The above in XML:

Or maybe like this:

`<GuyStuff>`  
    `<SpawnFrequencyMinimum>0.1</SpawnFrequencyMinimum>`  
    `<SpawnFrequencyMaximum>20.5</SpawnFrequencyMaximum>`  
    `<Health>5</Health>`  
    `<Strength>12</Strength>`  
    `<Agility>500</Agility>`  
    `<Stamina>30</Stamina>`  
    `<TechnoWizardry>10</TechnoWizardry>`  
    `<JavaSkillz>11</JavaSkillz>`  
`</GuyStuff>`

But once again when you start getting to that complexity, you might as well just start using java.io.Serializable because it's very easy.

EDIT Here's a Serializable example.

public class MySaveData implements java.io.Serializable //Serializable doesn't need any methods implemented, it simply says, "hey Java, my object can be written to a file."
{
    float data1;
    int data2;
    Object data3;
    //BufferedImage data4; //Note that in order for an object to serialize, it can't contain any data members that are not Serializable, so this would be illegal.
}

import java.io.*;
public class DataReader
{
    public void saveData(File loc, MySaveData obj1, MySaveData obj2, MySaveData obj3)
    {
        try
        {
            //You can use any type of OutputStream to create an OOS, so you can for
            //example use one when you're connected with Sockets or something similar.
            ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(loc));

            //Writing objects is tremendously easy, and so are primitives.
            //Note that the order you write them in is the same order you will read them.
            os.writeObject(obj1);
            os.writeObject(obj2);
            os.writeObject(obj3);
            os.writeDouble(someValueINeededToWrite);
            os.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public void loadData(File loc, PlaceToPutData place)
    {
        try
        {
            //ObjectInputStream follows the same rules as OOS mentioned above.
            ObjectInputStream is = new ObjectInputStream(new FileInputStream(loc));

            //Remember to read your data back the same order you wrote it.
            place.obj1 = is.readObject();
            place.obj2 = is.readObject();
            //If you don't want one of the objects for some reason and want
            //to get something after it, you can just read the next one but not use it.
            readObject();
            place.value = is.readDouble();
            is.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

Typically your File would be something like this: new java.io.File("/Documents/MyGame/MyDataFile.whateverIFeelLikeAsLongAsItsConsistent").

Eli
I have only used java.io.outputstream and inputstream. I'm still very new to java, so haven't heard of the others you mention, and so have no idea what they are or how to use them. I will have to look into them now! If I have my own objects in objects in objects ect, and all the game variables in a single main Game class object, would I be able to use the serializable as you so say?
Relequestual
A: 

You may think about using an embedded database like JavaDB, located here: http://developers.sun.com/javadb/

It's only 2.5MB to embed it, and you may find the ability to save all sorts of data in a structured, reliable way very helpful.

There are ORM frameworks like Hibernate which you could use to work with the data but that is probably overkill for you application. You can use straight-forward JDBC instead.

Best of luck and have fun.

Jon
A: 

Is cheating a problem? if so, then i would encrypt whetever the output is somehow. If it isn't then just output in plain text.

As far as the format goes, i'd use XML. You can do something like

<Map>
    <Tile x="1" y="1" value="2"></Tile>
    <Tile x="1" y="2" value="1"></Tile>
    <Tile x="1" y="3" value="7"></Tile>
    ...
</Map>

That will offer a nice readable format and can sztore quite a bit of data.

RCIX
Cheating is currently no problem.If it eventually became a problem, i could just encrypt the xml before save.
Relequestual
A: 

Hello,

I use a class (implements java.io.Serializable) where I store the game stats. Then I use an ObjectOutputSteam to write that class to a file. To load that class you can use an ObjectInputStream.

Martijn

Martijn Courteaux