Lua: Basic Engine

From Mario Fan Games Galaxy Wiki
Add to this template
 Standardwikimessagebox.png This article assumes the use of Lua 5.1.

Information may not be accurate or may need revision if you are using a different version.

This page covers the creation of a simple object engine. It will use many of the concepts from the other tutorials, so it is a good idea to read those first. For simplicity it assumes you are using MMF2 and a recent version of the XLua extension already set up and ready to go. When seeing the final code in its entirety at the end of the tutorial, you'll notice a lot of stuff has been moved around into a more logical order; this tutorial goes step by step so it'd be difficult to do that from the start!

To start off, we need a way to store and create new object instances. We also want to define a few namespaces, which will be used to hold many functions and variables under one table; this is considered good practice and also makes some things easier. For instance, accessing object methods would be a mess if they were stored in the global namespace.

object = { } -- object methods

newid = 0 -- next id to assign object
instances = { }

object.getId = function ()
    newid = newid + 1
    return newid
end = function (data_table)
    local var = data_table
    local obj = {
        __index = object, -- use the 'object' method table
        id = object.getId(),
        x = var.x or 0, -- default to 0 if no 'x' is supplied
        y = var.y or 0,
    setmetatable(obj, obj)
    return obj

Though we really don't need the object to serve as its own metatable (we could move the __index metamethod to object and reflect that change in setmetatable), it helps keep the method table uncluttered and also gives the object a sort of "type" specification: it's obvious we know that this is an 'object' instead of something like 'hud_element', which would use an entirely different method set.

You'll also notice how that function expects a table of named elements instead of separate parameters; it doesn't matter which of those you go for, but for constructor functions like this it makes sense to use a table, since they're used exactly like a regular table construction anyway.

To avoid possible gotchas, we aren't going to create (or destroy) objects immediately; instead we will either wait before (or after) the main loop runs and then we will either create/destroy it. Right now, we'll just worry about creating it:

createList = { }

object.createListFlush = function ()
    for _, obj in ipairs(createList) do
        table.insert(instances, obj)
    createList = { } -- clear the create list

object.create = function (data_table)

object.create is basically a macro function for constructing AND handling the new object. You don't necessarily need to use a function for that purpose, but it's a good idea in case you need to change how the object is created.

The createListFlush function calls a cb_newObject function; that function will be used by MMF to create an object and export it to XLua with the provided id. In fact, here is the psuedocode for that:

Start of Frame
--> XLua - Register MMF Function: cb_newObject

XLua: On Function "cb_newObject"
--> Create Object: <Active>; 0; 0
--> Active - Set ID (Alterable Value A): MF_NumericParam("XLua", 1)
--> XLua - Export Object: <Active>; ID("Active")

to be continued