Sunday, December 2, 2012

Code Refactoring

I started noticing I was writing paths to image files a lot as I was creating scenes.  And I realized as we kept adding more and more, we were going to run into problems if we decided to change images.

As an example - a line of code may have something like this: 

local bullet = display.newImage('resources/Bullet_Black.png')
 
As you can imagine, that image gets used a lot.  If we want to change to a different bullet image, and decided to keep Bullet_Black.png we may have to edit a lot of files.
 
So I built three resource Lua files:
 
  • bgFile.lua - to hold background image paths
  • controlFile.lua - to hold button and other control image paths
  • shipFile.lua - to hold the various ship image paths
 
Those files have local variables that hold the path statements to the images, and then get functions so other modules can gain access to the resource path.
 
It dawned on me, this is a classic refactoring scheme -  what is the least amount of 'knowledge' a code module has to have to do it's work.
 
So now - the resource files 'know' where to get an image; a scene file 'knows' how to manipulate an image, and so it goes.
 
One benefit we will be able to capitalize on later - as we add higher definition images for other devices we won't have to have the scene modules 'know' how to determine what image to use.  That bit if knowledge can be transferred to yet another module - and then 'asked' by the resource modules.  If the device is a higher res one - then the resource module can serve up a HD version; or else just the regular res image if the device can't handle it.
 
One thing that caused a bit of a struggle - Lua and the way it handles arrays.
 
Lua it turns out is a fairly primitive language - in that I mean primitive in the way C is.  Arrays are very simple structures in Lua - no matter how you have defined an array it is actually a KV collection set into memory.  And of course the variable name is just a pointer to the actual location where the values are stored.
 
Using them is not a big deal - it's copying them that things get fun.  There isn't anything built into Lua that provides a way to copy an array:
 
MyArray = {a, b, c}
foo = {}
foo = MyArray
 
becomes an assignment for the pointer foo to the pointer MyArray - not the values MyArray is pointing to.
 
So - I found a deep copy function at http://www.dreamincode.net/code/snippet5401.htm, made a couple of changes to it and added it to our fileIO.lua file.  That is what gets used when we need to make a copy from one array to another.
 
So when we have this defined in the ship file:
 
local uavShip = {'resources/drone1a.png', 'resources/drone1b.png','resources/drone1c.png','resources/drone1d.png'}

Using the deep copy function the KV collection uavShip is pointing to can be copied to the memory location myDrone is pointing to:

local shipFile = require "shipFile"
local myDrone = { }
myDrone = shipFile.getDroneTbl( myDrone )