have one image negate the collision detection of another image - lua

i have a water image that kills the user sprite on collision, taking 1 from the lives variable and re-spawns the sprite to the start. i have another image of a raft that constantly spawn new images that move across the screen. im trying to get it so the user can move onto the raft, that is over the water image, and not get re-spawned back to the start.
--sets the function for the death sequence.
function waterCollide(event)
frog.x = display.contentWidth/2
frog.y = 504
isOnRaft = 0
lives = lives - 1
showlives.text = "Lives: "..lives,230,-36,native.systemFont,25
lose()
end
--sets water
water = display.newRect(0,0,320,150)
water.x = display.contentWidth*0.5
water.y = 144
water.alpha = 0
physics.addBody(water,"static", {isSensor = true})
water:addEventListener("collision", function ()timer.performWithDelay(50,waterCollide)end)
--Set log position and movement
local mRandom = math.random
local raft = {"Raft1" ,"Raft2"}
local objectTag = 0
local object = {}
function spawnlogleft()
objectTag = objectTag + 1
local objIdx = mRandom(#raft)
local objName = raft[objIdx]
object[objectTag] = display.newImage(objName..".png")
object[objectTag].x = -96
object[objectTag].y = 216
object[objectTag].name = objectTag
transition.to(object[objectTag], {time = 10000, x = 416, onComplete = function(obj) obj:removeSelf(); obj = nil; end})
physics.addBody( object[objectTag], "static",{isSensor = true})
end
spawnlogleft()
timer.performWithDelay(3500,spawnlogleft,0)
--user sprite details
frog = display.newSprite(frogSheet, sequenceData)
frog.x = display.contentWidth/2
frog.y = 504
physics.addBody( frog, "dynamic", physicsData:get("FrogSheetData"))
frog.isFixedRotation = true
the user sprite is an animation of three frames and a time of 300. any help would be appreciated. and i will provide more details if needed.
thank you

Corona has these neat things called CollisionFilters. They show you how to use them in /Physics/CollisionFilter.
You basically set bits to make certain objects un-collideable with other objects. Check this main.lua example out:
local physics = require("physics")
physics.start()
physics.setScale( 60 )
display.setStatusBar( display.HiddenStatusBar )
local bkg = display.newImage( "stripes.png" )
borderCollisionFilter = { categoryBits = 1, maskBits = 6 } -- collides with (4 & 2) only
borderBodyElement = { friction=0.4, bounce=0.8, filter=borderCollisionFilter }
local borderTop = display.newRect( 0, 0, 320, 1 )
borderTop:setFillColor( 0, 0, 0, 0) -- make invisible
physics.addBody( borderTop, "static", borderBodyElement )
local borderBottom = display.newRect( 0, 479, 320, 1 )
borderBottom:setFillColor( 0, 0, 0, 0) -- make invisible
physics.addBody( borderBottom, "static", borderBodyElement )
local borderLeft = display.newRect( 0, 1, 1, 480 )
borderLeft:setFillColor( 0, 0, 0, 0) -- make invisible
physics.addBody( borderLeft, "static", borderBodyElement )
local borderRight = display.newRect( 319, 1, 1, 480 )
borderRight:setFillColor( 0, 0, 0, 0) -- make invisible
physics.addBody( borderRight, "static", borderBodyElement )
local red = {}
local blue = {}
local redCollisionFilter = { categoryBits = 2, maskBits = 3 } -- collides with (2 & 1) only
local blueCollisionFilter = { categoryBits = 4, maskBits = 5 } -- collides with (4 & 1) only
local redBody = { density=0.2, friction=0, bounce=0.95, radius=43.0, filter=redCollisionFilter }
local blueBody = { density=0.2, friction=0, bounce=0.95, radius=43.0, filter=blueCollisionFilter }
for i = 1,4 do
red[i] = display.newImage( "red_balloon.png", (80*i)-60, 50 + math.random(20) )
physics.addBody( red[i], redBody )
red[i].isFixedRotation = true
blue[i] = display.newImage( "blue_balloon.png", (80*i)-60, 250 + math.random(20) )
physics.addBody( blue[i], blueBody )
blue[i].isFixedRotation = true
end

Related

How to create a heap of balls and keep it within the screen on ground in lua and corona sdk?

How to create a heap of balls and keep it within the screen on the ground in lua and corona sdk?
Right now it is falling down from the screen and disappear from the screen.
local physics = require("physics")
physics.start()
--local sky = display.newImage("sky.png")
--sky:scale( 5, 10 )
--sky.x = -100
--sky.y = -200
local field = display.newImage("field.png")
field:scale( 5, 10 )
field.x = 240
field.y = 470
local sky = display.newImage("sky.png")
sky:scale( 10, 3 )
physics.addBody(field,{friction = 0.5})
field.bodyType = "static"
local football = display.newImage("football.png")
football.x = 180
football.y = 80
football.rotation = 20
physics.addBody(football,{density = 2.0,friction = 0.5,bounce =0.5})
local function fallingball_field()
local football = display.newImage("football.png")
football.x = math.random(400)
football.y = -100
football.rotation = 20
physics.addBody(football, { density = 4.0,friction = 0.5, bounce = 0.5})
end
timer.performWithDelay(200, fallingball_field,200)
In order to put your physics objects within the screen you must create a "Boundary box" that will keep your ball within the screen. Bellow is an example on how to create a boundary:
local physics = require("physics")
physics.start()
physics.setDrawMode("hybrid")
local myCircle = display.newCircle( 100, 100, 30 )
myCircle:setFillColor( 0.5 )
local leftWall = display.newRect(0,display.contentCenterY, 10, display.contentHeight)
local rightWall = display.newRect(display.contentWidth,display.contentCenterY, 10, display.contentHeight)
local bottomWall = display.newRect(display.contentCenterX, display.contentHeight - 25, display.contentWidth, 10)
local topWall = display.newRect(display.contentCenterX, 25, display.contentWidth, 10)
leftWall:setFillColor(nil)
rightWall:setFillColor(nil)
bottomWall:setFillColor(nil)
topWall:setFillColor(nil)
physics.addBody (leftWall, "static", { bounce = 0.1} )
physics.addBody (rightWall, "static", { bounce = 0.1} )
physics.addBody (bottomWall, "static", { bounce = 0.1} )
physics.addBody (topWall, "static", { bounce = 0.1} )
physics.addBody (myCircle, "dynamic", { bounce = 1.5} )
Explanation:
The "walls" will keep your physics objects into place assuming that your app is set to horizontal this will work as is. let me know if your application is vertical.
The physics.setDrawMode("hybrid") will show the physics boundaries of EACH objects that you set with a physics body.It will be easier to see how your objects interact to each other.

AddEventListener: Listener cannot be nil

Can someone please explain what is going wrong here? It went wrong as soon as I added the AddEventListener
newBalloon:addEventListener( "tap", pushBalloon )
Complete Code:
local composer = require( "composer" )
local scene = composer.newScene()
local physics = require( "physics" )
physics.start()
-- Configure image sheet
local positioninsheetOptions = 144.1
local sheetOptions =
{
frames =
{
{
x = 0,
y = 0,
width = 112,
height = 142
},
{
x = 0,
y = positioninsheetOptions,
width = 112,
height = 142
},
{
x = 0,
y = positioninsheetOptions*2,
width = 112,
height = 142
},
{
x = 0,
y = positioninsheetOptions*3,
width = 112,
height = 142
},
{
x = 0,
y = positioninsheetOptions*4,
width = 112,
height = 142
},
{
x = 0,
y = positioninsheetOptions*5,
width = 112,
height = 142
},
{
x = 0,
y = positioninsheetOptions*6,
width = 112,
height = 142
},
{
x = 0,
y = positioninsheetOptions*7,
width = 112,
height = 142
},
{
x = 0,
y = positioninsheetOptions*8,
width = 112,
height = 142
},
{
x = 0,
y = positioninsheetOptions*9,
width = 112,
height = 142
},
{
x = 0,
y = positioninsheetOptions*10,
width = 112,
height = 142
},
},
}
local objectSheet = graphics.newImageSheet( "gameObjects.png", sheetOptions )
local tapCount = 0
local platform
local tapText
local balloonsTable = {}
local leftBorder
local rightBorder
local backGroup
local mainGroup
local uiGroup
local platform
local platform2
local function createBalloon()
local randomBalloon = math.random( 10 )
local newBalloon = display.newImageRect( objectSheet, randomBalloon, 112, 142 )
if newBalloon then
table.insert( balloonsTable, newBalloon )
physics.addBody( newBalloon, "dynamic", { radius=70, bounce=0 } )
newBalloon.myName = "bigBalloon"
newBalloon.alpha = 0.75
newBalloon.gravityScale = randomBalloon/-150
newBalloon:addEventListener( "tap", pushBalloon )
end
local whereFrom = math.random( 3 )
if ( whereFrom == 1 ) then
-- From the left
newBalloon.x = 100
newBalloon.y = display.contentHeight+300
elseif ( whereFrom == 2 ) then
-- From the top
newBalloon.x = 160
newBalloon.y = display.contentHeight+300
elseif ( whereFrom == 3 ) then
-- From the right
newBalloon.x = 220
newBalloon.y = display.contentHeight+300
end
end
local function gameLoop()
-- Create new balloon
createBalloon()
-- Remove balloons which have drifted off screen
for i = #balloonsTable, 1, -1 do
local thisBalloon = balloonsTable[i]
if ( thisBalloon.x < -100 or
thisBalloon.x > display.contentWidth + 100 or
thisBalloon.y < -100 )
then
display.remove( thisBalloon )
table.remove( balloonsTable, i )
end
end
end
local function pushBalloon( event )
local tappedBalloon = event.target
-- balloon:applyLinearImpulse( 0.2, -2, balloon.x, balloon.y )
-- tapCount = tapCount + 1
-- tapText.text = tapCount
if event.phase == "began" then
tappedBalloon.gravityScale = 10
end
end
local function pushBalloon2()
-- balloon:applyLinearImpulse( 0.2, -2, balloon.x, balloon.y )
-- tapCount = tapCount + 1
-- tapText.text = tapCount
balloon2.gravityScale = 10
balloon2:applyLinearImpulse( 0.1, 0, balloon2.x, balloon2.y )
end
local function pushBalloon3()
-- balloon:applyLinearImpulse( 0.2, -2, balloon.x, balloon.y )
-- tapCount = tapCount + 1
-- tapText.text = tapCount
balloon3.gravityScale = 10
balloon3:applyLinearImpulse( -0.1, 0, balloon3.x, balloon3.y )
end
-- -----------------------------------------------------------------------------------
-- Scene event functions
-- -----------------------------------------------------------------------------------
-- create()
function scene:create( event )
local sceneGroup = self.view
-- Code here runs when the scene is first created but has not yet appeared on screen
physics.pause()
local background = display.newImageRect( "background.png", 360, 570 )
background.x = display.contentCenterX
background.y = display.contentCenterY
platform = display.newImageRect( "platform.png", 10, display.contentHeight*5 )
platform.x = -5
platform.y = 0
physics.addBody( platform, "static", { friction=0.5, bounce=0.3 } )
platform2 = display.newImageRect( "platform.png", 10, display.contentHeight*5 )
platform2.x = display.contentWidth+5
platform2.y = 0
physics.addBody( platform2, "static", { friction=0.5, bounce=0.3 } )
createBalloon()
end
-- show()
function scene:show( event )
local sceneGroup = self.view
local phase = event.phase
if ( phase == "will" ) then
-- Code here runs when the scene is still off screen (but is about to come on screen)
elseif ( phase == "did" ) then
gameLoopTimer = timer.performWithDelay( 1250, gameLoop, 0 )
-- Code here runs when the scene is entirely on screen
physics.start()
end
end
-- hide()
function scene:hide( event )
local sceneGroup = self.view
local phase = event.phase
if ( phase == "will" ) then
-- Code here runs when the scene is on screen (but is about to go off screen)
elseif ( phase == "did" ) then
-- Code here runs immediately after the scene goes entirely off screen
physics.pause()
end
end
-- destroy()
function scene:destroy( event )
local sceneGroup = self.view
-- Code here runs prior to the removal of scene's view
end
-- -----------------------------------------------------------------------------------
-- Scene event function listeners
-- -----------------------------------------------------------------------------------
scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )
-- -----------------------------------------------------------------------------------
return scene
Thank you.
You refer to function (pushBalloon) do not exist yet when add event listener. So put definition of function above line you add event listener like that
local function pushBalloon( event )
local tappedBalloon = event.target
-- balloon:applyLinearImpulse( 0.2, -2, balloon.x, balloon.y )
-- tapCount = tapCount + 1
-- tapText.text = tapCount
if event.phase == "began" then
tappedBalloon.gravityScale = 10
end
end
...
newBalloon:addEventListener( "tap", pushBalloon )
At the point in the file where you are adding the listener, pushBalloon() is not defined. You should add a forward declaration earlier in the file:
local scene = ...
local pushBalloon
...
-- createBalloon() and other existing code
...
pushBalloon = function ( event )
-- your function code
end

