Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Handy Code Snippets
Started by Danny Dec 15 2011 08:48 PM

* * * * * 4 votes
28 replies to this topic
[TOPIC CONTROLS]
Page 1 of 2 1 2
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

Danny

[GLOBAL: userInfoPane.html]
Danny
  • Corona Staff
  • 2,312 posts
  • Jedi

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)[/lua]

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)[/lua]

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:

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)

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.

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:

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

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.

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


uid: 84637 topic_id: 19231 reply_id: 319231


[TOPIC: post.html]
#2

Satheesh

[GLOBAL: userInfoPane.html]
Satheesh
  • Starter
  • PipPipPipPipPipPip
  • 694 posts
  • Jedi

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



for those who do not know, in C
if a>10 
  b=a+1;
else
  b=a-1;
end
can be written as
b = (a>10)?(a+1):(a-1)

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


uid: 64174 topic_id: 19231 reply_id: 74191


[TOPIC: post.html]
#3

darkconsoles

[GLOBAL: userInfoPane.html]
darkconsoles
  • Guests
  • PipPipPipPipPipPip
  • 795 posts
  • Jedi

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:

health_bar = display.newRect(0,0,200,10)health_bar:setReferencePoint(display.TopLeftReferencePoint)health_bar.x = 50; health_bar.y = 10health_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

local function onTouch(self,event) -- this can be anything, touch, collision, enterFrame, whatever you want to make your enemy depleting healthself.health = self.health - 10 -- or any amount of damage you needif self.health > 0 thenhealth_bar.xScale = self.health *0.01--this is simple math. equation that will help you reduce codeendendenemy.touch = onTouchenemy:addEventListener("touch", enemy)

uid: 16142 topic_id: 19231 reply_id: 74194


[TOPIC: post.html]
#4

peach pellen

[GLOBAL: userInfoPane.html]
peach pellen
  • Alumni
  • PipPipPipPipPipPip
  • 8,866 posts
  • Jedi

May also be worth including the memory usage function here;

local function monitorMem(event)     collectgarbage("collect")        print( "\nMemUsage: " .. (collectgarbage("count")/1000) .. " MB")   print("Texture Usage " .. system.getInfo( "textureMemoryUsed" ) / 1000000)          return trueendRuntime:addEventListener("enterFrame", monitorMem)


Peach :)
uid: 52491 topic_id: 19231 reply_id: 74498


[TOPIC: post.html]
#5

ewing

[GLOBAL: userInfoPane.html]
ewing
  • Alumni
  • PipPipPipPipPipPip
  • 1,137 posts
  • Jedi

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.

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

uid: 7563 topic_id: 19231 reply_id: 74506


[TOPIC: post.html]
#6

@RSCdev

[GLOBAL: userInfoPane.html]
@RSCdev
  • Pro
  • PipPipPipPipPipPip
  • 1,489 posts
  • Jedi

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

"love the commas instead that crazy dots"

:-)

uid: 89165 topic_id: 19231 reply_id: 74507


[TOPIC: post.html]
#7

blueboxsoft

[GLOBAL: userInfoPane.html]
blueboxsoft
  • Pro
  • PipPip
  • 17 posts
  • Member

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

	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
uid: 21692 topic_id: 19231 reply_id: 76275


[TOPIC: post.html]
#8

jstrahan

[GLOBAL: userInfoPane.html]
jstrahan
  • Pro
  • PipPipPipPipPipPip
  • 1,922 posts
  • Jedi

winning lottery numbers

10, 15, 32, 41, 44, 3

sorry couldn't help myself
uid: 7911 topic_id: 19231 reply_id: 76278


[TOPIC: post.html]
#9

boon

[GLOBAL: userInfoPane.html]
boon
  • Guests
  • Pip
  • 8 posts
  • Newbie

Love this one too, I hate those crazy dot!!
uid: 4187 topic_id: 19231 reply_id: 93991


[TOPIC: post.html]
#10

radamanthus

[GLOBAL: userInfoPane.html]
radamanthus
  • Starter
  • PipPipPipPipPipPip
  • 50 posts
  • Jedi

This can get noisy and hard to navigate pretty soon. How about a wiki?
uid: 7026 topic_id: 19231 reply_id: 98986


[TOPIC: post.html]
#11

Danny

[GLOBAL: userInfoPane.html]
Danny
  • Corona Staff
  • 2,312 posts
  • Jedi

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
uid: 84637 topic_id: 19231 reply_id: 108079


[TOPIC: post.html]
#12

horacebury

[GLOBAL: userInfoPane.html]
horacebury
  • Pro
  • PipPipPipPipPipPip
  • 2,000 posts
  • Jedi

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

