This is Bananattack.

Tag: OOP

Anonymous Functions, and Textshmup: A retrospect

Posted by Overkill on April 8, 2009 at 8:53 pm under Uncategorized

Some of you may have recently played my 24h game textshmup. As expected, it wasn’t that well received. It was a bad concept to begin with, after all! :D

It was too hard to read quickly and type responses. Audio cues and colored text were added to make the game slightly easier to react to, but even then, it was just too tedious. It was just a randomly generated endurance test, with no goal, and no intermediate tasks.

That said, I had fun making it! I mentioned last time that I made it in LuaVerge. I never mentioned why it was so quick to write.

Well let’s go!

For one, I used the vx library I had written. It came with the spiffy nifty object-oriented class system that I made.

I had my entire game use a single well-divided render/update loop, which boiled down to this:

while true do
    Render()
    Update()
end

I declare two lists which contain all the callbacks done by the render and update events:

render_list = {}
update_list = {}

Here is Render(), in its entirety:

function Render()
    vx.screen:RectFill(0, 0, vx.screen.width, vx.screen.height, 0)
    for i, f in ipairs(render_list) do
        f()
    end
    vx.ShowPage()
end

The Render() function starts by clearing the screen, then it iterates over all entries in the render list, and calls them all. At the end, it shows the changes on the screen. This was ridiculously nice to hook in new rendering events.

Similarly, here was my Update() code, which used frame-throttling so each update callback could be written in per-tick logic:

function Update()
    frame_limiter:Update()
    
    local i = 0
    while i < frame_limiter.gap do
        for _, f in ipairs(update_list) do
            f()
        end
        i = i + 1
    end
    vx.SetAppName(TITLE .. ' ' .. frame_limiter.frame_rate)
end

Both of these worked great for global functions and static methods.

There was one issue with the way they were designed though. Which wasn't immediately apparent, but here goes.

Say I made a class named BlueBox, which has an x, y, x2 and y2. I declare a method for it like this.

function BlueBox:Draw()
    vx.screen:RectFill(self.x, self.y, self.x2, self.y2, vx.RGB(0, 0, 255))
end

In Lua, the colon : in that function is syntax sugar for the following:

function BlueBox.Draw(self)
    vx.screen:RectFill(self.x, self.y, self.x2, self.y2, vx.RGB(0, 0, 255))
end

Which is syntax sugar for:

BlueBox.Draw = function(self)
    vx.screen:RectFill(self.x, self.y, self.x2, self.y2, vx.RGB(0, 0, 255))
end

See that 'self' parameter? Well, earlier when I'm calling the functions, I go like this:

f()

That's a call with no arguments. If we try and add the method pointer for a particular blue box's render, it will call it without passing self, so 'self' is nil:

-- Won't pass the self parameter!
table.insert(render_list, self.Render)
-- Similarly, won't pass the self parameter!
table.insert(render_list, self:Render)

Thus object instances aren't passed around. Not good!

So how do you pass around the 'self' parameter to this list? Well, fortunately, Lua allows you to create anonymous functions, wherever you want because functions are first-class values. And these anonymous functions can be passed "upvalues", which are local values defined in a scope outside the function.

Using these facts, I wrote a trivial fix to bind method pointers to their objects, and leave Render unchanged! I made a function that did the method wrapping for me:

function MethodPointer(self, meth)
    return function(...)
        return self[meth](self, ...)
    end
end

The function is passed the 'self' parameter and the method pointer to bind together, and it returns an anonymous function which will take care of calling, with 'self' being passed automatically.

Then I can go add to the render_list and update list:

table.insert(render_list, MethodPointer(self, 'Render'))
table.insert(update_list, MethodPointer(self, 'Update'))

This is actually pretty close to how Javascript gets around similar problems, but with its definition of 'this'.

This little tidbit allowed my various components of my game to plugged and unplugged from the main loop as it progressed.

For my text input, I used a callback to process commands when enter was pressed, using the same method pointer stuff. The callback passed around the piece of text, and would return true or false on whether or not the command was permissible. It was very nice.

Lua is just awesome. I love it.

Anyways. As you might see, coding isn't really a colossal obstacle, with Lua around. Instead, the new obstacle is coming up with good ideas!

Something to remember for the next time I try and make a 24h game, and what I always need to consider, while making Resonance.

Catch you later, everyone!

Tags: , , , , , , ,

No comments (make one!)


Minty chewing gum.

Posted by Overkill on January 25, 2009 at 2:10 am under Uncategorized

This week, I poured over some more scripting language stuff in LuaVerge. Monotonous work really, but it needed to be done!

As a result, LuaVerge is nearly done. I’m convinced it’s at about the point where it’s usable again.
 
 
 
I added a way to load from .vpk packfiles with Lua scripts. So now require statements will also examine packfiles for source code, meaning that things like vx, and peoples’ games can be packed away in a single file.

I might add override loadfile and dofile too, if it’s actually required, but I figure those are mainly lowlevel things, and most work can USUALLY be done by require. I guess if someone were using Lua as a file format for game data (like a database of items or something) as well, then you’d need to worry about this. I’ll take peoples’ input here, for those Lua users out there.
 
 
 
