Game Development Guidance

93 views
Skip to first unread message

Garrett Hopper

unread,
Oct 24, 2016, 9:57:15 PM10/24/16
to Haxe
Hello, everyone!

Over the past few weeks I've been working on a game using Kha.
The game is mainly meant to be played on Android / iOS, however I've been using the Html5 target for development.

This is my first Haxe project, and I've run into a couple questions.

- How can named, optional arguments be done efficiently?

I've been creating a ui framework for this game, and I've ended up with many anonymous config objects being passed around:
    public function new(?config: {
        ?layer: Int,
        ?w: Size,
        ?h: Size,
        ?left: Position,
        ?right: Position,
        ?top: Position,
        ?bottom: Position
    }) {
        if (config != null) {
            if (config.layer != null) {
                layer = config.layer;
            }
            if (config.w != null) {
                w = config.w;
            }
            if (config.h != null) {
                h = config.h;
            }
            if (config.left != null) {
                left = config.left;
            }
            if (config.right != null) {
                right = config.right;
            }
            if (config.top != null) {
                top = config.top;
            }
            if (config.bottom != null) {
                bottom = config.bottom;
            }
        }
    }


This works alright, aside from the potential performance hit.
The other problem is that classes which extend this class will need to include all of its config parameters.

Extending class:
    public function new(?config: {
        ?drawable: Drawable,
        ?sOff: Float,
        ?xOff: Float,
        ?yOff: Float,
        ?wOff: Float,
        ?hOff: Float
    }) {
        if (config != null) {
            if (config.drawable != null) {
                drawable = config.drawable;
            }
            if (config.sOff != null) {
                scaleOffset = config.sOff;
            }
            if (config.xOff != null) {
                xOffset = config.xOff;
            }
            if (config.yOff != null) {
                yOffset = config.yOff;
            }
            if (config.wOff != null) {
                widthOffset = config.wOff;
            }
            if (config.hOff != null) {
                heightOffset = config.hOff;
            }
        }
        super(config);
    }

So far this paradigm hasn't worked out too bad, but I figured I'd check with you guys to see if there was a better way.
I'd prefer to avoid anonymous structures for performance reasons, but perhaps I'll just hack together a macro to automatically inherit parents' config parameters and be done? Any thoughts?

- How can I manage memory allocation?

I don't have much history in memory management, but I'm starting to realize its importance on this project.

Currently in my game (running on Android), if I go to a scene (think Menu -> Settings), the entire scene is created (tables, buttons, widgets, etc.). This process takes some time when memory hasn't been allocated yet (as far as I can tell), however once I've gone to that scene, then back to the previous, I can now load this new scene very quickly.
So,
Menu -> Settings (5 seconds)
Settings -> Menu (instant)
Menu -> Settings (instant)

What could be the cause of this? My only assumption is that it's due to memory having been allocated already for all the Settings screen's widgets.

- Is there a way for a function to accept ADT's without enums?

I'd like to be able to create a function which accepts either a String or an Int (for example)
However, I don't want to have to indicate which type I'm passing it with an enum:
enum Param {
    INT(int: Int);
    STRING(string: String);
}

function func(param: Param): Bool {
    switch Param {
        case INT(int): if (int == 0) return true;
        case STRING(string): if (string == "test") return true;
    }
    return false;
}

While this is doable, the syntax is far too verbose. Perhaps a macro could automatically generate something like this. (Though it would have to modify calls to the function, since haxe doesn't support function overloads)

Yes, I know some of this can be done with optional parameters, but this isn't perfect. (a function could be passed both optional parameters or none) Also, I'd prefer to not have to null check all optional parameters.

Hugh

unread,
Oct 25, 2016, 1:08:08 AM10/25/16
to Haxe
You could make the code look nicer with something like this:
  w = getDefaultFloat(config,"w",20.0);

Which combines config and class member initialization on one quite sensible step.

One thing to remember is that this anonymous-with-option-fields is really a very weak form of typing.  All it is saying is that *if* the field exists then it should of this type.  It does not guard against the real problem with this, which is making a typo in the name, eg "xOff" vs "xoff".
IMHO, this makes this pattern an anti-pattern.
The benefits you will get of dropping this is the type swapping you seek ('param" is Int or String), and no need to define (and anticipate in advance) all the config types you wanted.

As for memory efficiency, you should consider then number of times your code will get called.  100 times at the start of your menu frame should not be a problem.

I know different people have different feelings about this sort of stuff, but if you embrace the Dynamic, I think life will be easier for you.

Joe Spataro

unread,
Oct 26, 2016, 12:09:41 AM10/26/16
to Haxe
I saw a pattern in the Luxe engine (https://luxeengine.com) that used typedef'd collections of 'options' to do this, which I really liked using in practice.

// Sprite inherits from Visual.  Here are the options for Visual and then the class w/ constructor

// Here is the extended typedef for a derived type

Hugh

unread,
Oct 26, 2016, 12:24:21 AM10/26/16
to Haxe
I understand that to the extent it is readable or completable it forms some kind of documentation.
But it does not really stop the main "typing" issue of providing a misnamed parameter.
If you are having trouble describing the types, the alternative would be I guess actual documentation.
Reply all
Reply to author
Forward
0 new messages