if (system.getInfo("environment") == "device") then	print = function() endend


This may have been in a blog post somewhere, but I can't find it now.
uid: 8271 topic_id: 19231 reply_id: 113737


[TOPIC: post.html]
#13

jstrahan

[GLOBAL: userInfoPane.html]
jstrahan
  • Pro
  • PipPipPipPipPipPip
  • 1,922 posts
  • Jedi

using transition.to on a variable

myVal = { myCustomVal = 0 }

transition.to( myVal, { time = 1000, myCustomVal = 10000 })
uid: 7911 topic_id: 19231 reply_id: 124806


[TOPIC: post.html]
#14

Ntero

[GLOBAL: userInfoPane.html]
Ntero
  • Enterprise
  • PipPipPipPipPipPip
  • 92 posts
  • Jedi

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

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.

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.
uid: 134101 topic_id: 19231 reply_id: 126284


[TOPIC: post.html]
#15

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Pro
  • PipPipPipPipPipPip
  • 2,303 posts
  • Jedi

Here's a great code snippet that can really help out in spotting unwanted Global variables creeping into your code (courtesy of Ntero):
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
uid: 67217 topic_id: 19231 reply_id: 126283


[TOPIC: post.html]
#16

mpappas

[GLOBAL: userInfoPane.html]
mpappas
  • Starter
  • PipPipPipPipPipPip
  • 527 posts
  • Jedi

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).
-- 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...
uid: 79933 topic_id: 19231 reply_id: 131357


[TOPIC: post.html]
#17

TanRu

[GLOBAL: userInfoPane.html]
TanRu
  • Pro
  • Pip
  • 3 posts
  • Newbie

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.

-- 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
uid: 207504 topic_id: 19231 reply_id: 142637


[TOPIC: post.html]
#18

stubones99

[GLOBAL: userInfoPane.html]
stubones99
  • Pro
  • PipPipPipPipPipPip
  • 59 posts
  • Jedi

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))

uid: 99429 topic_id: 19231 reply_id: 144725


[TOPIC: post.html]
#19

stubones99

[GLOBAL: userInfoPane.html]
stubones99
  • Pro
  • PipPipPipPipPipPip
  • 59 posts
  • Jedi

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))

uid: 99429 topic_id: 19231 reply_id: 144725


[TOPIC: post.html]
#20

BeyondtheTech

[GLOBAL: userInfoPane.html]
BeyondtheTech
  • Pro
  • PipPipPipPipPipPip
  • 474 posts
  • Jedi

I like this thread.  Here are some of the favorites I've made, and some I've found and used:

 

either gives you a random result from a selection of choices without having to do an if math.random() then A else B line of code.

Usage: local computerPlayerName = either( "John", "Frank", "Bob", "Melissa", "Joan" )

local function either( ... )
    if #arg == 0 then return nil else return arg[ math.random( #arg ) ] end
end

 

 

 

Multiple rotations of an object got your head spinning like crazy? Turn it into a clean angle of 0-359 using the modulo operator before doing any rotations on it:

local cleanAngle = player.rotation % 360
player.rotation = cleanAngle

 

 

 

angleBetweenPoints gets you, well, the angle between two points:

local function angleBetweenPoints( sX, sY, dX, dY )
    local angleBetween
    local xDist, yDist = dX - sX, dY - sY
    if xDist == 0 then
        print( "Divide by zero!" )
        angleBetween = 0
    else
        angleBetween = math.deg( math.atan( yDist / xDist ) )
        if ( sX < dX ) then
            angleBetween = angleBetween + 90
        else
            angleBetween = angleBetween - 90
        end
        if angleBetween == 0 then angleBetween = -180
        elseif angleBetween == -180 then angleBetween = 0
        end
    end
    return angleBetween
end

 

 

 

freeSpot finds a free spot for your display objects in a table.

Usage: enemy[ freespot( enemy ) ] = display.newImageRect( "enemy1.png", 64, 64 )

local function freeSpot( table )
    local spot, i
    local max = table.maxn( table )
    for i = 1, max do
        if spot == nil and object[ i ].x == nil then spot = i end
    end
    if spot == nil then
        spot = table.maxn( table ) + 1
        print( "No free spot within table, adding to the end, #" .. spot )
    else
        print( "Using free spot #" .. spot )
    end
    return spot
end

 

 

 

clamped quickly sets a low and high range for a given variable:

Usage: energy = clamped( energy + bonus, 0, 100 )

local function clamped( value, lowest, highest )
    return math.max( lowest, math.min( highest, value ) )
end


[TOPIC: post.html]
#21

Hendrix000007

