Modulous development

I’m curious about what your plugin will be doing, that it has such stringent code organisation needs :slight_smile:

All of the above, including my final snippet, is of course pseudo code. The plugin I’m actually building is an isometric game engine… coming along nicely too, I just needed to tidy it up somewhat before moving forwards and thanks to everybody here, that’s now done.

So far it converts Tiled maps into engine maps with layered tiles, renders them in isometric, incorporates pinch-to-zoom functionality and can snap the camera to any tile position. It can convert between any of raw tile co-ordinates, cartesian co-ordinates, isometric co-ordinates, and screen co-ordinates so in turn can convert a screen click in to which tile was selected or even which specific point within a tile was selected.

Swipe to pan and snap to object/character will be supported, allowing for free-roam isometrics or character-roam isometrics. AStar pathfinding algorithms will be built in allowing for object/character movement by simply passing a new tile position to walk to. Individual tile or full map data injection/removal will be supported allowing, basically, for tile layers to be removed or appended to a tile, for when objects need placing/taking or doors need opening/closing, for example. And I might, just might, build in some crude lighting engine by basically layering black over each tile and poking gradient holes to effectively create darkness masks… but I’ve not yet decided on the feasibility of this one.

I’m building this really for internal use more than anything else, but will be releasing to the Corona marketplace where there appears to be a distinct lack of isometric engines.

@richard11

That sounds like an awesome plugin.  Count me in!

Richard,

Great idea for a plugin.  I am looking forward to seeing it.

Bob

Thanks both =).

A very crude sample apk attached for anybody interested. Android only at the moment as we don’t have an iOS license yet, but it’s entirely Lua so should be cross platform when we come to a proper release.

The sample allows panning the map by dragging with one finger, zooming in/out with pinch gestures, and centering on to specific tiles by tapping them.

To produce this sample is just a few simple lines:

[lua]-- Load plugin library

local qiso = require “plugin.qisoengine”

– First, tell qisoengine where maps and sprite files are.

qiso.setAssetsFolder(“assets”)

– Load a Lua formatted Tiled Map Editor tilemap into a Qiso map.

qiso.loadTiledMap(“sample-tilemap”)

– Enable zooming when the screen is pinched

qiso.enablePinchZoom()

– Enable camera panning when the screen is dragged

qiso.enableCameraPan()

– Center on the tapped tile

function tapTile(event)

    – Get the tile located where the screen was tapped. If there’s no tile here, getTile returns nil.

    local tile = qiso.getTile(event.x, event.y)

    if(tile ~= nil) then

        qiso.goTo(tile.x, tile.y)

    end

end

– Main game loop

function mainLoop()

    – Render the map

    qiso.clearGraphics()

    qiso.renderMap()

end

– Do something when the screen is tapped

Runtime:addEventListener(‘tap’, tapTile)

– Run the main game loop

Runtime:addEventListener(‘enterFrame’, mainLoop)[/lua]

There are a few other functionalities that this sample doesn’t show off, and still lots to do before it’s ready for release, but the general idea is to make developing isometric games as simple as possible without losing any flexibility.

In the hopes this sparks some excitement, we’ve set up a mailing list that you can subscribe to if you’d like to be notified when this plugin is released.

http://campaigns.qweb.co.uk/h/i/3A142358D02BBDE3

Hmm. I can’t tell if I’m just not looking in the right place, or if my attempt to attach the apk to that post just didn’t work. Here’s a hosted version: https://development.qweb.co.uk/qiso/tilemaptest.apk

Updated the APK with a better example, now that a) the engine properly supports layering and b) we have some proper graphics created. Also attached a screenshot for those who don’t have Android to play with it on.

I won’t update here again as it’s really not the right place for it, so please do sign up to the above mailing list if you want to be notified when released.

When can you release this plugin?. I am very excited

Had to change priorities a little for a while but progressing with this development again now and hoping to release within the next few weeks. Probably early - mid February. Performance isn’t brilliant at the moment (mainly need to incorporate off-screen tile culling) and I really want to get path-finding algorithms in place for the first release.

If you haven’t already signed up to the mailing list at http://campaigns.qweb.co.uk/h/i/3A142358D02BBDE3 please do so, and we’ll notify you the moment we release =).

Regards.

Hi,

Just as a general question, do, or can, your library functions fall into functional categories? This is generally how a large library is structured.

For example:

local mylib = require("mylib") local res = mylib.category\_one.do\_something(...) local res = mylib.category\_two.do\_something(...)

Or, do they need to all be on the root mylib object?

I ask because my answer will be different depending upon which you need. The “category” style is simpler to implement, and generally preferred by the end user.

-dev

Whoops sorry - totally forgot I’d posted here, ha.

The functions can be categorised logically for the sake of splitting the code into manageable files, but I’m hoping to keep them ‘root’ for actual usability.

For example, mymodule.addSomething() and mymodule.renderSomething() could go in to say, dataHandling.lua and rendering.lua, but it would make less sense to have to call mymodule.dataHandling.addSomething() and mymodule.rendering.renderSomething().

That said, I’d be interested in both of your approaches to be honest.

My approach for all projects:

  1. Build a hierarchy of modules from the very top to the very bottom. At the top I always create a module called “appEngine”. This is like the director of the app. Everything else comes underneath. My main.lua file typically only creates an instance of “appEngine” and calls a function like appEngine.startMenu()

  2. As I said before, everything needs to be organised in a hierarchy. So “myMenu” is called as a local inside “appEngine”.

  3. Whenever you instance a new object, it need to receive it’s “super” object as a parameter. So when you create a menu from the appEngine module, you would say something like:

local myMenu = menuClass.new(self)

And then in menuClass you would do something like

mySuper = theValueThatWasPassedToMeReferringToAppEngine