Expecting a table?

I started learning Corona yesterday so sorry for my ignorance. Can someone please explain why it is "expecting table" on line 108 (physics.addBody( newBalloon, "dynamic", { radius=70, bounce=0.8 } )). All I want it to do is take the image from the object sheet and display it.
local composer = require( "composer" )
local scene = composer.newScene()
local physics = require( "physics" )
physics.start()
-- Configure image sheet
local sheetOptions =
{
frames =
{
{
x = 0,
y = 0,
width = 112,
height = 142
},
{
x = 0,
y = 142,
width = 112,
height = 284
},
{
x = 0,
y = 284,
width = 112,
height = 568
},
{
x = 0,
y = 568,
width = 112,
height = 710
},
{
x = 0,
y = 710,
width = 112,
height = 852
},
{
x = 0,
y = 852,
width = 112,
height = 994
},
{
x = 0,
y = 994,
width = 112,
height = 1136
},
{
x = 0,
y = 1136,
width = 112,
height = 1278
},
{
x = 0,
y = 1278,
width = 112,
height = 1420
},
},
}
local objectSheet = graphics.newImageSheet( "gameObjects.png", sheetOptions )
local tapCount = 0
local platform
local balloon
local balloon2
local balloon3
local tapText
local function createBalloon()
newBalloon = display.newImageRect( mainGroup, objectSheet, 1, 112, 142 )
physics.addBody( newBalloon, "dynamic", { radius=70, bounce=0.8 } )
newBalloon.myName = "Bigballoon"
local whereFrom = math.random( 3 )
if ( whereFrom == 1 ) then
-- From the left
newBalloon.x = 30
newBalloon.y = math.random( display.contentHeight )
elseif ( whereFrom == 2 ) then
-- From the top
newBalloon.x = 60
newBalloon.y = math.random( display.contentHeight )
elseif ( whereFrom == 3 ) then
-- From the right
newBalloon.x = 90
newBalloon.y = math.random( display.contentHeight )
end
end
local function pushBalloon()
-- balloon:applyLinearImpulse( 0.2, -2, balloon.x, balloon.y )
-- tapCount = tapCount + 1
-- tapText.text = tapCount
balloon.gravityScale = 10
balloon:applyLinearImpulse( 0.1, 0, balloon.x, balloon.y )
end
local function pushBalloon2()
-- balloon:applyLinearImpulse( 0.2, -2, balloon.x, balloon.y )
-- tapCount = tapCount + 1
-- tapText.text = tapCount
balloon2.gravityScale = 10
balloon2:applyLinearImpulse( 0.1, 0, balloon2.x, balloon2.y )
end
local function pushBalloon3()
-- balloon:applyLinearImpulse( 0.2, -2, balloon.x, balloon.y )
-- tapCount = tapCount + 1
-- tapText.text = tapCount
balloon3.gravityScale = 10
balloon3:applyLinearImpulse( -0.1, 0, balloon3.x, balloon3.y )
end
-- -----------------------------------------------------------------------------------
-- Scene event functions
-- -----------------------------------------------------------------------------------
-- create()
function scene:create( event )
local sceneGroup = self.view
-- Code here runs when the scene is first created but has not yet appeared on screen
physics.pause()
local background = display.newImageRect( "background.png", 360, 570 )
background.x = display.contentCenterX
background.y = display.contentCenterY
local platform = display.newImageRect( "platform.png", 300, 50 )
platform.x = display.contentCenterX
platform.y = display.contentHeight-25
balloon = display.newImageRect( "balloon.png", 112, 112 )
balloon.x = display.contentCenterX
balloon.y = display.contentCenterY
balloon.alpha = 0.8
balloon2 = display.newImageRect( "balloon.png", 112, 112 )
balloon2.x = display.contentCenterX-100
balloon2.y = display.contentCenterY
balloon2.alpha = 0.8
balloon3 = display.newImageRect( "balloon.png", 112, 112 )
balloon3.x = display.contentCenterX+100
balloon3.y = display.contentCenterY
balloon3.alpha = 0.8
createBalloon()
tapText = display.newText( tapCount, display.contentCenterX, 20, native.systemFont, 40 )
tapText:setFillColor( 0, 0, 0 )
physics.addBody( platform, "static" )
physics.addBody( balloon, "dynamic", { radius=50, bounce=0.6 } )
physics.addBody( balloon2, "dynamic", { radius=50, bounce=0.6 } )
physics.addBody( balloon3, "dynamic", { radius=50, bounce=0.6 } )
balloon:addEventListener( "tap", pushBalloon )
balloon.gravityScale = 0
balloon:setLinearVelocity( 0, -10 )
balloon2:addEventListener( "tap", pushBalloon2 )
balloon2.gravityScale = 0
balloon2:setLinearVelocity( 0, -10 )
balloon3:addEventListener( "tap", pushBalloon3 )
balloon3.gravityScale = 0
balloon3:setLinearVelocity( 0, -10 )
end
-- show()
function scene:show( event )
local sceneGroup = self.view
local phase = event.phase
if ( phase == "will" ) then
-- Code here runs when the scene is still off screen (but is about to come on screen)
elseif ( phase == "did" ) then
-- Code here runs when the scene is entirely on screen
physics.start()
end
end
-- hide()
function scene:hide( event )
local sceneGroup = self.view
local phase = event.phase
if ( phase == "will" ) then
-- Code here runs when the scene is on screen (but is about to go off screen)
elseif ( phase == "did" ) then
-- Code here runs immediately after the scene goes entirely off screen
physics.pause()
end
end
-- destroy()
function scene:destroy( event )
local sceneGroup = self.view
-- Code here runs prior to the removal of scene's view
end
-- -----------------------------------------------------------------------------------
-- Scene event function listeners
-- -----------------------------------------------------------------------------------
scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )
-- -----------------------------------------------------------------------------------
return scene
You should declare newBalloon as local when you initialize it in createBalloon(). Also, mainGroup == nil when you pass it as the parent group to display.newImageRect(). For these reasons, newBalloon is probably nil when you pass it to physics.addBody() instead of being a DisplayObject, which is what that method requires as its first argument.
For safety, in createBalloon(), you could do this:
local newBalloon = display.newImageRect( ... )
if newBalloon then
physics.addBody( newBalloon, ... )
else
print("WARNING: newBalloon is nil in createBalloon")
end
By the way, if you want all the balloons to be in the same GroupObject, you could add this:
local balloonGroup -- forward declaration
...
local function createBalloon()
local newBalloon = display.newImageRect( balloonGroup, ... )
...
end
local scene:create()
...
balloonGroup = display.newGroup()
sceneGroup:insert( balloonGroup )
balloonGroup:toFront()
...
balloonGroup:insert( balloon )
balloonGroup:insert( balloon2 )
...
end

