When using 'gotoScene', the scene appears, but the previous scene remains too - lua

I'm currently trying to get an app in Corona to move to a new scene. After much trial and error, and looking at the examples from others, I have got my second scene loading onto the screen.
However, when the second scene is loaded, there is no transition, and the previous scene stays visible too, leaving both scene1 and scene2 visible.
My main.lua file:
local composer = require("composer")
display.setStatusBar(display.HiddenStatusBar)
composer.gotoScene("scene1")
My scene1.lua file:
local composer = require("composer")
local scene = composer.newScene()
function scene:create(event)
local sceneGroup = self.view
local transitionOptions =
{
effect = "fade",
time = 2000
}
local function gotoScene2(event)
composer.gotoScene("scene2", transitionOptions)
end
local rect = display.newRect(display.contentCenterX,
display.contentCenterY, 50, 50)
rect:addEventListener("tap", gotoScene2)
end
scene:addEventListener("create", scene)
return scene
My scene2.lua file:
local composer = require("composer")
local scene = composer.newScene()
function scene:create(event)
local circ = display.newCircle(display.contentCenterX, 100, 25)
end
scene:addEventListener("create", scene)
return scene
I can't figure out what I'm doing wrong, so any help would be great, thanks.

Add
sceneGroup:insert( rect )
at end of scene:create function in scene1.lua file. It also apply to circ in scene2 scene.
From Corona documentation
Remember that you must insert scene display objects into the scene's
self.view group. If you create display objects but do not insert them
into this group, they will reside in front of the Composer stage and
they will not be regarded as part of the scene. For display objects
which should be part of the scene and "managed" by Composer — for
example, cleaned up when the scene is removed — you must insert them
into the scene's self.view group

Related

Corona SDK widget.newButton() not appearing in simulator when inside scene:create

I have the following code:
function scene:create( event )
local sceneGroup = self.view
-- Initialize the scene here.
-- Example: add display objects to "sceneGroup", add touch listeners, etc.
local options1 = {
x = display.contentWidth / 2,
y = 200,
onRelease = button,
lableAlign = "center",
emboss = true,
id = "1",
label = "Button1"
}
local options2 = {
y = 300,
x = display.contentWidth / 2,
onRelease = button,
lableAlign = "center",
emboss = true,
id = "2",
label = "Button2"
}
local button1 = widget.newButton(options1)
local button2 = widget.newButton(options2)
sceneGroup:insert(button1)
sceneGroup:insert(button2)
end
When I place this code in a standalone file (not a scene) the buttons show up as supposed. However now I am turning this standalone file into a scene and for some reason the above code results in nothing in the simulator. Any ideas?
You have two choices:
move your scene the a yourScene.lua file (named as you wish) in which you call storyboard.newScene() (no argument) and in your main.lua you use storyboard.goto('yourScene')
you can create the scene in main.lua via storyboard.newScene('yourScene') and goto it from within main.lua via storyboard.goto('yourScene')
Basically your scene can be in a separate module, corona automatically names it based on module name, and main.lua goes to it, or your scene can be in same module, but then you have to give it a name yourself, and main.lua can "goto" it (within same module). You can even have multiple scenes in same module.
I recommend you have your scenes in separate modules, it just makes for better modularization. Conjecture: maybe the method 2 was the original, and method 1 was added latter when developers found their scenes were getting large and so needed to move them to separate modules.
The code posted above is within the main.lua file. Therefore, the scene is never called. The solution is to rename the file above to something like menu.lua and then call this scene from main.lua.

self.view Objects Cleanup