One of the biger things I spent time scratching my head over was binding Verge’s builtin variables. You see, Lua shoves in getters and setters for variables as functions. So at the lower level, to get the backend variable VC-style entity.x[ent], it calls v3.get_entity_x(ent).

However forcing people to call raw functions rather than assign variables, I’m told is annoying. So, I added support, through Lua’s crazy voodoo magic with metatables.

Since ‘variable’-style accesses to builtins are more expensive than their raw function calls, a bit of optimization had to be considered, to at least lower these costs. After all, the older LuaVerge had issues with speedy access.

This was a bit of a surprise to me at first, but also really neat, local variables have a much faster access time than global ones. Storing local copies of global variables gives a significant efficiency boost. Some report about a 10% lookup for globals, so imagine if it were a nested table of some sort. Caching variable lookups as much as possible would very much improve performance.

So using this knowledge and a few tricks, I think I’ve constructed a way to make fast lookups to LuaVerge builtins. I won’t bore or scare you with the details.

But if you insist, and are curious, all the work is in the source repository for Verge at http://www.verge-rpg.com/svn/verge3/ with username “anonymous” and password “anonymous”.

Particular files to look at are:

 
 
 
So after all this, I started to repair the vx library so it’d work after the giant rewrite. Surprisingly, it wasn’t too hard to repair.

Why? Because vx enclosed all its source in a custom class system. Object oriented code made things compartmentalized and simple enough to refactor.

I made a simple vergeclass function that declares a class, and basically allows you to declare objects of that class after it’s been made.

You declare classes like this:

vergeclass "Thing"

(Whoa! no brackets around the function call? Lua lets you omit them for literals like quoted strings or tables). Anyway, after that point, there’s a globally named class called “Thing” which can be instantiated.

Constructors are declared like

function Thing:__init(a, b, c)
    self.a = a
    self.b = b
    self.c = c
end

And methods inside the class are sort like

function Thing:method()
    print "Hody2!"
end

Objects can be instantiated like this:

mything = Thing(5, 3, "tacos")

Their methods can be invoked fairly simply:

mything:method()

The downside, was the original system I had (before LuaVerge was rewritten) was horrendously inefficient, but it worked somehow. Lua is magical and allows you to horrendously hack things that just work.

Anyway, I revisited this code not because of this but for another reason. None of classes could be ‘extended’ or ‘inherited’ from, making the OOP limited. Granted, for vx, inheritance wasn’t necessary, and I didn’t really desire people extending the core objects because I’d much prefer composition.

Basically objects should as much as possible use “has-a” relations instead, and avoid “is-a” whenever possible, however tempting it is. It decreases coupling somewhat that way.
 
 
 
But I had other code, with Resonance’s sidescroller engine that I wanted to salvage. It used a moderate degree of inheritance, which given for free by luabind. Luabind being the thing that glued LuaVerge behind the scenes before we tossed it, and it came with a class system with inheritance… Anyway.

So I added a single-inheritance system to vx’s vergeclass so I could eliminate this old dependency and have working code again. This involved entirely rewriting the old system now that I understand the Lua library, Lua-based optimizations and metatables a lot better.

It was actually pretty enjoyable to overhaul the whole thing, and… weird. Metatables have some godly power to them. Anyway I finished, and even gave two methods of setting up inheritance.

I supply a temporary global function super(...) which must be invoked in a child class’s initializer to ensure the object inherits all the attributes that its parent class has. Later, I might enforce the call be made on every subclass just to ensure undefined behaviour won’t happen.

Now any time a method is called, it’ll look in its own class first, and failing that it’ll look in it’s parent’s class. If a class needs to explicitly call a method of its parent, it can index self.parent and use self.parent.method(self, ...).

So using the Thing example from earlier, the calls to create a child class are either this…

vergeclass("SuperThing", Thing) do
    SuperThing:__init(a, b, c, x, y, z)
        super(a, b, c)
        self.x = x
        self.y = y
        self.z = z
    end
end

…or this, which I prefer because it looks like Python kind of:

vergeclass "SuperThing"(Thing) do
    SuperThing:__init(a, b, c, x, y, z)
        super(a, b, c)
        self.x = x
        self.y = y
        self.z = z
    end
end

Either one of them reads “The class SuperThing is a child of Thing”. And there you go! Inheritance! Nifty! Sexy!

I even added one other thing! Properties. Other languages provide properties to declare pseudovariables with functions that are called when their values are accessed or mutated. I do similarly, through a bit of metatable magic.

Let’s take an example of a typical RPG player for a second, who has an HP attribute. To declare a property, you can go something like this:

Player._property('alive', function(self) return self.hp ~= 0 end)

You can then use the ‘alive property like a readonly variable, for instance on a player object named bob:

if bob.alive then print("We're still kicking!") end

I might expand this class system to allow multiple inheritance or mixins at some point. Not a high priority, but it’d be nifty!
 
 
 
So yeah, this has been my week. I’d love to hear about yours too! :D

Tags: , , , , ,

No comments (make one!)