This way myMenu knows that it’s “parent” is appEngine and can talk to it. And appEngine of course knows that myMenu is a child object, or further down in the hierarchical tree.

  1. When you know you will create a lot of similar items, create a “manager” class above it in the tree. So for instance, when you have a game with ghosts as enemies, first create a module called myGhostManager. This module has an array that holds the child object which are modules called ghostClass, for example. The ghostManager class takes care of all “ghost management”: adding new ones, removing old ones, removing all at end of level etc…

  2. If you construct things this way, EVERY object or module will be able to talk to eachother, because they can address every single item in your hierarchy by going up and down the list.

  3. This sometimes creates ugly code like self.super.super.super.myGhostManager:killAllGhosts() - meaning, go up 3 levels in the hierarchy tree (the super of the super of the super of myself, or the parent of my parent of my parent), but it works!

  4. For debugging reasons I give every module or class I write a property called self.type, with a string describing what type of object it is (an appEngine, a ghost, a ghostManager etc…). In case I get confused I just print self.super.super.super.type to the console to see what type of object I’m talking to.

Voila. Not sure I’m making a lot of sense here, but the method above is extremely powerful and flexible!

Thanks Thomas,

That does make sense to me I think, yes. My concern though is that I’m building a plugin so I want that when a development uses this plugin, the code from within that development can just call myplugin.myfunction() without having to incorporate hierarchy into that call, but that internally, within myplugin, the actual code providing all of the myfunction()'s is logically separated into ‘modules’.

I can totally see how with some developments having the hierarchy open like this is useful - i.e. somePlugin.math.round() and somePlugin.graphics.circle() would be fine while somePlugin.round() and somePlugin.circle() could cause confusion as to which does what, but I think in my case I’d prefer to just be able to call somePlugin.someFunction() without having to think about there someFunction() is going to be provided from the plugins internal hierarchy…

Perhaps it’s just that I’m new to Lua and I’m thinking about it wrongly. If what I’m trying to achieve really isn’t the done thing then I guess I should just follow your approach. I’ve never been a fan of OOP’s classes hierarchy though and Lua seems to me like it has procedural roots so I’d sort of expected require() to work more like say… PHP’s require() function, where the included code is brought in and effectively runs inline with everything else rather than it being called as a standalone class.

Hi Richard, It’s just tables.

You can assign references to the modules functions  as members of the main plugin table

local myModule = {} -- declare your functions as you like. -- either as module members myModule.function1 = function () ... end -- or as locals local function2 = function () ... end -- then assign them to the main module myModule.init = function (mainModule) mainModule.function1 = myModule.function1 mainModule.function2 = function2 end return myModule

and in the plugin

local plugin = {} -- require the subModule local myModule = require "myModule" -- get the module functions myModule.init(plugin) -- now you can call them directly as they are from the main module itself plugin.function1() return plugin

just keep track of local and self scopes, they might become confusing sometimes…

Thanks Arteficio. If I’m understanding this correctly, it’s an ingenious method!

One thing though - say I now have the following plugin:

[lua]

local Library = require “CoronaLibrary”

local lib = Library:new{ name=‘myplugin’, publisherId=‘foo.bah’ }

local myVariable = 0

local module1 = require “plugin.myplugin.module1”

module1.init(lib)

local module2 = require “plugin.myplugin.module2”

module2.init(lib)

return lib

[/lua]

But module1.lua and module2.lua both need to read and write to myVariable… How would I reference it from within those files?

Similarly, how would module2.function1() reference module1.function2() ? Presumably lib isn’t available within their scope otherwise your init() function wouldn’t be needed?

OK, I’ve reworked half of my plugin to be modulous now, thanks to the examples above, but I’m getting confused by the variable scope.

For variables that multiple modules within the plugin need to refer to, I’m making them global within the main plugin library. However this of course means that they’re open to the code which loads in my plugin too, and I don’t want that. I want them to be local within the scope of the plugin but for the plugin to be modulous.

Next, where I have modules that need to call functions within other modules, I’m currently require’ing those at the top of the caller module, as well as using the init() trick above to add them in as library calls. I think this is only working though because the functions I’m currently sharing don’t do anything very fancy but for example if the called module had an internal local variable and I was calling a function to return that value, I’m guessing this would return different values because I’m effectively creating multiple instances of that module?

You’re right.
As far as i know, the way require works is different from php. Each lua source has it’s own scope so i don’t think a local variable declared outside the module can be accessed from the module itself.

Even cross referencing between the modules might be a problem: if module1 requires module2, module2 cannot require module1

I have a possible structure in mind that might be helpful but i’m on mobile now and writing code on a smartphone is something i feel a bit uncomfortable.
I’ll be back tomorrow.

Greatly appreciated and very much looking forward to seeing what you come up with! I can’t decide if I’m just going about this the wrong way, as a rookie to Lua, or if this is something the language actually fails at. If we can’t split code into tidy files without losing the ability for that code to share variables then long scripts must get very difficult to manage.

I’m also on mobile right now and can’t dig further into this just yet, but https://docs.coronalabs.com/tutorial/basics/globals/index.html is quite interesting actually. The method at the end suggests that if you load a module in from the top of all other modules, the variables it creates are indeed then shared. If this works then it should resolve my issue, but it’s not making much sense to me how this doesn’t just create multiple instances of those variables, one instance within each module. In fact, I’m now wondering how you would actually go about creating a second instance of a module… Say if that module was to create an NPC and you needed multiple NPC’s, my instinct would be to do this: [lua]local npc1 = require “npcModule” local npc2 = require “npcModule”[/lua] But going by this doc, it sounds like npc2.hp = 10 would result in both npc1.hp and npc2.hp setting as 10, because they’re in the same memory space? Will play with this more tomorrow.