Scenes and groups trouble using Lua and Corona SDK - lua

My buttons and scene changes are bugging, the buttons on my titlescreen scene bellow both work and direct to the appropriate screens, but they will only do it once. So I cannot naviagte to options, then back to the the title screen, then back to options again - and I cannot work out why?
Here is my titlescreen file:
module(..., package.seeall)
local assetPath = "assets/"
local mainGroup = display.newGroup()
function new()
local ui = require("ui")
local titleScreen = display.newImageRect(assetPath .. "mainMenu.png", display.contentWidth, display.contentHeight)
titleScreen.x = display.contentWidth / 2
titleScreen.y = display.contentHeight / 2
mainGroup:insert(titleScreen)
local onPlayTouch = function( event )
if event.phase == "release" then
director:changeScene("gameScreen")
end
end
local playButton = ui.newButton{
defaultSrc = assetPath .. "playnowbtn.png",
defaultX = 222,
defaultY = 62,
overSrc = assetPath .. "playnowbtn-over.png",
overX = 222,
overY = 62,
onEvent = onPlayTouch
}
playButton.x = display.contentWidth / 2
playButton.y = 50;
mainGroup:insert( playButton )
local onOptionTouch = function( event )
if event.phase == "release" then
director:changeScene("optionsScreen")
end
end
local optionButton = ui.newButton{
defaultSrc = assetPath .. "playnowbtn.png",
defaultX = 222,
defaultY = 62,
overSrc = assetPath .. "playnowbtn-over.png",
overX = 222,
overY = 62,
onEvent = onOptionTouch
}
optionButton.x = display.contentWidth / 2
optionButton.y = 190;
mainGroup:insert( optionButton )
return mainGroup
end
My options file looks like this :
module(..., package.seeall)
function new()
local assetPath = "assets/"
local localGroup = display.newGroup()
local background = display.newImage (assetPath .."optionsScreen.png")
localGroup:insert(background)
local onBackTouch = function( event )
if event.phase == "release" then
director:changeScene("titleScreen")
end
end
local backButton = ui.newButton{
defaultSrc = assetPath .. "playnowbtn.png",
defaultX = 222,
defaultY = 62,
overSrc = assetPath .. "playnowbtn-over.png",
overX = 222,
overY = 62,
onEvent = onBackTouch
}
backButton.x = display.contentWidth / 2
backButton.y = display.contentHeight / 2
localGroup:insert(backbutton)
return localGroup
end
Now the button is displayed on the options scene and responds to touch, but does not direct back to the titlescreen.
I think I am getting confused with groups and only assigning images to scenes not the whole game?
Can anyone help me out, Thanks.
EDIT:
I'm also getting these runtime errors when clicking the buttons.
Runtime error
/Users/Lewis/Desktop/proj/optionsScreen.lua:30: ERROR: table expected. If this is a function call, you might have used '.' instead of ':'
stack traceback:
[C]: ?
[C]: in function 'insert'
/Users/Lewis/Desktop/proj/optionsScreen.lua:30: in function 'new'
/Users/Lewis/Desktop/proj/director.lua:118: in function 'loadScene'
/Users/Lewis/Desktop/proj/director.lua:415: in function 'changeScene'
/Users/Lewis/Desktop/proj/titlescreen.lua:67: in function 'onEvent'
/Users/Lewis/Desktop/proj/ui.lua:94: in function
?: in function
Runtime error
/Users/Lewis/Desktop/proj/director.lua:151: attempt to call field 'unloadMe' (a nil value)
stack traceback:
[C]: in function 'unloadMe'
/Users/Lewis/Desktop/proj/director.lua:151: in function '_listener'
?: in function
?: in function

I don't use director.lua myself so I'm not 100% sure, but in your options.lua you put the following two lines inside the new() function:
local assetPath = "assets/"
local localGroup = display.newGroup()
However in your titlescreen.lua those lines are above the new() function, and I think that's how it needs to be.
In general you should make your indentation consistent, so that it's easy to notice which code is inside which code-blocks.