Placing one object in front of another in Corona SDK

I am building a platform jumper, and when the ball passes through the platform, I would like it to appear in front, not behind, the platform. I've tried putting both objects into a new dispaly group in the proper order and sending the ball to the front using toFront(), but I just can't get it to work. Any thoughts?
local ball = display.newCircle( 100, 100, 30 )
ball.id = "ball"
ball.x, ball.y = 160, 350
ball.rotation = 15
local gradient = {
type="gradient",
color1={ 1, 4, 7 }, color2={ .1, 1, 1.5}, direction="down"
}
ball:setFillColor( gradient )
-- add physics to the ball
physics.addBody( ball, "dynamic", { density=1.0,
friction=0.9, bounce=0 } )
-- create a platform w/ physics
local bottom = display.newRect( 0, 0, 320, 100 )
bottom.anchorX = 0
bottom.anchorY = 1
bottom.x, bottom.y = 0, display.contentHeight
physics.addBody( bottom, "static", { friction=0.3 } )
-- put plat in middle
local platform = display.newRect( 0, 0, screenW-100, screenH-450 )
platform.x, platform.y = 160, 200
platform.collType = "passthru"
physics.addBody( platform, "static", { bounce=0.0, friction=0.3 } )
-- place ball in front
local group = display.newGroup( )
group:insert( ball )
group:insert( platform )
ball:toFront( )
your putting the ball in the wrong order, it should be
local group = display.newGroup( )
group:insert( platform )
group:insert( ball )
Take a look at Group Hierarchy

