Handy Code Snippets

17 replies [Last post]
Danny
User offline. Last seen 32 weeks 2 days ago. Offline
Staff
Joined: 17 Aug 2011

This is a post that lists some handy code snippets. They will generally be small examples and the list will be added to in time and also if you guys post some snippets I will add them to this list.

Print/Display a boolean value preceded by a string

Problem :

If you try to simply print a boolean value preceded by a string like so :

local myBool = true
 
print("Value of my bool = " .. myBool)

You will get the following error :

"attempt to concatenate field 'myBool' (a boolean value)"

To get around this you instead use a comma.

--Usage
local myBool = true
 
print("Value of my bool = ", myBool)

This will output :

Value of my bool = true

Iterating through a key/pair table in order

As you know if you iterate through a key/pair table, it does not do so in the order it was defined.

Eg:

1
2
3
4
5
6
7
8
9
local myTable = {
    ["key1"] = 1,
    ["key2"] = 2,
    ["key3"] = 3,
}
 
for k, v in pairs(myTable) do
        print(myTable[k])
end

will print :

1, 3, 2

Sometimes that is fine, but it is not always what you want.

To iterate in order you can use the following function (taken from the lua wiki)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
local myTable = {
    ["key1"] = 1,
    ["key2"] = 2,
    ["key3"] = 3,
}
 
 
local function __genOrderedIndex( t )
    local orderedIndex = {}
    for key in pairs(t) do
        table.insert( orderedIndex, key )
    end
    table.sort( orderedIndex )
    return orderedIndex
end
 
local function orderedNext(t, state)
    -- Equivalent of the next function, but returns the keys in the alphabetic
    -- order. We use a temporary ordered key table that is stored in the
    -- table being iterated.
 
    --print("orderedNext: state = "..tostring(state) )
    if state == nil then
        -- the first time, generate the index
        t.__orderedIndex = __genOrderedIndex( t )
        key = t.__orderedIndex[1]
        return key, t[key]
    end
    -- fetch the next value
    key = nil
    for i = 1,table.getn(t.__orderedIndex) do
        if t.__orderedIndex[i] == state then
            key = t.__orderedIndex[i+1]
        end
    end
 
    if key then
        return key, t[key]
    end
 
    -- no more value to return, cleanup
    t.__orderedIndex = nil
    return
end
 
--This is the function you will use to replace "pairs"
local function orderedPairs(t)
    -- Equivalent of the pairs() function on tables. Allows to iterate
    -- in order
    return orderedNext, t, nil
end
 
 
for k, v in orderedPairs(myTable) do
        print(myTable[k])
end

That will print:

1, 2, 3

Shuffling a table

Say you are making a card game and want to shuffle your table containing your cards. Here is one function that can do it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
local function shuffle(t)
    local rand = math.random 
    assert(t, "table.shuffle() expected a table, got nil")
    local iterations = #t
    local j
    
    for i = iterations, 2, -1 do
        j = rand(i)
        t[i], t[j] = t[j], t[i]
    end
end
 
--Usage
shuffle(myTable)

Checking if a file exists

This speaks for itself, to check if a file exists you can use a handy function like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
local function doesFileExist(theFile, path)
        local thePath = path or system.DocumentsDirectory
        local filePath = system.pathForFile(theFile, thePath)
        local results = false
                
        local file = io.open(filePath, "r")
            
        --If the file exists, return true
        if file then
                io.close(file)
            results = true
        end
         
        return results
end
 
--Usage
doesFileExist("levels.data") --Returns true/false
 
--Or
doesFileExist("levels.data", system.ResourceDirectory) --Returns true/false

Get distance between two objects

This is a commonly needed function, it simply returns the distance between two objects

1
2
3
4
5
6
7
8
9
10
local function getDistanceBetween(obj1, obj2)
        return math.ceil(math.sqrt( ((obj2.y - obj1.y) * (obj2.y - obj1.y)) + ((obj2.x - obj1.x) * (obj2.x - obj1.x)) ))
end
 
--Usage
 
local plane = display.newRect(100, 100, 40, 40)
local bird = display.newRect(200, 100, 40, 40)
 
getDistanceBetween(plane, bird) --In this case it will return 100

Printing memory usage to the terminal

A lot of people ask how do i monitor my memory usage? Here is a handy function that will print it neatly to the terminal and format it so it is easy to understand.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
local function printMemUsage()          
        local memUsed = (collectGarbage("count")) / 1000
        local texUsed = system.getInfo( "textureMemoryUsed" ) / 1000000
        
        print("\n---------MEMORY USAGE INFORMATION---------")
    print("System Memory Used:", string.format("%.03f", memUsed), "Mb")
        print("Texture Memory Used:", string.format("%.03f", texUsed), "Mb")
    print("------------------------------------------\n")
     
    return true