In your error print-out, it's asking for an unload me function.
Try adding this to your code (above the return statement) and see if it makes a difference:
function unloadMe()
print( "test" )
end
And see if that gets rid of the error. Another option is to ditch ui.lua and use the new widget library's widget.newButton() function instead. Here's the doc page for that (syntax is almost the same as what you already have, so shouldn't be much changes necessary):
http://developer.anscamobile.com/reference/index/widgetnewbutton

Related

Director Error : The scene name must be a string. scene = nil. CORONA SDK

I am trying my first application in corona using director class but facing problem in my initial code here's my code:
_W = display.contentWidth
_H = display.contentHeight
local director = require("director")
local mainGroup = display.newGroup()
local main = function ()
mainGroup:insert(director.directorView)
director.changeScene("splashscreen")
return true
end
main()
And here is my splashscreen code:
module(..., package.seall)
function new()
local localGroup = display.newGroup ( );
local bgImage = display.newImageRect ( "splash_screen_images.png", _W, _H );
bgImage:setReferencePoint(display.CentreRefrencePoint);
bgImage.x = _W/2;
bgImage.y = _H/2;
localGroup:insert(bgImage);
local delayTimer = timer.performWithDelay ( 3000, changeScreen, 1 )
local function changeScreen1
director:changeScene("meuscreen");
timer.cancel ( delayTimer );
end
return localGroup
end
I am not able to run this code, always getting this error:
Director Error : The scene name must be a string. scene = nil
In your main.lua page, replace the following:
director.changeScene("splashscreen")
with:
director:changeScene("splashscreen")
Note that dot(.) is changed to colon(:)

Lua/Corona Attempt to Index a Boolean Value

It looks like I am having problems with transitioning from my level select page to my first level. I think it might be that I am missing something in my level 1, but I don't know exactly.
levelSelect.lua
module(..., package.seeall)
local director = require ("director")
local physics = require("physics")
physics.start()
local widget = require( "widget" )
-- Function to handle button events
local function handleButtonEventLevel1( event )
local phase = event.phase
if "ended" == phase then
director:changeScene("lvl1")
end
end
--local function goLevel1()
--director:changeScene("lvl1")
--return true
--end
--widget.newButton:addEventListener("tap", goLevel1)
local function handleButtonEventToPage( event )
local phase = event.phase
if "ended" == phase then
director:changeScene("page")
end
end
-- Main function - MUST return a display.newGroup()
function new()
local localGroup = display.newGroup()
local background = display.newImage("bigtestsky.png")
background.x=150
background.y=250
local myButton = widget.newButton
{
left = 25,
top = 25,
width = 100,
height = 50,
defaultFile = "default.png",
overFile = "over.png",
label = "1",
font = "LS",
fontSize = 20,
labelColor = { default = {0,0,50}, over = {0,0,255} },
onEvent = handleButtonEventLevel1,
}
local myButton = widget.newButton
{
left = 25,
top = 415,
width = 100,
height = 50,
defaultFile = "default.png",
overFile = "over.png",
label = "BACK",
font = "LS",
fontSize = 20,
labelColor = { default = {0,0,50}, over = {0,0,255} },
onEvent = handleButtonEventToPage,
}
return localGroup
end
lvl1.lua
local physics = require("physics")
physics.start()
local widget = require( "widget" )
(This is what I mean about missing something in the first level. Could someone please help?)
stack traceback:
[C]: ?
.../myName/Desktop/Bubbles! App/director.lua:116: in function 'loadScene'
.../myName/Desktop/Bubbles! App/director.lua:394: in function 'changeScene'
...myName/Desktop/Bubbles! App/levelSelect.lua:14: in function '_onEvent'
?: in function '?'
?: in function <?:405>
?: in function <?:218>
These are due to some issues with your class: lvl1.lua.
If such error occurs, open director.lua analyse the error return line. This will help you to find what the real problem is.
Here, you must write more lines in your lvl1.lua as below:
module(...,package.seeall) -- If this line is not written, then the package will not be loaded.
function new() -- Module 'lvl1' must have a new() function
local localGroup = display.newGroup() -- The scene should create a display group
local physics = require("physics")
physics.start()
local widget = require( "widget" )
print("Inside lvl1...")
return localGroup; -- And the scene should return the previously created display group.
end
Keep Coding.............. :)

