DRY: get/set project.xml properties at runtime

I would like my code to be DRY. Currently, I use HaxeFlixel; because of the way it exposes the width/height of the game, I have to write the game width/height in three places:

  • Project.xml
  • Main game state
  • Constants file

I would like one of these (preferably project.xml) to be the single source.

Is there an API for parsing/extracting values out of project.xml? I would need the window's width and height properties.

Alternatively, is there a way to inject a value from a constant into this file? Something like (pseudocode):

window width=${com.yourpackage.Main.Width}

The easiest thing to do is read stage.stageWidth and stage.stageHeight.

If that won’t work for some reason, add this to project.xml:

<set name="windowWidth" value="800" />
<set name="windowHeight" value="700" />

<window width="${windowWidth}" height="${windowHeight}" />

<haxedef name="windowWidth" value="${windowWidth}" />
<haxedef name="windowHeight" value="${windowHeight}" />

Feel free to change the values, but that’s the general idea. Now you can make the following constants:

public static inline var WINDOW_WIDTH:Int = haxe.macro.Compiler.getDefine("windowWidth");
public static inline var WINDOW_HEIGHT:Int =  haxe.macro.Compiler.getDefine("windowHeight");
1 Like

@player_03 is there no way to get the width/height other than by using set and haxedef? You’re essentialy creating another variable and using it everywhere (which works), instead of reusing the existing property from window.

Unfortunately, the string substitution feature only looks at defines and environment variables. (That is, values set by the <set /> and <setenv /> tags.) You could modify the <window /> tag parser to set a define as well, but then you’d want to modify the rest of the file for consistency.

But it might be easiest to switch to the HXP format, which allows you to do everything the XML format can do, and much more. Then all you need to do is this:

haxedefs.set("windowWidth", window.width);
haxedefs.set("windowHeight", window.height);

Or you could use reflection to copy all the fields at once:

for(field in Reflect.fields(window)) {
    haxedefs.set("window" + field.charAt(0).toUpperCase() + field.substr(1),
        Reflect.field(window, field));
}

There are some plans to improve the runtime support for detecting what was set in your project files, but for now, adding your own define is the one of the cleanest ways to get the identical value at runtime. Often a person would use the stage.stageWidth and stage.stageHeight for this, but I understand it’s different when you hard-code a size and it letterboxes for you on mobile