[GLOBAL: userInfoPane.html]
Hendrix000007
  • Pro
  • PipPipPipPipPipPip
  • 121 posts
  • Jedi

Very nice page

I tried to implement "Printing memory usage to the terminal"
I put the function between createScene and enterScene
I tried to call: printMemUsage() but that din´t work


Tested this:


local showMem = function()
print( collectgarbage( "count" ) / 1000 , "MB" )
end
local memTimer = timer.performWithDelay( 1000, showMem, 1 )

--[[ Now you have a handler you can use when removing the timer
and if you like to run it every second to see how mem is building up
just change the last param to 0
You could also put the results into a table and find the max and min of mem usage I guess
... this one works nice in storyboard for me
just put it in enterScene func :)
--]]

[TOPIC: post.html]
#22

jstrahan

[GLOBAL: userInfoPane.html]
jstrahan
  • Pro
  • PipPipPipPipPipPip
  • 1,922 posts
  • Jedi

alternative for string.len

 

text = "hello corona"

print(string.len(text)

print(#text)



[TOPIC: post.html]
#23

wojtekjakubo

[GLOBAL: userInfoPane.html]
wojtekjakubo
  • Starter
  • Pip
  • 5 posts
  • Newbie

I needed a HSL and HSV converter to RGB, so i dig here and there, made my own optimisations and here is the shortest i've managed to get: (mostly inspired by TinyPenguin but with some fixes and shortcuts)

 

 

HSL to RGB:

-- input h-0-360(deg.), s-0-100(%), l-0-100(%)
local function hsl(h, s, l)
	if s == 0 then return l*.01,l*.01,l*.01 end
	local c, h = (1-math.abs(2*(l*.01)-1))*(s*.01), (h%360)/60
	local x, m = (1-math.abs(h%2-1))*c, ((l*.01)-.5*c)
	c = ({{c,x,0},{x,c,0},{0,c,x},{0,x,c},{x,0,c},{c,0,x}})[math.ceil(h)] or {c,x,0}
	return (c[1]+m),(c[2]+m),(c[3]+m)
end

 

 

HSV to RGB:

 

-- input h-0-360(deg.), s-0-100(%), v-0-100(%)
local function hsv(h,s,v)
	if s == 0 then return v*.01,v*.01,v*.01 end
	local c, h = ((s*.01)*(v*.01)), (h%360)/60
	local x, m = c*(1-math.abs(h%2-1)), (v*.01)-c
	c = ({{c,x,0},{x,c,0},{0,c,x},{0,x,c},{x,0,c},{c,0,x}})[math.ceil(h)] or {c,x,0}
	return (c[1]+m),(c[2]+m),(c[3]+m)
end


[TOPIC: post.html]
#24

gazjm

[GLOBAL: userInfoPane.html]
gazjm
  • Pro
  • PipPipPipPipPipPip
  • 141 posts
  • Jedi

Thought I'd share this as it might be usual for others.

 

I needed to detect if I had a good internet connection to prevent my app from hanging when requesting ads on a poor connection.  The existing methods only seemed to work if you had a good connection or no connection, so I came up with the below.  The code could probably be optimised.

 

 

hasInternet = false

function networkListener( event )
if ( event.isError ) then
    timer.cancel(checkTime)
    hasInternet = false
print("NO INTERNET")
else
    timer.cancel(checkTime)
    print("event.response = " .. event.response)
    print("time to live = " .. netTime .. "seconds")
    print("HAS INTERNET")
    hasInternet = true
end
end

params = {}
params.timeout = 3

netTime = 0

function netTimer()
netTime = netTime + .1
end

checkTime = timer.performWithDelay(100,netTimer,0)

checkNet = network.request( "http://www.xxxxxxx.com/check.php", "POST", networkListener,params)
 

 

 

The network request will connect to a php file on my web server, if the server responds within the timeout period, the hasInternet variable is set to true.  If it fails to connect or times out the hasInternet variable is left as false.  The timer function is for testing purposes so you can work out what to set the timeout to.  An acceptable internet connection usually responds in less than 3 seconds, generally 3G is around .75-2

 

the php code is

 

 

<?php

echo "ok";

?>
 

 

I call this on launch, and on a loading screen between games.  I can then use the hasInternet variable to see if I can launch ad's etc without hanging the app.



[TOPIC: post.html]
#25

ksan

[GLOBAL: userInfoPane.html]
ksan
  • Pro
  • PipPipPipPipPipPip
  • 2,712 posts
  • Jedi

@gazjm, this is great! Thank you very much for sharing. 




[topic_controls]
Page 1 of 2 1 2
 
[/topic_controls]