This code in scene1...
local composer = require ( "composer")
local scene = composer.newScene()
local function showScene2()
local options = {
effect = "slideLeft",
time = 130,
}
composer.gotoScene("scene2", options)
end
...is overriding this code, also in scene1...
local object = display.newImage("images/goBackBtn.png", 240, 250)
object.name = "button object"
local function onObjectTap( self, event )
composer.gotoScene( "firstBar1" )
return true
end
object.tap = onObjectTap
object:addEventListener( "tap", object )
sceneGroup:insert( object )
The back button works. It shows the firstBar1 scene, but only for an instant.
Then the next scene, scene2, comes on screen and the slideshow continues. (The order is firstBar1, scene1, scene2, scene3 and so on). All the scenes have a back button to firstBar1.
Why won't the slideshow go back to firstBar1 and stop there? How can I correct it?
This is related to a previous query which one commentator suggested I clarify: "Back button does not navigate to required scene".
Thanks.
Maybe because you have a timer performed on the firstBar scene ..If so, every time you show the firstBar1 scene, you call the showScene2 function() .. so every time you go back to the scene the timer is performed ..
I suggest you pass a param when tapping the back button to stop the timer, or even to decide to use the timer or not.
so I would add to the back button
local function onObjectTap( self, event )
composer.gotoScene( "firstBar1",{params = {timer = "stop"} )
return true
end
on the firstBar scene
local params = event.params
if (params.timer ~="stop") then
timer.performWithDelay(2000, showScene2 )
end
Related
I'm working on a game in which I have a bunch of overlays and one scene which is called game.lua. I wanted to make it, when I press back button (hardware button on Android device), game would, if there's an overlay, close the overlay and if there's no overlay (just game.lua scene), it would show exitmenu.lua(simple pop-up menu).
function onKeyEvent( event )
if(event.keyName == "back") then
local CurrentScene = composer.getSceneName("current")
local CurrentOverlay = composer.getSceneName("overlay")
if CurrentScene == "Scenes.game" and CurrentOverlay == nil then
composer.showOverlay("Scenes.exitmenu", {isModal = true})
return true
elseif CurrentOverlay ~= nil and CurrentOverlay ~= "Scenes.exitmenu" then
composer.hideOverlay("fade", 500)
return true
end
end
end
Runtime:addEventListener("key", onKeyEvent)
What happens is, when I press back button while overlay is on, function hides the overlay and also shows exitmenu.lua overlay. I have no idea what is wrong with my code, any advice is highly appreciated.
EDIT: I've fixed it! I needed to add and event.phase == "down", which makes my button press do function only once. That was the fix.
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.
I am using display.loadRemoteImage to obtain many image from a remote location.
All works fine, but if I click on a button to transition to another scene while 1 (of the many) images is still loading the image gets displayed on the other scene.
I don't want this to happen.
How can I:
cancel the loadRemoteImage before gotoScene
remove all
elements in a new scene that do not belong to that scene. I do not
have an ID since the loadRemoteImage is added into a
display.newGroup()
Cheers
The display.loadRemoteImage() doesn't return an ID that can be used to cancel the download like the network.* functions do. This API call is just a convenience method around network.request. Corona Labs has recently published the code for display.loadRemoteImage() to the documentation here:
http://docs.coronalabs.com/api/library/display/loadRemoteImage.html
You can take that code and modify it so you can cancel the call.
I think its problem of grouping of image which you loaded from loadRemoteImage.
This api will directly load images on scene and comes in front of view. and once you'll switch or remove scene from memory,still it'll stay on view.
You should use network.download for it. it has option to insert your downloaded images on scene groups and you can edit, remove or manipulate with downloaded images.
In networkListener you can insert myImage in your scene groups:
Here is the code block for it:
local function networkListener( event )
if ( event.isError ) then
print( "Network error - download failed" )
elseif ( event.phase == "began" ) then
print( "Progress Phase: began" )
elseif ( event.phase == "ended" ) then
print( "displaying response image file" )
myImage = display.newImage( event.response.filename, event.response.baseDirectory, 60, 40 )
myImage.alpha = 0
transition.to( myImage, { alpha = 1.0 } )
end
end
local params = {}
params.progress = true
network.download(
"http://www.coronalabs.com/demo/hello.png",
"GET",
networkListener,
params,
"helloCopy.png",
system.TemporaryDirectory
)
Either you can disable the next scene button which loading images from network or you can cancel the download network..
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............ :)
When a player has completed a game, i would like for the scene to be restarted, i.e i want to reload the current scene. I have tried storyboard:reloadScene() without success.
I also tried to purge the scene and then reload it, also without any result.
local function onEveryFramePoop()
if(foodBalls) then
for i = foodBalls.numChildren, 1, -1 do
local ball = foodBalls[i]
if(ball.y > 200 and not(ball.isBeingPooped)) then
ball.isBeingPooped = true
local function tempRemove()
if(foodBalls.numChildren)then
ball:removeSelf()
ball = nil
print("removed")
end
end
physics.removeBody(ball)
transition.to(ball, {time = 2000, y = 400, onComplete = tempRemove})
audio.play(fartSound)
end
end
if(foodBalls.numChildren == 0 and food.numChildren == 2) then
reward.playRewardAnimation()
Runtime:removeEventListener("enterFrame", onEveryFramePoop)
timer.performWithDelay(2500, reloadSceneWithDelay)
end
end
end
function reloadSceneWithDelay()
storyboard.gotoScene("levels.levelDigestion") -- **HERE I WANT TO RESTART SCENE**
end
Nothing seems to happen at all. What am i missing here ?
I didn't use storyboard but, you can try this :
Create a black scene in storyboard
Then, when you want to restart, just go to black scene and afterwards to the scene where you want to go.
The problem may be about that you are trying to call a module from itself.