Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (539)
Games in Android Showcase (132)
games submitted by our members
Games in WIP (603)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Working with YAML: Configuration Files  (Read 7420 times)
0 Members and 1 Guest are viewing this topic.
Offline actual

JGO Coder


Medals: 24



« Posted 2013-06-22 23:16:27 »

In game programming it's generally considered good practice to specify game information in external configuration files.
1. It gathers parameters that may be scattered across the code base into a couple of small files.
2. The external files can be easier to read, understand, and modify.
3. Modifications can be made without changing (and having to rebuild) the source.

In the Java world XML is the typical choice although JSON, properties, INI, and other formats are also used. Another, less well known format, is YAML(YAML Ain't Markup Language). YAML is a structured text format which provides a viable alternative to XML and JSON as means of specifying configuration data, particularly when the files are being edited by hand.

This article gives a brief overview of YAML, with a focus on using it as a means for writing configuration files.

There are two main libraries for working with YAML in Java; snakeYAML and YamlBeans. Both have fairly equivalent functionality, and at the bottom of this article is a simple class that uses snakeYAML to read in a yaml file, convert the YAML result tree into a simple set of nested maps, and write the output to the console. Both snakeYAML and YamlBeans provide additional functionality such as loading YAML data directly into POJOs and walking the YAML parse result tree.

Here is a simple YAML file:

# YAML comments start with a "#"

# Properties and values are separated by a colon.
# There has to be at least one space between the colon and the value.

menuFontFamily: Arial
menuFontColor: blue       # Blue is my favorite color
menuFontSize: 14pt
menuBackgroundImage: menu.png
tileMenuBackgroudImage: true



Reading this in via the code at the end of the post gives us the following following simple map:

{menuFontFamily=Arial, menuFontColor=blue, menuFontSize=14pt, menuBackgroundImage=menu.png, tileMenuBackgroudImage=true}

So for cases where all you need is a simple set of key/value pairs, a YAML file is not any more verbose than a properties file. Imagine what the equivalent XML might look like.


Maps

YAML uses indentation to specify hierarchical data. If we change the file to:

menu:
  font:
    family: Arial
    color: blue
    size: 14pt

  # Font and BackgroundImage need to be indented the same amount.
  backgroundImage:
    image: menu.png
    tile:  true


...and run the code again we get a series of nested maps:

{menu={font={family=Arial, color=blue, size=14pt}, backgroundImage={image=menu.png, tile=true}}}

It does not matter how many spaces you indent, as long as it is consistent within a map. Try adding a space in front of "color: blue" and see what happens. You cannot use tabs for indentation.

YAML also allows you to define multiple keys on the same line. The previous example could also be written as:

menu:
  font: { family: Arial, color: blue, size: 14pt }

  backgroundImage:
    { image: menu.png, tile: true }




Lists

Let's say we want to add to our configuration a list of sound files to load at start up. All of the files are in the same directory, and for each sound we want to specify both the name of the file and the name to be used to get the sound from the library (something like soundLibrary.getSound("PlayerDied")).


menu:
  font: { family: Arial, color: blue, size: 14pt }

  backgroundImage:
    { image: menu.png, tile: true }

audio:
   # Path is relative to the main game directory
   base-path: .\sounds\raw\

   # Each entry in the list starts with a "-" and must be at the same level of indentation.
   sounds:
     - name: Hit
       file: hit_1.ogg

     - name: PlayerDied
       file: player_death.ogg

     - { name: Miss, file: miss_target.ogg }  # We can also define a sound on one line.


This results in the following output:

{menu={font={family=Arial, color=blue, size=14pt}, backgroundImage={image=menu.png, tile=true}}, audio={base-path=.\sounds\raw\, sounds=[{name=Hit, file=hit_1.ogg}, {name=PlayerDied, file=player_death.ogg}, {name=Miss, file=miss_target.ogg}]}}


Like maps, lists can be defined on one line with list items separated with a comma and space.

sounds: [ {name: Hit, file: hit_1.ogg}, { name: playerDied, file: player_death.ogg}, { name:Miss, file:miss_target.ogg}]


There is more to YAML than what I have shown such as:
1. Support for multi-line strings
2. Anchors and References which allow nodes to reference previous nodes in the document
3. Specifying the type of values
4. Automated mapping of YAML data to POJOs.
5. Serialization of objects to YAML.


Some scattered, closing thoughts

Personally I like YAML. It keeps the simple things simple. When all I need is a flat list of properties, a YAML file has no more overhead than a .properties file. I can then add a bit of hierarchy for convenience without having to switch to a new format.

I find YAML to be easier to read and modify than either XML or JSON.

YAML's use of whitespace may welcome or annoying depending on your preference.

XML and JSON have much larger communities with much richer toolset available.

Like JSON, YAML is not as self describing as XML and more care may be required to ensure that your format is understandable from a semantic standpoint.

Unlike XML, YAML has no standard way of defining a schema and validating a document against it, although projects such as Kwalify have been developed to meet that need.


References
Official YAML site
YAML Wikipedia Page

Java libraries for reading/writing YAML
snakeYAML
YamlBeans



Simple class to run example files

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
import java.io.*;
import java.util.Map;

// Download the snakeYaml jar at: http://code.google.com/p/snakeyaml/downloads/list
import org.yaml.snakeyaml.Yaml;


public class SimpleYAMLMain {

     
   public static void main(String[] args) {
     
      // The path of your YAML file.
      final String fileName = "path\\to\\yaml\\file\\test.yaml";
     
      Yaml yaml = new Yaml();
   
      try {
         InputStream ios = new FileInputStream(new File(fileName));
         
         // Parse the YAML file and return the output as a series of Maps and Lists
         Map<String,Object> result = (Map<String,Object>)yaml.load(ios);
         System.out.println(result.toString());
         
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
}

Offline sproingie

JGO Kernel


Medals: 202



« Reply #1 - Posted 2013-06-23 00:55:25 »

It's probably worth mentioning that Jackson supports YAML with an extension library, so add this to the list of links:

jackson-dataformat-yaml
Offline gimbal

JGO Knight


Medals: 25



« Reply #2 - Posted 2013-07-10 07:23:41 »

If you are in the position where you need data for an in-memory database (or unit tests), I have used Fixy for that purpose which is incredibly easy and built on top of SnakeYAML too.

https://github.com/sberan/Fixy

That quote on the site is actually from me by the way Wink

Not many people will actually utilize an embedded database in their game, but I thought I'd mention it all the same for the rare case where someone does want to play with it.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

rwatson462 (30 views)
2014-12-15 09:26:44

Mr.CodeIt (20 views)
2014-12-14 19:50:38

BurntPizza (42 views)
2014-12-09 22:41:13

BurntPizza (76 views)
2014-12-08 04:46:31

JscottyBieshaar (37 views)
2014-12-05 12:39:02

SHC (51 views)
2014-12-03 16:27:13

CopyableCougar4 (49 views)
2014-11-29 21:32:03

toopeicgaming1999 (115 views)
2014-11-26 15:22:04

toopeicgaming1999 (105 views)
2014-11-26 15:20:36

toopeicgaming1999 (31 views)
2014-11-26 15:20:08
Resources for WIP games
by kpars
2014-12-18 10:26:14

Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!