Attempt to index global "self"(a nil value)

I ran this code and it gave me an error attempt to index global 'self' (a nil value), in this scene i'm creating the Question1 of the game, inside which includes creating cannon, balloons and other game elements. I checked but i'm not sure whats wrong here.
function scene.createScene()
local group = self.view ---line 27 where i got the error
scoreText = display.newText( "0", 0, 0, globals.font.bold, 32 )
scoreText.x = display.contentCenterX
scoreText.y = 32
group:insert( scoreText )
background = display.newImage( "bkg_clouds.png")
group:insert(background)
background.x = 240
background.y = 195
questionText = display.newText('a', display.contentCenterX, display.contentWidth/4, native.systemFont, 40)
group:insert(questionText)
infoBar = display.newImage ("infoBar.png")
group:insert(infoBar)
background.x = 200
background.y = 100
restartBtn = display.newImage ("restartBtn.png")
group:insert(restartBtn)
background.x = 470
background.y = 300
cannon = display.newImage ("cannon.png")
group:insert(cannon)
background.x = 10
background.y = 270
cannon.anchorX = 0.5
cannon.anchorY = 0.5
restartBtn.isVisible = true
function createBalloons(a, b)
for i = 1, a do
for j = 1, b do
local balloon = display.newImage ('balloon_fat_red.png', 465+ (i * 30), 80 + (j * 50))
balloon.balloonText1 = display.newText(hiragana_array[x+1], 495, 125)
balloon.balloonText2 = display.newText(hiragana_array[x+2], 495, 175)
balloon.balloonText3 = display.newText(hiragana_array[x+3], 495, 225)
balloon.balloonText1:setFillColor( 1,1, 0 )
balloon.balloonText2:setFillColor( 1,1, 0 )
balloon.balloonText3:setFillColor( 1,1, 0 )
balloon.name = 'balloon'
physics.addBody(balloon)
balloon.bodyType = 'static'
table.insert(balloons, balloon)
end
end
target.text = #balloons
end
function cannonCharge:touch(e)
if(e.phase == 'began') then
impulse = 0
cannon.isVisible = true
Runtime:addEventListener('enterFrame', charge)
end
end
function charge()
local degreesPerFrame = 1
cannon.rotation = cannon.rotation - degreesPerFrame
impulse=impulse-0.2
if(cannon.rotation < -46) then
cannon.rotation = -46
impulse = -3.2
end
end
function shot:touch(e)
if(e.phase == 'ended') then
Runtime:removeEventListener('enterFrame', charge)
cannon.isVisible = false
cannon.rotation = 0
local cannonBall = display.newImage('cannon ball.png', 84, 220)
physics.addBody(cannonBall, {density = 1, friction = 0, bounce = 0})
group:insert(cannonBall)
-- Shoot cannon ball
cannonBall:applyLinearImpulse(dir, impulse, cannonBall.x, cannonBall.y )
--Collision listener
cannonBall:addEventListener ('collision', ballCollision)
end
end
function ballCollision(e)
if (e.other.name == 'balloon') then
scene.updateScore()
e.target:removeSelf()
print ('remove balloon text')
e.other:removeSelf()
audio.play(pop)
end
end
cannonBall:applyLinearImpulse(dir, impulse, cannonBall.x, cannonBall.y )
--Collision listener
cannonBall:addEventListener ('collision', ballCollision)
scene.view:insert( ballCollision )
end
You probably need function scene:createScene(). Note the colon instead of the dot in your original code.
Your function should be like this.
function scene:createScene( event )
local group = self.view
-----------------------------------------------------------------------------
-- CREATE display objects and add them to 'group' here.
-- Example use-case: Restore 'group' from previously saved state.
-----------------------------------------------------------------------------
end
Here is the reference:
http://docs.coronalabs.com/api/library/storyboard/

Resources