I am trying to understand how to efficiently remove scene objects once a scene is destroyed. According to corona docs objects can be inserted to self.view in order to clean them up once a scene is destroyed.
Here is my code that I am trying
local composer = require( "composer")
local scene = composer.newScene()
local rects={}
local rectsNum = 0
local rectsCount = 0
local rectsTimer
local sceneGroup
local function rectTransComplete( obj )
print("rectTransComplete .. called")
rectsCount = rectsCount + 1
if rectsCount == 3 then
composer.removeScene("scene2")
end
end
local function spawnRect( )
print("inside spawnrects")
rectsNum = rectsNum + 1
rects[rectsNum] = display.newRect( display.contentWidth/2, 100, 100, 100)
rects[rectsNum]:setFillColor( 1,1,1 )
rects[rectsNum].id = numRect
rects[rectsNum].transition = transition.to( rects[rectsNum], {time = 9000, y = display.contentHeight + 100,
onComplete = rectTransComplete
} )
sceneGroup:insert( rects[rectsNum] )
end
function scene:create( event )
sceneGroup = self.view
end
function scene:show(event)
print("inside create")
if event.phase == "did" then
rectsTimer = timer.performWithDelay( 1000, spawnRect, -1 )
end
end
function scene:hide( event )
-- body
end
function scene:destroy( event )
timer.cancel( rectsTimer )
print("scene Destroyed")
end
scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )
return scene
I seems to work fine since all the rectangles are removed from the screen once the scene is destroyed but I see the app printing messages "rectTransComplete .. called" even after the scene is destroyed. Why is it so and why are the transitions not automatically cancelled once the objects are removed. Do I need to cancel all transitions manually by iterating through all the rectangles and cancel each transition. What about the rects table as it also contains references to the rects. Should I manually clean it up. If I need to manually clean everything (or most of the things), what exactly is the benefit of using self.view
Just a note, you will also have the same problem if you ever use Runtime events to propagate events to your display objects.
I had the same issue a few days ago, there are 2 ways to approach this:
Method 1: You keep a reference to the opened transitions, iterate through all your references and call transition.cancel(transitionReference) on them.
Method 2: You create a listener in your rectangles objects, send a runtime event to the rectangles object when the scene is destroyed that triggers the listener, and inside the listener you "cancel" the transition linked to current rectangle (transition.cancel(rectangle))
You can have a look at this article if you need a howto to work with runtime events: http://www.engelteddy.com/softwaredevelopment/mobiledevelopment/observer-pattern-corona-sdk/
You need to call transition.cancel() in scene:destroy function.

Overlay scene not showing

I have 2 scenes: One main scene with a button, and another scene with only 1 text.
button action in Main Scene:
local options =
{
effect = "fade",
time = 400,
params =
{
sample_var = "anything",
custom = "you want",
data = "here"
}
}
storyboard.showOverlay("inventory", options)
The Overlay Scene:
local storyboard = require("storyboard")
local scene = storyboard.newScene()
function scene:createScene( event )
local group = self.view
local title = display.newText("Inventory", 20, 20, native.systemFont, 16)
title:setTextColor(255,0,0)
group:insert(title)
end
function scene:enterScene( event )
print("enterScene")
end
function scene:exitScene( event )
print("exitScene")
end
function scene:destroyScene( event )
print("destroyScene")
end
scene:addEventListener( "createScene", scene )
scene:addEventListener( "enterScene", scene )
scene:addEventListener( "exitScene", scene )
scene:addEventListener( "destroyScene", scene )
return scene
After pressed the "button", nothing happens (no error). Main Scene is still active & accessible. According to official documentation, a scene should appear after pressing the button.
What did I miss?
Note: Both scene has similar structure (using Storyboard), and button as main scene is created with the following codes:
function scene:createScene( event )
btnInventory = display.newImage("images/btn_right.png", 320, 600)
btnInventory:addEventListener("tap", openInventory)
end
where openInventory is the first code listing.
Should work, I just tried it.
So perhaps you have a typo in the scene file name or is it in a sub-folder ?
If it's in a sub-folder you've got to call :
storyboard.showOverlay("mysubfolder.inventory", options)
End up I found out that the Ceramic Tile Map covers everything (it's just like on topmost layer). If the map is removed, the overlay works fine.
p.s. I found that Director module is easier to use than Storyboard. I switched to it.

In Corona SDK is it possible to use Scenes for a view that partially overlays another view

I have a Settings view that I want to slide over my main game view, but only partially, so that the main view is still visible behind the Settings view (a bit like a modal dialog)
The main game view would then be darkened (or blurred) slightly so its obvious that its not active anymore.
Is it possible to use a Scene to achieve this effect? I would really prefer to keep the code for the Settings view separated from the code for the main view. If not Scenes, then any other suggestions or examples I can look at.
I managed to get it working using the following code in the tap event handler for the button in the source view:
local options =
{
effect = "zoomOutIn",
time = 200,
isModal = true,
}
storyboard.showOverlay( "scenes.settings", options )
Using isModal=true prevents any clicks on the overlay view from propagating down onto the original view which remains displayed underneath the overlay view. Here is a tutorial explaining how to create an overlay view:
http://www.coronalabs.com/blog/2012/04/27/scene-overlays-and-parameter-passing/
Yes it is possible. I'll give you a sample:
-- main.lua --
local storyboard = require "storyboard"
storyboard.gotoScene( "scene1", "fade", 400 )
-- settings.lua --
local function myObject(group,x,y,imagePath)
local image = display.newImage( imagePath )
image.x, image.y = x, y
group:insert( image )
-- add motion (if needed) --
transition.to(image, {time=1000, x=display.contentWidth/2, y=0, transition=easing.inOutQuad})
-- add Listener --
image:addEventListener("touch", function() print("imageClicked") end )
end
local status = { myObject = myObject }
return status
-- Gamemenu.lua -- (This is your game scene)
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
function scene:createScene( event )
-- create a display group --
local screenGroup = self.view
settings.myObject(screenGroup, display.contentWidth/2, -(display.contentHeight/2), "bg.jpg")
screenGroup:insert( bg )
-- require object page --
local settings = require "settings"
-- call object --
settings.myObject(screenGroup, 200, 100, "Icon.png")
end
scene:addEventListener( "createScene", scene )
return scene
Keep Coding............ :)

