Monday, 2 February 2015

Object.defineProperty

I've been doing a lot of coding recently. For anyone who liked my little demo in the last fall, I have no idea if I will ever get back to it, but I've got something far more exciting going on now.

I haven't posted anything about the Kittens Game but I've been playing it for a while. It's a town management Idle game with a lot of complexity. Obviously anyone who reads this blog knows I'm a huge fan of Sandcastle Builder, but, as a recent IGN Article explains so well, the complexity of Sandcastle Builder is so outside of normal that it would be impossible and even foolish to try to replicate. Kittens Game is very complex but uses things like wood and minerals to build warehouses and ships, so it's easier to parse. It also doesn't go to infinity.

I wanted to get some of the Kittens Game things-make-sense with just a hint of the alien and the weird math that made Sandcastle Builder great. I have something that is working, probably with a day or two of gameplay before you'd really hit the wall in terms of things to do.

Of course at some point I stop developing and start working on making things work better. Recently it was saving. My save_game function was starting to get pretty clunky, about 100 lines. I rewrote it and did some other reworks, and here it is now:

H.save_game = function () {
    var save_file = {}, i;
   
    for (i in H.saveables) {
        save_file[H.saveables[i].call] = H.saveables[i].save()
    }
       
    save_file = JSON.stringify(save_file);

    localStorage.humbabellas_horror = save_file;
}

That looks very nice, but at a glance it probably looks like I just took those 100 lines of code for saving and broke them off to the objects that want to be saved. That would still be a bit of an improvement, since I think it's much more convenient to have an object know how to save itself rather than having a function know how to do the saving for it, but it's even better than that. The "save" property of these objects is added by the "H.register_for_save" function which puts on a boilerplate "save" function:

Object.defineProperty(x, 'save', {value: function () {
    var i, r={};
    for (i in x.load_functions) {
        r[i] = x[i]
    }
    return r;
}})

Of course that code has to exist somewhere. Where it exists, obviously, is in the load_functions property of each object. In the load_functions property I put the handler for loading each property that is saved, each keyed to the name of the property. Adding new things to save is now totally streamlined.

It turns out I am foolishly in love with Object.defineProperty. This might be a terrible thing - and I know I have a blog reader who might show up to tell me what a terrible thing it is - but there are some things I just love about it so much. I love adding non-enumerable properties to objects so that I can still enumerate over the other properties. I particularly love adding properties to arrays, though I've moved away from that because it wasn't the best way to do what I was trying to do.

Right now I'm rewriting my number code. In most of the places in the game I don't actually store numbers for things, instead have an accessor property on the object that gets the result of a calculation of the value. If I want to increase the rate and which you gain a resource by 3 per second, I don't, for example, find the per_second value and add three. Instead I find the per_second value and add a H.new_bonus('add', 3) to it, which makes it recalculate the value of the thing and place that where the accessor will grab it. What I want to do is change that so instead of push on a function (x) that returns x+3. That might not sound very different, but it's pretty different for two reason, neither of which I'll put the time in to discuss here.

Hopefully, once I'm finished redoing the underlying number code, I'll implement it in the place I really need it right now, and then have something to release. I really need ideas for this thing.

No comments:

Post a Comment