Im trying to implement a levels style page into my app. Im doing an advent calendar style app where there is a calendar page (similar to a level selection page), where the user selects a day and it redirects you to a page displaying a xmas message.
Ive gotten a similar page working using the example I found here;
http://www.christianpeeters.com/corona-sdk/level-selection-template-for-corona-sdk/
However when I implemented this in my app, when I select the day/level available to open, once it is completed the image does not transition to the completed image (a green check), and the day/level next to it is still locked when it should be available.
My code can be found below, and help would be great. Thanks!
Main
require "CiderDebugger";
-- Add a global background
local background = display.newImage("xmasbg.jpg",160, 240,300,480)
local function removeFlake(target)
target:removeSelf()
target = nil
end
local function spawnSnowFlake()
local flake = display.newImage("snowflake.png")
--group:insert(flake)
flake.x = math.random(display.contentWidth)
flake.y = -2
local wind = math.random(80) - 40
transition.to(flake,{time=math.random(3000) + 3000, y = display.contentHeight + 2, x = flake.x + wind, onComplete=removeFlake})
--group:insert(flake)
end
local function makeSnow(event)
if math.random(10) == 1 then -- adjust speed here by making the random number higher or lower
spawnSnowFlake()
end
return true
end
Runtime:addEventListener("enterFrame",makeSnow)
-- Initialize our global variables
--local globals = require( "globals" )
-- main.lua
local storyboard = require( "storyboard" )
storyboard.purgeOnScreenChange = true
storyboard.gotoScene( "menu_scene" )
menu_scene
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
local hohoho = audio.loadSound("xmas.wav")
-- Clear previous scene
storyboard.removeAll()
-- local forward references should go here --
local function buttonHit(event)
audio.play(hohoho)
storyboard.gotoScene(event.target.goto, {effect = "slideRight"})
end
---------------------------------------------------------------------------------
-- BEGINNING OF YOUR IMPLEMENTATION
---------------------------------------------------------------------------------
-- Called when the scene's view does not exist:
function scene:createScene( event )
local group = self.view
--local background = display.newImage("xmasbg.jpg",160, 240,300,480)
--group:insert(background)
local hohoho = audio.loadSound("xmas.wav")
--group:insert(hohoho)
local bgMusic = audio.loadSound("bgmusic.wav")
--group:insert(bgMusic)
local calendarButton = display.newImage("calendarButton.png", 160, 170)
group:insert(calendarButton)
calendarButton:addEventListener("tap", buttonHit)
calendarButton.goto = "calendar_scene"
local creditsButton = display.newImage("creditsButton.png", 160, 250)
group:insert(creditsButton)
creditsButton:addEventListener("tap", buttonHit)
creditsButton.goto = "credits_scene"
local sound = display.newImage("speaker117.png", 290, 495)
group:insert(sound)
local backgroundMusicChannel = audio.play( bgMusic, { channel=1, loops=-1, fadein=5000 } )
--Until Xmas Text
local xmasText = display.newText("Until Christmas", 0, 0, native.systemFontBold, 30)
xmasText: setTextColor( 0, 0,.75)
xmasText.x, xmasText.y = 160, 80
group:insert(xmasText)
--The number of days remaining
local dayText = display.newText( "", 0, 0, native.systemFontBold, 30 )
dayText:setTextColor( 0, 0, .75)
dayText.x, dayText.y = 55, 45
group:insert(dayText)
--The number of hours remaining
local hourText = display.newText( "", 0, 0, native.systemFontBold, 30 )
hourText:setTextColor( 0, 0, .75)
hourText.x, hourText.y = 160, 45
group:insert(hourText)
--The number of minutes remaining
local minutesText = display.newText( "", 0, 0, native.systemFontBold, 30 )
minutesText:setTextColor( 0, 0, .75)
minutesText.x, minutesText.y = 255, 45
group:insert(minutesText)
-- Create labels to indicate what the numbers mean
local dayLabel = display.newText( "Days", 0, 0, native.systemFont, 30 )
dayLabel:setTextColor( 0, 0, .75 )
dayLabel.x = 60; dayLabel.y = 5
group:insert(dayLabel)
local hourLabel = display.newText( "Hours", 0, 0, native.systemFont, 30)
hourLabel:setTextColor( 0, 0, .75 )
hourLabel.x = 160; hourLabel.y = 5
group:insert(hourLabel)
local minuteLabel = display.newText( "Mins", 0, 0, native.systemFont, 30 )
minuteLabel:setTextColor( 0, 0, .75 )
minuteLabel.x = 260; minuteLabel.y = 5
group:insert(minuteLabel)
--Function to update the countdown clock
local function updateTime()
local time = os.date("*t")
local daysLeft = 358 - time.yday
if (daysLeft < 10) then
daysLeft = "0" .. daysLeft
end
dayText.text = daysLeft
local hoursLeft = 23 - time.hour
if (hoursLeft < 10) then
hoursLeft = "0" .. hoursLeft
end
hourText.text = hoursLeft
local minutesLeft = 60 - time.min
if (minutesLeft < 10) then
minutesLeft = "0" .. minutesLeft
end
minutesText.text = minutesLeft
end
--Update the time once immediately to display the correct time
updateTime()
-- Update the clock once per second
local clockTimer = timer.performWithDelay( 1000, updateTime, -1 )
--[[function calendarButton:tap(event)
audio.play(hohoho)
calendarButton:removeSelf()
display.newImage("pushedCalendarButton.png", 160, 170)
end--]]
--[[function creditsButton:tap(event)
storyboard.gotoScene("credits_scene")
audio.play(hohoho)
creditsButton:removeSelf()
--display.newImage("pushedCreditsButton.png", 160, 250)
end]]--
function sound: tap(event)
--[[if(self.status == "playing") then
sound:removeSelf()
display.newImage("mute.png", 290, 495)
audio.pause()
self.status = "paused"
elseif(self.status == "paused") then
display.newImage("speaker117.png", 290, 495)
audio.play()
--self.status = "paused"
end--]]
sound:removeSelf()
display.newImage("mute.png", 290, 495)
audio.stop()
end
--[[local function removeFlake(target)
target:removeSelf()
target = nil
end
local function spawnSnowFlake()
local flake = display.newImage("snowflake.png")
--group:insert(flake)
flake.x = math.random(display.contentWidth)
flake.y = -2
local wind = math.random(80) - 40
transition.to(flake,{time=math.random(3000) + 3000, y = display.contentHeight + 2, x = flake.x + wind, onComplete=removeFlake})
--group:insert(flake)
end
local function makeSnow(event)
if math.random(10) == 1 then -- adjust speed here by making the random number higher or lower
spawnSnowFlake()
end
return true
end
Runtime:addEventListener("enterFrame",makeSnow)--]]
calendarButton:addEventListener("tap", calendarButton)
--creditsButton:addEventListener("tap", creditsButton)
sound:addEventListener("tap", sound)
end
-- Called BEFORE scene has moved onscreen:
function scene:willEnterScene( event )
local group = self.view
end
-- Called immediately after scene has moved onscreen:
function scene:enterScene( event )
local group = self.view
end
-- Called when scene is about to move offscreen:
function scene:exitScene( event )
local group = self.view
end
-- Called AFTER scene has finished moving offscreen:
function scene:didExitScene( event )
local group = self.view
end
-- Called prior to the removal of scene's "view" (display view)
function scene:destroyScene( event )
local group = self.view
end
-- Called if/when overlay scene is displayed via storyboard.showOverlay()
function scene:overlayBegan( event )
local group = self.view
local overlay_name = event.sceneName -- name of the overlay scene
end
-- Called if/when overlay scene is hidden/removed via storyboard.hideOverlay()
function scene:overlayEnded( event )
local group = self.view
local overlay_name = event.sceneName -- name of the overlay scene
end
---------------------------------------------------------------------------------
-- END OF YOUR IMPLEMENTATION
---------------------------------------------------------------------------------
-- "createScene" event is dispatched if scene's view does not exist
scene:addEventListener( "createScene", scene )
-- "willEnterScene" event is dispatched before scene transition begins
scene:addEventListener( "willEnterScene", 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 )
-- "didExitScene" event is dispatched after scene has finished transitioning out
scene:addEventListener( "didExitScene", 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 )
-- "overlayBegan" event is dispatched when an overlay scene is shown
scene:addEventListener( "overlayBegan", scene )
-- "overlayEnded" event is dispatched when an overlay scene is hidden/removed
scene:addEventListener( "overlayEnded", scene )
---------------------------------------------------------------------------------
return scene
calendar_scene
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
local hohoho = audio.loadSound("xmas.wav")
-- Clear previous scene
storyboard.removeAll()
-- local forward references should go here --
levels =
{
1, 2, 2, 2 ,2, --1 means level is open to be played (level.png)
2, 2, 2, 2, 2, --2 means level is locked (locked.png)
2, 2, 2, 2, 2, --3 means level is completed (greenchecked.png)
2, 2, 2, 2, 2,
2, 2, 2, 2, 2,
}
images ={
{ getFile = "gift.png", types = "play"},
{ getFile = "lock.png", types = "locked"},
{ getFile = "greenchecked.png", types = "done"}
}
local function buttonHit(event)
storyboard.gotoScene ( event.target.destination, {effect = "slideLeft"} )
audio.play(hohoho)
print( event.target.destination)
return true
end
---------------------------------------------------------------------------------
-- BEGINNING OF YOUR IMPLEMENTATION
---------------------------------------------------------------------------------
-- Called when the scene's view does not exist:
function scene:createScene( event )
local group = self.view
local levelIndex = 0
for i=0,4 do
for j=1,5 do
tablePlace = i*5 + j
levelIndex = levelIndex + 1
local imagesId = levels[levelIndex]
levelImg = display.newImageRect (images[imagesId].getFile , 50, 50 )
levelImg.x = -22 + (j*62)
levelImg.y = 130+ (i*70)
levelImg.anchorY = .8
group:insert(levelImg)
local levelText = display.newText(tablePlace,0,0,native.systemFont,28)
levelText.x = -22 + (j*62)
levelText.y = 125+ (i*70)
group:insert(levelText)
levelImg.destination = "level0"..tostring(tablePlace)
if images[imagesId].types ~= "locked" then
levelImg:addEventListener("tap", buttonHit)
end
end
end
local heading = display.newText("Christmas Countdown", 0, 0, native.systemFontBold, 31)
heading: setTextColor( .75, 0, 0)
heading.x, heading.y = 160, 35
group:insert(heading)
local backButton = display.newImage("backButton.png", 43, 495)
group:insert(backButton)
backButton:addEventListener("tap", buttonHit)
backButton.destination = "menu_scene"
end
-- Called BEFORE scene has moved onscreen:
function scene:willEnterScene( event )
local group = self.view
end
-- Called immediately after scene has moved onscreen:
function scene:enterScene( event )
local group = self.view
end
-- Called when scene is about to move offscreen:
function scene:exitScene( event )
local group = self.view
end
-- Called AFTER scene has finished moving offscreen:
function scene:didExitScene( event )
local group = self.view
end
-- Called prior to the removal of scene's "view" (display view)
function scene:destroyScene( event )
local group = self.view
end
-- Called if/when overlay scene is displayed via storyboard.showOverlay()
function scene:overlayBegan( event )
local group = self.view
local overlay_name = event.sceneName -- name of the overlay scene
end
-- Called if/when overlay scene is hidden/removed via storyboard.hideOverlay()
function scene:overlayEnded( event )
local group = self.view
local overlay_name = event.sceneName -- name of the overlay scene
end
---------------------------------------------------------------------------------
-- END OF YOUR IMPLEMENTATION
---------------------------------------------------------------------------------
-- "createScene" event is dispatched if scene's view does not exist
scene:addEventListener( "createScene", scene )
-- "willEnterScene" event is dispatched before scene transition begins
scene:addEventListener( "willEnterScene", 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 )
-- "didExitScene" event is dispatched after scene has finished transitioning out
scene:addEventListener( "didExitScene", 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 )
-- "overlayBegan" event is dispatched when an overlay scene is shown
scene:addEventListener( "overlayBegan", scene )
-- "overlayEnded" event is dispatched when an overlay scene is hidden/removed
scene:addEventListener( "overlayEnded", scene )
---------------------------------------------------------------------------------
return scene
level01
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
local widget = require ("widget")
local calendar_scenefile = require ("calendar_scene")
-- local forward references should go here --
local completegameBtn
local function buttonHit(event)
storyboard.gotoScene ( event.target.destination, {effect = "slideLeft"} )
return true
end
-- Called when the scene's view does not exist:
function scene:createScene( event )
local group = self.view
local title = display.newText( "Level 1", 0, 0, "Helvetica", 38 )
title.x = 160
title.y = display.screenOriginY + 40
group:insert(title)
local backBtn = display.newText( "Back", 0, 0, "Helvetica", 25 )
backBtn.x = display.screenOriginX + 50
backBtn.y = display.contentHeight - 30
backBtn.destination = "calendar_scene"
backBtn:addEventListener("tap", buttonHit)
group:insert(backBtn)
end
-- Called immediately after scene has moved onscreen:
function scene:enterScene( event )
local group = self.view
local function btnClicked (event)
--levelProgress = levelProgress + 1
levels[1] = 3
levels[2] = 1
completegameBtn.destination = "calendar_scene"
completegameBtn:addEventListener("tap", buttonHit)
end
completegameBtn = widget.newButton { label = "Complete game", onRelease=btnClicked}
completegameBtn.x = 160
completegameBtn.y = 240
group:insert (completegameBtn)
end
-- Called when scene is about to move offscreen:
function scene:exitScene( event )
local group = self.view
-- INSERT code here (e.g. stop timers, remove listeners, unload sounds, etc.)
-- Remove listeners attached to the Runtime, timers, transitions, audio tracks
end
-- Called prior to the removal of scene's "view" (display group)
function scene:destroyScene( event )
local group = self.view
-- INSERT code here (e.g. remove listeners, widgets, save state, etc.)
-- Remove listeners attached to the Runtime, timers, transitions, audio tracks
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
Try commenting out the calls to removeAll, it is unlikely you need them: purging and removing (unloading) scenes is primarily for saving memory, so the purge and removal functions should only be used for scenes that are rarely re-visited but contain lots of objects. For all other scenes (those visited often, or that don't have lots of objects), they are not necessary, and can lead to subtle bugs as you may be experiencing.
Note that storyboard.purgeOnScreenChange does not exist, you probably intended storyboard.purgeOnSceneChange. But the typo means the setting stayed false, so it is not part of the issue you are experiencing. But if you fix the typo, also comment out that line too in main.lua otherwise it will have same effect.
So comment out any lines that have to do with the storyboard scene purge and removal functions, and if you feel you really need them (because the default Corona behavior is inadequate), then re-introduce in one place and test going between scenes.
Please note that Corona has moved to Composer to manage scenes, instead of Storyboard. That being said, your levels are still locked because the code that draws your levels and sets listeners is in createScene function, which in turn is called only once in your case, as Corona won't call createScene if your scene has not been completely destroyed.
From the docs for scene:create() in Composer (applies to Storyboard as well):
Note that the scene:create() function is only called if the scene’s
view does not exist — that is, it will be called the first time the
scene is loaded. However, Composer tries to keep the scene in memory
assuming that you’ll revisit it later, so if the scene remains in
memory, scene:create() will not be called.
So even though you're modifying global levels table, when you're back in calendar_scene, createScene is NOT being called again. You have 3 choices:
You could move your drawing/setting listeners code to willEnterScene
function, which will be called again when you're back in
calendar_scene, this time with updated values (but it's not a good idea - remember to remove display objects in exitScene, null listeners etc...)
Use storyboard.purgeOnSceneChange (and not purgeOnScreenChange, as
Schollii noticed) and set it to true, this way the scene will be
destroyed when you leave it, meaning that createScene will be called
again when you're back from level selection (better, but again, it's more important to understand scene memory management and code accordingly, than to use short cuts, although sometimes these have valid uses too).
Migrate your code to Composer API, and at the same time, it might be
a good idea to understand scene management. Then draw your level selection, and update as necessary when back from particular level.
Related
I'm working on an app in lua using Corona SDK.
I'm trying to go from my buildscene2 to my mainbuildscene, and I am successfully calling the new scene, but the objects from buildscene2 are not being removed. I have added the code to remove the previous scene, in the mainbuildscene.lua file. I've tried adding it in scene:create() and in scene:show(). Neither worked. This exact method has worked for me when transitioning from other scenes in the same application. What I've done here is created a function that uses composer.gotoScene("mainbuildscene") and then called the function when a button is pressed. I have a bunch of random prints in there just to see if the code is being read. It is.
I've looked for other people having this problem. Plenty of people have experienced this, but none of their solutions have worked for me. I've tried moving the event listener for when the next button is pressed to inside the snapTo function and then back out. If the listener is outside, it gives me an error.
Also, I know that the problem is not when I'm calling the new scene, because I put in a random picture to test if the objects from that scene would show up, and they did, except they were overtop of the objects from buildscene2. I even tried adding a function into the second scene that, when called, destroys the first scene. Didn't work.
Unless I did something wrong, all my display objects in buildscene2 are added to the group.
Here's my buildscene2 file. This is the file I'm transitioning away from and trying to destroy.
local composer = require( "composer" )
local scene = composer.newScene()
-- -----------------------------------------------------------------------------------------------------------------
-- All code outside of the listener functions will only be executed ONCE unless "composer.removeScene()" is called.
-- -----------------------------------------------------------------------------------------------------------------
-- local forward references should go here
-- ------------------------------------------------------------------------------
-- "scene:create()"
function scene:create( event )
local sceneGroup = self.view
-- Initialize the scene here.
-- Example: add display objects to "sceneGroup", add touch listeners, etc.
local group = display.newGroup()
composer.removeScene("thirdscene")
----------EMPTY BOXES
local itemFrame1=display.newImageRect("images/selection-box.png", 200,200)
itemFrame1.x=140
itemFrame1.y=130
group:insert(itemFrame1)
local itemFrame2=display.newImageRect("images/selection-box.png", 200,200)
itemFrame2.x=387
itemFrame2.y=130
group:insert(itemFrame2)
local itemFrame3=display.newImageRect("images/selection-box.png", 200,200)
itemFrame3.x=635
itemFrame3.y=130
group:insert(itemFrame3)
---------------HEADS
local robotHead=display.newImageRect("images/robot-head.png", 195,180)
robotHead.x=137
robotHead.y=130
robotHead.rotation = 180
robotHead.headtype=1
local rabbitHead=display.newImageRect("images/rabbit-head.png", 200, 180)
rabbitHead.x=387
rabbitHead.y=130
rabbitHead.rotation = 180
rabbitHead.headtype=2
local dinoHead=display.newImageRect("images/dino-head.png", 210, 190)
dinoHead.x=665
dinoHead.y=140
dinoHead.rotation = 180
dinoHead.headtype=3
-------------------OTHER
local nextButton=display.newImageRect("images/donebutton.png", 130, 130)
nextButton.x=140
nextButton.y=710
group:insert(nextButton)
nextButton.isVisible = false
local nextText=display.newText("NEXT", 100,100, native.systemFontBold, 40)
nextText.x=140
nextText.y=710
nextText:setTextColor (0,0,0)
group:insert(nextText)
function snapTo (event)
function makeVisible (event)
nextButton.isVisible = true
end
if event.phase == "began" then
event.target.markX = event.target.x -- store x location of object
event.target.markY = event.target.y -- store y location of object
torsoPlaced=event.target.torsoName
end
function addHeadsToGroup (event)
group:insert(robotHead)
group:insert(rabbitHead)
group:insert(dinoHead)
end
if event.phase == "moved" then
local x = (event.x - event.xStart) + event.target.markX
local y = (event.y - event.yStart) + event.target.markY
event.target.x, event.target.y = x, y -- move object based on calculations above
function demolish1 (event)
robotHead.x = 1000
robotHead.y = 900
robotHead.width = 10
robotHead.length = 10
robotHead.isVisible = false
group:insert(robotHead)
local staticRobot = display.newImageRect("images/robot-head.png", 195, 180)
staticRobot.x=137
staticRobot.y=130
staticRobot.rotation = 180
group:insert(staticRobot)
end
function demolish2 (event)
rabbitHead.x = 1000
rabbitHead.y = 900
rabbitHead.width = 10
rabbitHead.length = 10
rabbitHead.isVisible = false
group:insert(rabbitHead)
local staticRabbit = display.newImageRect("images/rabbit-head.png", 200, 180)
staticRabbit.x=387
staticRabbit.y=130
staticRabbit.rotation = 180
group:insert(staticRabbit)
end
function demolish3 (event)
dinoHead.x = 1000
dinoHead.y = 900
dinoHead.width = 10
dinoHead.length = 10
dinoHead.isVisible = false
group:insert(dinoHead)
local staticDino = display.newImageRect("images/dino-head.png", 210, 190)
staticDino.x=665
staticDino.y=140
staticDino.rotation = 180
group:insert(staticDino)
end
if (event.target.headtype == 1) then
event.target.width = 220
event.target.height = 200
if event.target.y > 400 then
event.target.isVisible = false
local newHead1 = display.newImageRect("images/robot-head.png",220, 200)
newHead1.x=150
newHead1.y=500
newHead1.rotation = 270
end
addHeadsToGroup()
makeVisible()
demolish2()
demolish3()
end
if (event.target.headtype == 2) then
event.target.width = 340
event.target.height = 240
if event.target.y > 400 then
event.target.isVisible = false
local newHead2 = display.newImageRect("images/rabbit-head.png",340, 240)
newHead2.x=140
newHead2.y=500
newHead2.rotation = 270
end
addHeadsToGroup()
makeVisible()
demolish1()
demolish3()
end
if (event.target.headtype == 3) then
event.target.width = 280
event.target.height = 250
if event.target.y > 400 then
event.target.isVisible = false
local newHead3 = display.newImageRect("images/dino-head.png",280, 250)
newHead3.x=140
newHead3.y=540
newHead3.rotation = 270
end
addHeadsToGroup()
makeVisible()
demolish1()
demolish2()
end
local function nextButtonClicked2 (event)
if event.phase=="ended" then
function sceneChange (event)
composer.gotoScene("mainbuildscene")
print("jererefs")
end
print("egsijegij")
sceneChange()
end
end
nextButton:addEventListener("touch", nextButtonClicked2)
end
end--end of snapTo
robotHead:addEventListener( "touch", snapTo)
rabbitHead:addEventListener( "touch", snapTo)
dinoHead:addEventListener("touch", snapTo)
end -- end
-- "scene:show()"
function scene:show( event )
local sceneGroup = self.view
local phase = event.phase
if ( phase == "will" ) then
-- Called when the scene is still off screen (but is about to come on screen).
elseif ( phase == "did" ) then
-- Called when the scene is now on screen.
-- Insert code here to make the scene come alive.
-- Example: start timers, begin animation, play audio, etc.
end
end
-- "scene:hide()"
function scene:hide( event )
local sceneGroup = self.view
local phase = event.phase
if ( phase == "will" ) then
-- Called when the scene is on screen (but is about to go off screen).
-- Insert code here to "pause" the scene.
-- Example: stop timers, stop animation, stop audio, etc.
elseif ( phase == "did" ) then
-- Called immediately after scene goes off screen.
end
end
-- "scene:destroy()"
function scene:destroy( event )
local sceneGroup = self.view
-- Called prior to the removal of scene's view ("sceneGroup").
-- Insert code here to clean up the scene.
-- Example: remove display objects, save state, etc.
end
---------------------------------------------------------------------------------
-- Listener setup
scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )
-- ------------------------------------------------------------------ -------------
return scene
Here's my mainbuildscene file, the file I'm trying to load. It's loading in but the previous scene isn't going away.
local composer = require( "composer" )
local scene = composer.newScene()
-- -----------------------------------------------------------------------------------------------------------------
-- All code outside of the listener functions will only be executed ONCE unless "composer.removeScene()" is called.
-- -----------------------------------------------------------------------------------------------------------------
-- local forward references should go here
-- -------------------------------------------------------------------------------
-- "scene:create()"
function scene:create( event )
local sceneGroup = self.view
function removeTheScene (event)
print("this is not working, unless it is...?")
composer.removeScene("buildscene2")
end
removeTheScene()
-- Initialize the scene here.
-- Example: add display objects to "sceneGroup", add touch listeners, etc.
local group=display.newGroup()
--
--
local picture=display.newImageRect("images/bee-torso.png", 100, 100)
picture.x=display.contentCenterX
picture.y=display.contentCenterY
group:insert(picture)
end
-- "scene:show()"
function scene:show( event )
local sceneGroup = self.view
local phase = event.phase
if ( phase == "will" ) then
-- Called when the scene is still off screen (but is about to come on screen).
elseif ( phase == "did" ) then
-- Called when the scene is now on screen.
-- Insert code here to make the scene come alive.
-- Example: start timers, begin animation, play audio, etc.
end
end
-- "scene:hide()"
function scene:hide( event )
local sceneGroup = self.view
local phase = event.phase
if ( phase == "will" ) then
-- Called when the scene is on screen (but is about to go off screen).
-- Insert code here to "pause" the scene.
-- Example: stop timers, stop animation, stop audio, etc.
elseif ( phase == "did" ) then
-- Called immediately after scene goes off screen.
end
end
-- "scene:destroy()"
function scene:destroy( event )
local sceneGroup = self.view
-- Called prior to the removal of scene's view ("sceneGroup").
-- Insert code here to clean up the scene.
-- Example: remove display objects, save state, etc.
end
-- -------------------------------------------------------------------------------
-- Listener setup
scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )
-- -------------------------------------------------------------------------------
return scene
Please let me know what I did wrong or give me any advice you can. Thanks for reading.
You must add them to "sceneGroup". You are adding all the object into your own group but they should be added to the "sceneGroup".
In buildscene2.lua remove these lines:
local group = display.newGroup()
composer.removeScene("thirdscene")
And make sure you add all your display object into the sceneGroup, and not the group:
Change this group:insert(itemFrame1) to this sceneGroup:insert(itemFrame1) but for all your display objects and on all your scenes.
If you're planning to reuse the scene (i.e. being able to go back and forth) you don't need to use the removeScene because Corona handles all the display objects belonging to the scenes i.e. when you go from Scene A to Scene B Corona will automatically move away the display objects belonging to Scene A from the screen and move the display objects belonging to Scene B to the screen.
I cannot change the scene with composer or storyboard. I am trying to change the scene when you touch a row in tableview. I am able to change the scene from the main file to the file with the tableview. The tableview touch is not working though.
Some of my code is below:
local widget = require( "widget" )
local storyboard = require( "storyboard" )
local composer = require( "composer" )
local scene = composer.newScene()
function RowTouch( event )
composer.gotoScene( "thehike" )
end
myTable = widget.newTableView
{
width = display.contentWidth,
height = display.contentHeight,
backgroundColor = { .47, .66, .53 },
topPadding = 0,
hideBackground = false,
onRowRender = onRowRender,
onRowTouch = RowTouch,
noLines = true,
}
for i=1, #hike do
myTable:insertRow{
rowHeight = 220,
isCategory = false,
lineColor = { .47, .66, .53 }
}
end
end
function scene:show( event )
local sceneGroup = self.view
local phase = event.phase
if phase == "will" then
-- Called when the scene is still off screen and is about to move on screen
elseif phase == "did" then
-- Called when the scene is now on screen
--
-- INSERT code here to make the scene come alive
-- e.g. start timers, begin animation, play audio, etc.
end
end
function scene:hide( event )
local sceneGroup = self.view
local phase = event.phase
if event.phase == "will" then
-- Called when the scene is on screen and is about to move off screen
--
-- INSERT code here to pause the scene
-- e.g. stop timers, stop animation, unload sounds, etc.)
elseif phase == "did" then
-- Called when the scene is now off screen
end
end
function scene:destroy( event )
local sceneGroup = self.view
-- Called prior to the removal of scene's "view" (sceneGroup)
--
-- INSERT code here to cleanup the scene
-- e.g. remove display objects, remove touch listeners, save state, etc.
end
---------------------------------------------------------------------------------
-- Listener setup
scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )
-----------------------------------------------------------------------------------------
return scene
Your code does not work for a couple of reasons. You have a dangling end in line 34 and you did not define hike. You probably need a smaller rowHeight in order to show the rows in your view:
local myTable = widget.newTableView
{
left = 0,
top = 0,
height = 330,
width = 300
}
myTable:insertRow(
{
isCategory = false,
rowHeight = 40,
rowColor = rowColor,
lineColor = {.47, .66, .53}
}
)
Also, the documentation is pretty good on this[1].
[1] http://docs.coronalabs.com/api/library/widget/newTableView.html
I am new to lua and corona sdk, and i am using the storyboard api to create an app. i have a main.lua which just sends the user to menu.lua. menu.lua code looks like this:
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
-- include Corona's "widget" library
local widget = require "widget"
-- forward declarations and other locals
local playBtn
-- 'onRelease' event listener for playBtn
local function onPlayBtnRelease()
-- go to level1.lua scene
storyboard.gotoScene( "level1", "fade", 500 )
return true -- indicates successful touch
end
-- Called when the scene's view does not exist:
function scene:createScene( event )
local group = self.view
-- display a background image
local background = display.newImageRect( "background.png", display.contentWidth, display.contentHeight )
background:setReferencePoint( display.TopLeftReferencePoint )
background.x, background.y = 0, 0
-- create/position logo/title image on upper-half of the screen
local titleLogo = display.newImageRect( "logo.png", 264, 42 )
titleLogo:setReferencePoint( display.CenterReferencePoint )
titleLogo.x = display.contentWidth * 0.5
titleLogo.y = 100
-- create a widget button (which will loads level1.lua on release)
playBtn = widget.newButton{
label="Play Now",
labelColor = { default={255}, over={128} },
fontSize = "40",
defaultFile="button.png",
overFile="button-over.png",
width=250, height=80,
onRelease = onPlayBtnRelease -- event listener function
}
playBtn:setReferencePoint( display.CenterReferencePoint )
playBtn.x = display.contentWidth*0.5
playBtn.y = display.contentHeight - 125
-- all display objects must be inserted into group
group:insert( background )
group:insert( titleLogo )
group:insert( playBtn )
end
-- Called immediately after scene has moved onscreen:
function scene:enterScene( event )
local group = self.view
-- INSERT code here (e.g. start timers, load audio, start listeners, etc.)
end
-- Called when scene is about to move offscreen:
function scene:exitScene( event )
local group = self.view
-- INSERT code here (e.g. stop timers, remove listenets, unload sounds, etc.)
end
-- If scene's view is removed, scene:destroyScene() will be called just prior to:
function scene:destroyScene( event )
local group = self.view
if playBtn then
playBtn:removeSelf() -- widgets must be manually removed
playBtn = nil
end
end
-- "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 whenever 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
and this is my level1.lua:
-----------------------------------------------------------------------------------------
--
-- level1.lua
--
-----------------------------------------------------------------------------------------
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
-- include Corona's "physics" library
local physics = require "physics"
physics.start(); physics.pause()
--------------------------------------------
-- forward declarations and other locals
local screenW, screenH, halfW = display.contentWidth, display.contentHeight, display.contentWidth*0.5
-----------------------------------------------------------------------------------------
-- BEGINNING OF YOUR IMPLEMENTATION
--
-- NOTE: Code outside of listener functions (below) will only be executed once,
-- unless storyboard.removeScene() is called.
--
-----------------------------------------------------------------------------------------
-- Called when the scene's view does not exist:
function scene:createScene( event )
local group = self.view
-- create a grass object
local bar= display.newImage( "bar.png", 0, 398)
local function update( event )
local group = self.view
updateBackgrounds()
end
local background1 = display.newImage("images/bg.png")
background1.x = 240
background1.y = 160
local background2 = display.newImage("images/bg.png")
background2.x = 760
background2.y = 160
function updateBackgrounds()
local group = self.view
--near background movement
background1.y = background1.y - (3)
--if the sprite has moved off the screen move it back to the
--other side so it will move back on
if(background1.x < -239) then
background1.x = 760
end
background2.y = background2.y - (3)
if(background2.x < -239) then
background2.x = 760
end
end
--this is how we call the update function, make sure that this line comes after the
--actual function or it will not be able to find it
--timer.performWithDelay(how often it will run in milliseconds, function to call,
--how many times to call(-1 means forever))
timer.performWithDelay(1, update, -1)
end
-- all display objects must be inserted into group
group:insert( background1 )
group:insert( background2 )
group:insert( bar )
-- Called immediately after scene has moved onscreen:
function scene:enterScene( event )
local group = self.view
physics.start()
end
-- Called when scene is about to move offscreen:
function scene:exitScene( event )
local group = self.view
physics.stop()
end
-- If scene's view is removed, scene:destroyScene() will be called just prior to:
function scene:destroyScene( event )
local group = self.view
package.loaded[physics] = nil
physics = nil
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 whenever 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
And here is my error:
When you create the group variable in the updateBackgrounds() method, self.view is nil because self.view only exists in the methods createScene() and enterScene(). What I recommend to do is create a global variable on the beginning of the script called group and then on your createScene method just do group = self.view without the "local" identifier.
Something like this:
--begining of the script
local group
-- Called when the scene's view does not exist:
function scene:createScene( event )
group = self.view
end
this creates a variable called group that has the reference of the self.view variable through all the script.
Another good option is to create a new global group and add it to the self.view on the createScene() method, this keeps things clean.
local globalGroup
function scene:createScene(event)
local group = self.view
globalGroup = display.newGroup()
group:insert(globalGroup)
end
Hope this helps.
This might because functions are not ending properly. Check if you are ending each function in level1.lua.
You are calling a function with a timer, but that function doesn't have access to self.view. Use the "enterFrame" event on Runtime, this is called at every frame:
function scene:enterFrame(event)
local group = self.view
... stuff from update functions ...
end
Runtime.addEventListener("enterFrame", scene)
If you don't need every frame, but say every second frame, put a counter in scene:enterFrame. Or in scene:enterFrame compute how much time since last call to determine if update needed.
local group
Should become
group
so that it is indeed global. Adding the local makes the 'global' become a part of only the body, not the functions, vice versa. If you need Lua practice, Roblox is a good place to start. The provide libraries already in your scripts so that it is easier to code. Try it. ;)
So, I have a program that is using the corona storyboard.
There is scene 1 where the user can type something in a textbox at and there is also another scene, scene 2 where I have some text. The problem is that when the user goes away from the scene with the textbox, the textbox still appears on the screen. I've tried using removeSelf() which does delete it. But the problem is that the textbox is gone forever if i use removeSelf(), even when the user goes back to scene 1, it's still gone!
How could I fix this? Here is the code for scene 1:
--
-- view1.lua
--
-----------------------------------------------------------------------------------------
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
function scene:createScene( event )
local group = self.view
local bg = display.newRect( 0, 0, display.contentWidth, display.contentHeight )
bg:setFillColor(0,255,0 ) -- green
local title = display.newText( "Second View", 0, 0, native.systemFont, 32 )
title:setTextColor( 0 ) -- black
title:setReferencePoint( display.CenterReferencePoint )
title.x = display.contentWidth * 0.5
title.y = 125
local summary = display.newText( "Loaded by the first tab 'onPress' listener\n— specified in the 'tabButtons' table.", 0, 0, 300, 300, native.systemFont, 14 )
summary:setTextColor( 0 ) -- black
summary:setReferencePoint( display.CenterReferencePoint )
summary.x = display.contentWidth * 0.5 + 10
summary.y = title.y + 215
local function textListener( event )
if ( event.phase == "began" ) then
-- user begins editing text field
print( event.text )
elseif ( event.phase == "ended" ) then
-- text field loses focus
elseif ( event.phase == "ended" or event.phase == "submitted" ) then
-- do something with defaulField's text
elseif ( event.phase == "editing" ) then
print( event.newCharacters )
print( event.oldText )
print( event.startPosition )
print( event.text )
end
end
-- Create our Text Field
defaultField = native.newTextField( 150, 150, 180, 30 )
defaultField:addEventListener( "userInput", textListener )
-- all objects must be added to group (e.g. self.view)
group:insert( bg )
group:insert( title )
group:insert( summary )
end
-- Called immediately after scene has moved onscreen:
function scene:enterScene( event )
local group = self.view
-- do nothing
end
-- Called when scene is about to move offscreen:
function scene:exitScene( event )
local group = self.view
-- INSERT code here (e.g. stop timers, remove listenets, unload sounds, etc.)
end
-- If scene's view is removed, scene:destroyScene() will be called just prior to:
function scene:destroyScene( event )
local group = self.view
-- INSERT code here (e.g. remove listeners, remove widgets, save state variables, etc.)
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 whenever 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
So maybe you could use alpha to hide all elements in group?
group.alpha=0
You need to add the text box on the scene:enterScene method and remove it on the scene:exitScene.
Corona calls createScene only once, when creating the scene, but it calls enterScene and exitScene when the scene moves in or out of the stack. These are the places to create/remove elements.
For more information about screen management in corona you can read this. It's main focus is about cleaning up resources used in a scene and the examples are about sounds, but it applies to what you're trying to do and explains a little the Scene Management in Corona.
Basically, I have a table that has images that move horizontally, when I change scenes it stays there, even though I didn't call for it.. As in, on there is no code for it in offlinemode.lua.. I'm thinking that for some reason it's a global element..
Here is main.lua:
local storyboard = require "storyboard"
local options =
{
effect = "slideLeft",
time = 800
}
storyboard.gotoScene( ".Lua.MainMenu", options )
This MainMenu.lua
--//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
--/////// Unamed game (so far) main.lua is GUI/MENU
-- //////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////
--implements the storybord then deletes it upon completeion--
local storyboard = require "storyboard"
storyboard.purgeOnSceneChange = true
--You may began now-- (incorrectly speeleed corrctly)
local scene = storyboard.newScene()
--makes a container for the background--
-- createScene event simply creates a background image
function scene:createScene( event )
local bg = display.newImage( self.view, "background.png" )
end
scene:addEventListener( "createScene" )
--end of aking a container for the background--
--disables the status bar--
display.setStatusBar( display.HiddenStatusBar )
--end of disabling of status bar--
--Returns Screen Width and Screen Height--
_W = display.contentWidth;
_H = display.contentHeight;
--end of returning screen width and height--
--////////////////////////////////////////////////end of the background\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\--
--**********************************************************************************************************************--
--////////////////////////////////////////////////Menu Buttons\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\--
--Set up a local container for the buttons--
local widget = require( "widget" )
local PlayBtn
local function onPlayBtnRelease()
-- go to level1.lua scene
storyboard.gotoScene( ".Lua.offlinemode", "slideLeft", 500 )
display.remove(initstar)
return true -- indicates successful touch
end
local PlayBtn = widget.newButton
{
left = 160,
top = 80,
label = "Offline",
labelAlign = "center",
font = "Arial",
fontSize = 18,
labelColor = { default = {0,0,0}, over = {255,255,255} },
onRelease = onPlayBtnRelease
}
-- "createScene" event is dispatched if scene's view does not exist
scene:addEventListener( "createScene", scene )
--********************************************************************************************************************--
--///////////////////////////////////////Setting up background\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\--
--set up the table to store the clouds in--
local starTable = {}
--end of the table to store the clouds in--
--creates three containers with a picture of a cloud--
function initStar()
local star1 = {}
star1.imgpath = "/images/Cloud1.png"; --Set Image Path for Star
star1.movementSpeed = 10000; --Determines the movement speed of star
table.insert(starTable, star1); --Insert Star into starTable
local star2 = {}
star2.imgpath = "/images/cloud2.png";
star2.movementSpeed = 12000;
table.insert(starTable, star2);
local star3 = {}
star3.imgpath = "/images/cloud3.png";
star3.movementSpeed = 14000;
table.insert(starTable, star3);
end
--ends the function--
--Gets random stars from the table, positioning them randomly--
function getRandomStar()
local temp = starTable[math.random(1, #starTable)] -- Get a random star from starTable
local randomStar = display.newImage(temp.imgpath) -- Set image path for object
randomStar.myName = "star" -- Set the name of the object to star
randomStar.movementSpeed = temp.movementSpeed; -- Set how fast the object will move
randomStar.y = math.random(10,_H) -- Set starting point of star at a random X position
randomStar.x = -40; -- Start the star off screenm
starMove = transition.to(randomStar, { --Move the Clouds
time=randomStar.movementSpeed, --sets the speed relative to it's lifetime
onComplete = function(self) self.parent:remove(self); self = nil; end, -- removes itself
x=500 --speed of ?
}) -- Move the Clouds
end
--The end of this function--
--Starts the timer before the Clouds "spawn"--
function startGame()
starTimer1 = timer.performWithDelay(1070,getRandomStar, 0)
starTimer2 = timer.performWithDelay(2030,getRandomStar, 0)
starTimer3 = timer.performWithDelay(2070,getRandomStar, 0)
end
--ends the function--
initStar()
startGame()
-- "enterScene" event is dispatched whenever scene transition has finished
scene:addEventListener( "enterScene", scene )
-- "exitScene" event is dispatched whenever 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().
function scene:didExitScene( event )
storyboard.purgeScene( "scene1" )
end
scene:addEventListener( "didExitScene" )
return scene
--end the Online function--
and finally offlinemode.lua:
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
local background = display.newImage("background.png")
local image = display.newImage("/images/ButtonStartOffline.png")
function scene:createScene( event )
end
function scene:enterScene( event )
end
function scene:exitScene( event )
end
function scene:destroyScene( event )
end
scene:addEventListener( "createScene", scene )
scene:addEventListener( "enterScene", scene )
scene:addEventListener( "exitScene", scene )
scene:addEventListener( "destroyScene", scene )
return scene
If it works, tell me why it didn't for me please..
you should put the image to the display group either in createScene or enterScene so when you go to another scene it will remove all the image within that scene here's the implementation of the it see the code
function scene:createScene( event )
local group = self.view
--/////////////////////Setting up background\\\\\\\\\\\\\\\\\\--
--set up the table to store the clouds in--
local starTable = {}
--end of the table to store the clouds in--
--creates three containers with a picture of a cloud--
function initStar()
local star1 = {}
star1.imgpath = "/images/Cloud1.png"; --Set Image Path for Star
star1.movementSpeed = 10000; --Determines the movement speed of star
table.insert(starTable, star1); --Insert Star into starTable
local star2 = {}
star2.imgpath = "/images/cloud2.png";
star2.movementSpeed = 12000;
table.insert(starTable, star2);
local star3 = {}
star3.imgpath = "/images/cloud3.png";
star3.movementSpeed = 14000;
table.insert(starTable, star3);
end
--ends the function--
--Gets random stars from the table, positioning them randomly--
function getRandomStar()
local temp = starTable[math.random(1, #starTable)] -- Get a random star from starTable
local randomStar = display.newImage(temp.imgpath) -- Set image path for object
randomStar.myName = "star" -- Set the name of the object to star
randomStar.movementSpeed = temp.movementSpeed; -- Set how fast the object will move
randomStar.y = math.random(10,_H) -- Set starting point of star at a random X position
randomStar.x = -40; -- Start the star off screenm
group:insert(randomStart) **-- inserting random star into Group**
starMove = transition.to(randomStar, { --Move the Clouds
time=randomStar.movementSpeed, --sets the speed relative to it's lifetime
onComplete = function(self) self.parent:remove(self); self = nil; end, -- removes itself
x=500 --speed of ?
}) -- Move the Clouds
end
--The end of this function--
--Starts the timer before the Clouds "spawn"--
function startGame()
starTimer1 = timer.performWithDelay(1070,getRandomStar, 0)
starTimer2 = timer.performWithDelay(2030,getRandomStar, 0)
starTimer3 = timer.performWithDelay(2070,getRandomStar, 0)
end
--ends the function--
initStar()
startGame()
end
Can you try to add " randomStar.y = -100" to your new scene this will not remove them but will take them out of view.
scene:addEventListener( "didExitScene")
Should be :
scene:addEventListener( "didExitScene", scene )
In your last part of the first code snippet