Changing Scenes in Corona objects stay on screen

I have been modifying code from the memory match game to use scenes, sounds, and a 2d table. Adding the scenes has been the hard part. I have it set up to randomly select items from my 2d table. Load those into a temporary table, shuffle them shuffle(), then boardSet(); to load their sounds and place them on the screen. Basically after the game is over I want the scene to reload or go back to the menu to start again. Selecting random data{} elements over and over.
I have tried returning to the menu, or going to a duplicate scene however I can't seem to correctly unload the objects created by my 2d array, as I can't properly add each item into a display group. I have tried everything I can think of. Right now my game loop is setup to add the play again btn that I want to restart the game after one match is found.
This link was a start in the right direction I believe with information about dealing with tables and groups. I still don't know how to cycle thru my 2d table to include everything in a group and then properly unload it.
http://developer.coronalabs.com/content/application-programming-guide-graphics-and-drawing#Variable_References
---------------------------------------------------------------------------------
--
-- level1.lua
--
---------------------------------------------------------------------------------
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
local widget = require "widget"
---------------------------------------------------------------------------------
-- BEGINNING OF YOUR IMPLEMENTATION
---------------------------------------------------------------------------------
local image, text1, text2, text3, memTimer
-- forward declarations and other locals
local againBtn
-- 'onRelease' event listener for playBtn
local function onPlayBtnRelease()
-- go to level1.lua scene
storyboard.gotoScene( "menu", "fade", 500 )
return true -- indicates successful touch
end
-- Preload the sound file (needed for Android)
--
local playBeep = function( testSound )
media.playEventSound( testSound )
end
---Preload sounds
ki = audio.loadSound("ki-nawaneyoo.mp3")
u = audio.loadSound("u.mp3")
mayuhoo = audio.loadSound("mayuhoo.mp3")
--End Sound Test
--Set Global width and height variables
_W = display.contentWidth;
_H = display.contentHeight;
---Count number of correct matches
local matchCount = 0;
--Hide status bar
display.setStatusBar(display.HiddenStatusBar);
--Declare a totalButtons variable to track number of buttons on screen
local totalButtons = 0
--Declare variable to track button select
local secondSelect = 0
local checkForMatch = false
--Declare Data Table
local data = {}
--Load objects into data
data[1] = {}
data[1].title = "Naka"
data[1].subtitle = "a"
data[1].image = "a.png"
data[1].image1 = "ear.png"
data[1].sound = "naka-ear.caf"
data[1].sound1 = "naka-ear.mp3"
data[2] = {}
data[2].title = "Aapuhu"
data[2].subtitle = "aa"
data[2].image = "aa.png"
data[2].image1 = "eyebrow.png"
data[2].sound = "aapuhu-eyebrow.caf"
data[2].sound1 = "aapuhu-eyebrow.mp3"
data[3] = {}
data[3].title = "Ego"
data[3].subtitle = "Ego"
data[3].image = "e.png"
data[3].image1 = "tongue.png"
data[3].sound = "ego-tongue.caf"
data[3].sound1 = "ego-tongue.mp3"
data[4] = {}
data[4].title = "Kamoo"
data[4].subtitle = "kamoo"
data[4].image = "ee.png"
data[4].image1 = "chin.png"
data[4].sound = "kamoo-chin.caf"
data[4].sound1 = "kamoo-chin.mp3"
data[5] = {}
data[5].title = "Kowpa"
data[5].subtitle = "ego"
data[5].image = "leg.png"
data[5].image1 = "leg.png"
data[5].sound = "kowpa-leg.caf"
data[5].sound1 = "kowpa-leg.mp3"
data[6] = {}
data[6].title = "Mae"
data[6].subtitle = "kwa"
data[6].image = "hand.png"
data[6].image1 = "hand.png"
data[6].sound = "mae-hand.caf"
data[6].sound1 = "mae-hand.mp3"
data[7] = {}
data[7].title = "Nodo"
data[7].subtitle = "kwe"
data[7].image = "kwe.png"
data[7].image1 = "throat.png"
data[7].sound = "nodo-throat.caf"
data[7].sound1 = "nodo-throat.mp3"
data[8] = {}
data[8].title = "Matogo"
data[8].subtitle = "kwe"
data[8].image = "kwe.png"
data[8].image1 = "thumb.png"
data[8].sound = "matogo-thumb.caf"
data[8].sound1 = "matogo-thumb.mp3"
data[9] = {}
data[9].title = "Matzehe"
data[9].subtitle = "kwe"
data[9].image = "kwe.png"
data[9].image1 = "elbow.png"
data[9].sound = "matzehe-eblow.caf"
data[9].sound1 = "matzehe-elbow.mp3"
data[10] = {}
data[10].title = "Kuku"
data[10].subtitle = "kwe"
data[10].image = "kwe.png"
data[10].image1 = "foot.png"
data[10].sound = "kuku-foot.caf"
data[10].sound1 = "kuku-foot.mp3"
--Declare button, buttonCover, and buttonImages table
local tableCopy = {}
local buttonImages = {}
--Shuffle data table
--local shuffleSet = function()
--Shuffle data table
math.randomseed (os.time())
local function shuffle(a)
local n = #a
local t
local k
while(n > 0) do
t = a[n]
k = math.random(n)
a[n] = a[k]
a[k] = t
n = n - 1
end
return a
end
local tableCopy = shuffle(data);
local button = {}
local buttonCover = {}
--Choose six random objects from data to be used in game.
local firstSix = {}
for i = 1,6 do
firstSix[i] = tableCopy[i];
end
local buttonImages = {firstSix[1],firstSix[1],firstSix[2],firstSix[2],firstSix[3],firstSix[3],firstSix[4],firstSix[4],firstSix[5],firstSix[5],firstSix[6],firstSix[6]}
--end
--Declare and prime a last button selected variable
local lastButton;-- = display.newImage("1.png");
--lastButton.myName = 1;
--
--Set up simple off-white background
--Notify player if match is found or not
local matchText = display.newText(" ", 0, 0, native.systemFont, 65)
matchText:setReferencePoint(display.CenterReferencePoint)
matchText:setTextColor(255, 255, 255)
matchText.x = _W/2
--
--Set starting point for button grid
local x = -20
local matchesFound = 0;
--Set up game function
local function game(object, event)
if(event.phase == "began") then
if(checkForMatch == false and secondSelect == 0) then
--Flip over first button
buttonCover[object.number].isVisible = false;
audio.play(object.sound);
lastButton = object
checkForMatch = true
elseif(checkForMatch == true and object.number ~= lastButton.number) then
if(secondSelect == 0) then
--Flip over second button
buttonCover[object.number].isVisible = false;
secondSelect = 1;
--If buttons do not match, flip buttons over
if(lastButton.myName ~= object.myName) then
audio.play(object.sound);
timer.performWithDelay(1000,function()
matchText.text = "Ki Nawa'neyoo";
audio.play(ki); end,1)
timer.performWithDelay(2500, function()
matchText.text = " ";
checkForMatch = false;
secondSelect = 0;
buttonCover[lastButton.number].isVisible = true;
buttonCover[object.number].isVisible = true;
end, 1)
--If buttons DO match, remove buttons
elseif(lastButton.myName == object.myName) then
matchText.text = "U " .. object.myName .. " Mayuhoo";
audio.play(u)
timer.performWithDelay(750,function()
audio.play(object.sound); end, 1)
timer.performWithDelay(1500,function()
audio.play(mayuhoo); end, 1)
timer.performWithDelay(2400, function()
matchText.text = " ";
checkForMatch = false;
secondSelect = 0;
lastButton:removeSelf();
object:removeSelf();
buttonCover[lastButton.number]:removeSelf();
buttonCover[object.number]:removeSelf();
matchesFound = matchesFound + 1;
timer.performWithDelay(250, function()
if (matchesFound == 1) then
matchText.text = " Play Again? ";
againBtn.isVisible = true;
-- all display objects must be inserted into group
--group:insert( playBtn )
end
end, 1)
end, 1)
end
end
end
end
end
--]]
-- Touch event listener for background image
--[[
local function onSceneTouch( self, event )
if event.phase == "began" then
storyboard.gotoScene( "scene2", "slideLeft", 800 )
return true
end
end
--]]
-- Called when the scene's view does not exist:
function scene:createScene( event )
local screenGroup = self.view
local image = display.newImageRect( "bg.png", display.contentWidth, display.contentHeight )
image:setReferencePoint( display.TopLeftReferencePoint )
image.x, image.y = 0, 0
screenGroup:insert( image )
local function boardSet()
for count = 1,3 do
x = x + 100 * 2
y = 20 *2
for insideCount = 1,4 do
y = y + 90 * 2
--Assign each image a random location on grid
local temp = math.random(1,#buttonImages)
button[count] = display.newImageRect(buttonImages[temp].image1, 150, 150);
--Position the button
button[count].x = x;
button[count].y = y;
--Give each a button a name
button[count].myName = buttonImages[temp].title
-- Preload the sound file (needed for Android)
--Give each button a sounds
soundID = audio.loadSound(buttonImages[temp].sound1)
button[count].sound = soundID
button[count].sound1 = soundID
button[count].number = totalButtons
--Remove button from buttonImages table
table.remove(buttonImages, temp)
--Set a cover to hide the button image
buttonCover[totalButtons] = display.newImageRect("button.png", 150, 150);
buttonCover[totalButtons].x = x; buttonCover[totalButtons].y = y;
--screenGroup:insert(button[count].)
totalButtons = totalButtons + 1
--Attach listener event to each button
button[count].touch = game
button[count]:addEventListener( "touch", button[count] )
end
end
end
boardSet();
end
-- Called immediately after scene has moved onscreen:
function scene:enterScene( event )
againBtn = widget.newButton{
label="Play Again?",
fontSize = 25,
labelColor = { default={255}, over={128} },
default="button1.png",
over="button-over.png",
width=250, height=100,
onRelease = onPlayBtnRelease -- event listener function
}
againBtn:setReferencePoint( display.CenterReferencePoint )
againBtn.x = display.contentWidth * 0.5
againBtn.y = display.contentHeight - 125
againBtn.isVisible = false
print( "1: enterScene event" )
-- remove previous scene's view
end
-- Called when scene is about to move offscreen:
function scene:exitScene( event )
print( "1: exitScene event" )
if againBtn then
matchText.text = " "
againBtn:removeSelf() -- widgets must be manually removed
button = nil
buttonCover = nil
firstSix = nil
data = nil
tableCopy = nil
buttonImages = nil
againBtn = nil
end
end
-- Called prior to the removal of scene's "view" (display group)
function scene:destroyScene( event )
local screenGroup = self.view
storyboard.removeScene();
--storyboard.purgeScene( "level1" )
print( "((destroying scene 1's view))" )
end
---------------------------------------------------------------------------------
-- END OF YOUR IMPLEMENTATION
---------------------------------------------------------------------------------
-- "createScene" event is dispatched if scene's view does not exist
scene:addEventListener( "createScene", scene )
-- "enterScene" event is dispatched whenever scene transition has finished
scene:addEventListener( "enterScene", scene )
-- "exitScene" event is dispatched before next scene's transition begins
scene:addEventListener( "exitScene", scene )
-- "destroyScene" event is dispatched before view is unloaded, which can be
-- automatically unloaded in low memory situations, or explicitly via a call to
-- storyboard.purgeScene() or storyboard.removeScene().
scene:addEventListener( "destroyScene", scene )
---------------------------------------------------------------------------------
return scene
Yeah, this is simple.
here is an example(assuming that you have implemented storyboard)
function scene:createScene(event)
screenGroup = self.view
local image = display.newImage("image.png")
screenGroup:insert(image)
end
Now everything will go fine :)
Add all the display objects to a group.local myGroup = display.newGroup();
local img = display.newImage("yourimage.png");
myGroup:insert(img);
For example
If you follow this method, all display objects will not be flushed out of memory when you change the screen.
When using corona storyboard you need to add display objects to the group. For example you would need to add all of your display objects into screenGroup in order for them to be removed when you change scenes.