end
 
--Usage
 
printMemUsage() --Best to call when you are finished changing scenes once

Replies

Satheesh
User offline. Last seen 1 day 14 hours ago. Offline
Joined: 25 May 2011

Here's a lua implementation of C's ternary operator:

for those who do not know, in C

1
2
3
4
5
if a>10 
  b=a+1;
else
  b=a-1;
end

can be written as
1
b = (a>10)?(a+1):(a-1)

Corresponding lua implementation

1
b = (a>10) and (a+1) or (a-1)

darkconsoles
User offline. Last seen 2 years 29 weeks ago. Offline
Joined: 17 Jan 2011

How to make a Health Bar

If you are new to corona and wandered how to implement health bar to your game( for certain object or enemy), here's my little code:

1
2
3
4
5
health_bar = display.newRect(0,0,200,10)
health_bar:setReferencePoint(display.TopLeftReferencePoint)
health_bar.x = 50; health_bar.y = 10
health_bar:setFillColor(0,255,0)
gameGroup:insert(health_bar)

Point is to change .xScale property of health_bar upon change of enemy's health or something like that, to achieve this we can use next function, presumable that enemy has .health = 100 property

1
2
3
4
5
6
7
8
9
10
11
12
local function onTouch(self,event) -- this can be anything, touch, collision, enterFrame, whatever you want to make your enemy depleting health
 
self.health = self.health - 10 -- or any amount of damage you need
 
if self.health > 0 then
health_bar.xScale = self.health *0.01
--this is simple math. equation that will help you reduce code
end
end
 
enemy.touch = onTouch
enemy:addEventListener("touch", enemy)

peach pellen
User offline. Last seen 1 year 36 weeks ago. Offline
Alumni
Joined: 12 Apr 2011

May also be worth including the memory usage function here;

1
2
3
4
5
6
7
8
9
10
local function monitorMem(event)
     collectgarbage("collect")
     
   print( "\nMemUsage: " .. (collectgarbage("count")/1000) .. " MB")
   print("Texture Usage " .. system.getInfo( "textureMemoryUsed" ) / 1000000)
       
   return true
end
 
Runtime:addEventListener("enterFrame", monitorMem)

Peach :)

ewing
User offline. Last seen 1 year 39 weeks ago. Offline
Alumni
Joined: 13 Jul 2010

Everybody should know that the print function accepts comma separated values so you should never have to use the .. operator in a print function. This is much more efficient too because temporary strings don't have to be created and collected.

1
print("Value of my bool = ", myBool)

@RSCdev
User offline. Last seen 1 year 33 weeks ago. Offline
Joined: 6 Sep 2011

Wow Eric, I did not know that ever! Thanks for it!

"love the commas instead that crazy dots"

:-)

blueboxsoft
User offline. Last seen 1 year 4 weeks ago. Offline
Joined: 19 Jan 2011

Print a LUA table, really useful during development / debug:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
        print_r = function (t, name, indent)
                local tableList = {}
                function table_r (t, name, indent, full)
                        local serial=string.len(full) == 0 and name or type(name)~="number" and '["'..tostring(name)..'"]' or '['..name..']'
                io.write(indent,serial,' = ') 
                        if type(t) == "table" then
                                if tableList[t] ~= nil then
                                        io.write('{}; -- ',tableList[t],' (self reference)\n')
                                else
                                tableList[t]=full..serial
                                if next(t) then -- Table not empty
                                        io.write('{\n')
                                        for key,value in pairs(t) do table_r(value,key,indent..'\t',full..serial) end 
                                        io.write(indent,'};\n')
                                        else io.write('{};\n') end
                                end
                        else
                                io.write(type(t)~="number" and type(t)~="boolean" and '"'..tostring(t)..'"' or tostring(t),';\n') 
                        end
          end
          table_r(t,name or '__unnamed__',indent or '','')
        end

jstrahan
User offline. Last seen 2 hours 23 min ago. Offline
Joined: 29 Jul 2010

winning lottery numbers

10, 15, 32, 41, 44, 3

sorry couldn't help myself

boon
User offline. Last seen 2 years 8 weeks ago. Offline
Joined: 3 Dec 2009

Love this one too, I hate those crazy dot!!

radamanthus
User offline. Last seen 20 weeks 2 days ago. Offline
Joined: 12 Jun 2010

This can get noisy and hard to navigate pretty soon. How about a wiki?

Danny
User offline. Last seen 32 weeks 2 days ago. Offline
Staff
Joined: 17 Aug 2011