In Corona SDK the background image always cover other images

I'm currently making a tower defense game with Corona SDK. However, while I'm making the gaming scene, The background scene always cover the monster spawn, I've tried background:toBack() ,however it's doesn't work.Here is my code:
module(..., package.seeall)
function new()
local localGroup = display.newGroup();
local level=require(data.levelSelected);
local currentDes = 1;
monsters_list = display.newGroup()
--The background
local bg = display.newImage ("image/levels/1/bg.png");
bg.x = _W/2;bg.y = _H/2;
bg:toBack();
--generate the monsters
function spawn_monster(kind)
local monster=require("monsters."..kind);
newMonster=monster.new()
--read the spawn(starting point) in level, and spawn the monster there
newMonster.x=level.route[1][1];newMonster.y=level.route[1][2];
monsters_list:insert(newMonster);
localGroup:insert(monsters_list);
return monsters_list;
end
function move(monster,x,y)
-- Using pythagoras to calauate the moving distace, Hence calauate the time consumed according to speed
transition.to(monster,{time=math.sqrt(math.abs(monster.x-x)^2+math.abs(monster.y-y)^2)/(monster.speed/30),x=x, y=y, onComplete=newDes})
end
function newDes()
currentDes=currentDes+1;
end
--moake monster move according to the route
function move_monster()
for i=1,monsters_list.numChildren do
move(monsters_list[i],200,200);
print (currentDes);
end
end
function agent()
spawn_monster("basic");
end
--Excute function above.
timer2 = timer.performWithDelay(1000,agent,10);
timer.performWithDelay(100,move_monster,-1);
timer.performWithDelay(10,update,-1);
move_monster();
return localGroup;
end
and the monster just stuck at the spawn point and stay there.
but, When i comment these 3 lines of code:
--local bg = display.newImage ("image/levels/1/bg.png");
--bg.x = _W/2;bg.y = _H/2;
--bg:toBack();
The problem disappear
Any ideas??Thanks for helping
Since you are using director, you should insert all your display objects into the localGroup.
You haven't inserted bg into localGroup.
SO director class inserts bg finally after inserting localGroup.
Modify your code as
--The background
local bg = display.newImage (localGroup,"image/levels/1/bg.png");
bg.x = _W/2;bg.y = _H/2;
bg:toBack();
or add the code
localGroup:insert(bg)
In more recent versions of Corona SDK:
Composer is the official scene (screen) creation and management library in Corona SDK.... The primary object in the Composer library is the scene object...and it contains a unique self.view.... This self.view is where you should insert visual elements pertaining to the scene.
So now in your scene:create() method, you should insert all DisplayObjects into self.view. It looks like this:
local composer = require( "composer" )
local scene = composer.newScene()
function scene:create()
local sceneGroup = self.view
local bg = display.newImage( ...
bg.x, bg.y = ...
local dude = display.newImage( ...
dude.x, dude.y = ....
sceneGroup:insert(bg)
sceneGroup:insert(dude)
end
The layering of DisplayObjects in this sceneGroup depends on the order in which they are added to the group, with the object added last on top. You can control this ordering with the toBack() and toFront() methods.

Resources