Corona SDK Ui Button for Main Menu

I'm kinda new in using Corona SDK and I'm having a little problem on my main menu buttons. Whenever I press the buttons, it doesn't move or change the view; the buttons just disappear in the title screen.
module(..., package.seeall)
local ui = require ("ui")
local ui = require ("director")
local assetPath = "assets/"
local mainGroup = display.newGroup()
function new(params)
local titleScreen = display.newImageRect(assetPath .. "Law of Magic.jpg",
display.contentWidth, display.contentHeight)
titleScreen.x = display.contentWidth / 2
titleScreen.y = 265
mainGroup:insert(titleScreen)
director:changeScene("titleScreen")
local newgame = ui.newButton{ default = assetPath .. "new game.png",
onRelease = function(event) director:changeScene("New game") end,}
newgame.x = display.contentWidth / 2
newgame.y = 445
mainGroup:insert(newgame)
local continue = ui.newButton{ default = assetPath .. "continue.png",
onRelease = function(event) director:changeScene("Continue") end,}
continue.x = display.contentWidth / 2
continue.y = 447
mainGroup:insert(continue)
local option = ui.newButton{ default = assetPath .. "option.png",
onRelease = function(event) director:changeScene("Option") end,}
option.x = display.contentWidth / 2
option.y = 449
mainGroup:insert(option)
local help = ui.newButton{ default = assetPath .. "help.png",
onRelease = function(event) director:changeScene("Help") end,}
help.x = display.contentWidth / 2
help.y = 451
mainGroup:insert(help)
local exitgame = ui.newButton{ default = assetPath .. "exit game.png",
onRelease = function(event) director:changeScene("Exit game") end,}
exitgame.x = display.contentWidth / 2
exitgame.y = 453
mainGroup:insert(exitgame)
return mainGroup
end
First I see you declare local ui two times.
Second you should use storyboard since it is supported by corona and you are new to coronaSDk
Also for this: director:changeScene("New game")
It's going to try and go to a scene, you are putting the name of the scene file. In this case, it's looking for a file called:
New Game.lua
in the same folder as your main.lua file. I personally would avoid filenames with spaces in them, and while the simulator isn't case sensitive, devices are and you have to make sure the filenames case matches what you are coding.
Also I'm concerned about this line: director:changeScene("titleScreen")
It would try to change scenes before you ever get to setting up your buttons.
Change this line
local ui = require ("director")
to
local director = require ("director")
And yeah make sure the file names are correct.