Added the following snippets:

Iterating through a key/pair table in order
Shuffling a table
Checking if a file exists
Get distance between two objects
Printing memory usage to the terminal

horacebury
User offline. Last seen 15 hours 37 min ago. Offline
Joined: 17 Aug 2010

Stop 'print()' output when running on a device (improves performance) without removing the print statements in your code:

1
2
3
if (system.getInfo("environment") == "device") then
        print = function() end
end

This may have been in a blog post somewhere, but I can't find it now.

jstrahan
User offline. Last seen 2 hours 23 min ago. Offline
Joined: 29 Jul 2010

using transition.to on a variable

myVal = { myCustomVal = 0 }

transition.to( myVal, { time = 1000, myCustomVal = 10000 })

Naomi
User offline. Last seen 20 hours 1 min ago. Offline
Joined: 6 Jun 2011

Here's a great code snippet that can really help out in spotting unwanted Global variables creeping into your code (courtesy of Ntero):

1
2
3
4
5
local function globalWatch(g, key, value)
    print("GlobalWatch --- ", tostring(key) .. " has been added to _G\n" .. debug.traceback())
    rawset(g, key, value)
end
setmetatable(_G, { __index = globalWatch })

Originally posted by Ntero on http://developer.coronalabs.com/forum/2012/09/19/type-being-redefined#comment-124608

Naomi

Ntero
User offline. Last seen 1 year 35 weeks ago. Offline
Joined: 12 Mar 2012

Here's two that take advantage of Lua's Closures:

1
2
3
4
5
6
local function generateCommand(funcPtr, ...)
    local temp = {n=select('#', ...), ...}
    return function()
        return funcPtr(unpack(temp, 1, temp.n))
    end
end

This first one allows you to take a function, and a variable list of parameters (passed in as generateCommand(function, param1, param2, param3...) and creates a parameterless function that when called will call your original function with all params attached. It's very useful for creating all sorts of variables and linkages on initialization, and then just having behaviours attached to simple callbacks, without having to manage access to all the required parameters. Mostly I use this for button actions, to hookup the entire behaviour on creation but not have a dozen slightly different functions.

1
2
3
4
5
local function wrapParam(funcPtr, param)
    return function(...)
        return funcPtr(param, ...)
    end
end

This one is similar to generateCommand, but it only attaches 1 parameter, and allows you to call the function with additional arguments. A good use case is if you want to have a Corona callback with a 'self' parameters, you can call onPress = wrapParam(self.myFunction, self), and now the Corona callback will be onPress(self, event), or any other parameters you need to attach, rather than just being stuck with the onPress(event) signature. this function can be chained together (pass the result of the function into another wrapParam), to attach multiple parameters.

mpappas
User offline. Last seen 1 day 10 hours ago. Offline
Joined: 31 Jul 2011

Copies a table completely. Pass in a table, it returns a new, unique copy you can modify independently (instead of a typical reference, when assigning in lua).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-- Creates a complete/deep copy of the data
function deepCopy(object)
    local lookup_table = {}
    local function _copy(object)
        if type(object) ~= "table" then
            return object
        elseif lookup_table[object] then
            return lookup_table[object]
        end
        local new_table = {}
        lookup_table[object] = new_table
        for index, value in pairs(object) do
            new_table[_copy(index)] = _copy(value)
        end
        return setmetatable(new_table, getmetatable(object))
    end
    return _copy(object)
end

Snagged this somewhere on the boards, it's fast, it's tight --- pure genius, it's a keeper. That table print up there looks pretty good too.... Hmmm...

TanRu
User offline. Last seen 1 year 22 weeks ago. Offline
Joined: 24 Dec 2012

I was banging my head against the wall trying to figure out how to use sqlite prepared statements, and I finally got it. Hopefully this small example will save someone some time.

1
2
3
4
5
6
7
8
9
-- insert a new item into a specific set and return the id of the new item
function createSetItem(theSetID,theSetItem)
        local stmt = db:prepare([[ INSERT INTO setItems (setID,item) VALUES (:pSetID, :pItem) ]])
        stmt:bind_names({pSetID = theSetID, pItem = theSetItem})
        stmt:step()
        local newID = db:last_insert_rowid()
        print("newID: ", newID)
        return newID
end

stubones99
User offline. Last seen 3 weeks 4 days ago. Offline
Joined: 22 Oct 2011

just in case you didn't notice, the comma adds a tab (or large space) between the first text and the following text. So, it's not the same as a concatenation .. of two strings.

Perhaps there if you used tostring(yourbool) it would concatenate your bool and string into a string.

print("Value of my bool = " .. tostring(myBool))

Viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.