Runtime error in OOP class (Corona)

New to Corona (coming from Actionscript) and trying to work through some OOP tutorials to create reusable modules for my app. Currently working on a number picker, which seems to be working, but also throwing an error when I press the buttons. Here's the code for the 'numberPicker.lua':
local numberPicker = {}
local numberPicker_mt = { __index = numberPicker } -- metatable
widget = require "widget"
-------------------------------------------------
-- PUBLIC FUNCTIONS
-------------------------------------------------
function numberPicker.new() -- constructor
local newNP = display.newGroup()
local value = 0
local function dec()
print("dec")
if value > 0 then
value = value - 1
valueText.text = value
end
end
local function inc()
print("inc")
if value < 100 then
value = value + 1
valueText.text = value
end
end
decrement = widget.newButton{
default="gfx/dec_normal.png",
over="gfx/dec_press.png",
width=58, height=58,
onRelease = dec
}
valueText = display.newText(value, 70, 10, native.systemFont, 40)
valueText:setTextColor(0, 0, 0)
increment = widget.newButton{
default="gfx/inc_normal.png",
over="gfx/inc_press.png",
width=58, height=58,
onRelease = inc
}
increment.x = 140
newNP:insert(decrement.view)
newNP:insert(valueText)
newNP:insert(increment.view)
return setmetatable( newNP, numberPicker_mt )
end
return numberPicker
usage:
local numberPicker = require( "numberPicker" )
local lengthPicker = numberPicker.new()
scrollView:insert(lengthPicker)
When I press either button, I get the following error printing out twice:
Runtime error
attempt to call a nil value
stack traceback:
[C]: ?
Any clues anyone?
Thanks,
Emma.
"scrollView" variable was not initialized.

Resources