Corona SDK game scenes - events

I looked in many other questions and tutorials, but sadly, without result.
I am trying to go from scene1 to scene2 with event listener and I am copying the code which was given in the project. The only difference between my button and the working one is that I declare mine in the lua file and it does not exist in the scene1.ccscene
Do I have to put an image as an object in scene1.csscene in order to use it as a button?
the code I try:
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
local start_button = display.newImage("START.png") --start button
-- -------------------------------------------------------------------------------
-- "scene:create()"
function scene:create( event )
local sceneGroup = self.view
-- Initialize the scene here.
-- Example: add display objects to "sceneGroup", add touch listeners, etc.
start_button.x=200
start_button.y=150
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.
function nextScene:touch ( event )
local phase = event.phase
if "ended" == phase then
composer.gotoScene( "scene2", { effect = "fade", time = 300 } )
end
end
start_button:addEventListener( "touch", nextScene )
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.
if nextSceneButton then
start_button:removeEventListener( "touch", nextScene )
end
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

The extension of the scene files needs to be ".lua" in Corona. I think "csscene" has something to do with Cocoa.
The code below will work.
Notes:
Make sure that the files ends with .lua (main.lua, scene1.lua, scene2.lua).
start_button is now a rectangle but you can easy change it to an image.
start_button is added into sceneGroup. This is the group that the scene will use i.e. when you change the scene all objects in the sceneGroup will be handled properly.
I add the eventListener in a different way, please read the documentation for more information: https://docs.coronalabs.com/api/event/touch/index.html
main.lua:
local composer = require( "composer" )
composer.gotoScene("scene1")
scene1.lua:
local composer = require( "composer" )
local scene = composer.newScene()
-- VARIABLES
local start_button
-- EVENTS
local function onTouchStartButton( event )
if event.phase == "ended" then
composer.gotoScene( "scene2" )
end
end
function scene:create( event )
local sceneGroup = self.view
-- Create the start_button
start_button = display.newRect( 100, 100, 100, 100 )
-- Make sure you insert the button into the sceneGroup
sceneGroup:insert( start_button )
-- Set position of start_button
start_button.x=200
start_button.y=150
-- Add the event listener in the "create" stage instead of the show state
-- Now the start_button is in the scene_group so there is no need to remove
-- the touch listener under the "destroy" stag
start_button:addEventListener( "touch", onTouchStartButton )
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
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
scene2.lua:
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.
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).
print("Now we are in scene2.lua!")
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

Related

How to make a GUI fade in roblox studio?

Hello roblox studio scripters,
I'm a intermediate scripter-builder and need some help with the gui for my game.
I have a start screen with a play button like this:
I'm trying to fade out the gui when the button is clicked, but none of the tutorials worked. This is my script for the button:
local button = script.Parent
local gui = script.Parent.Parent.Parent
button.MouseButton1Down:Connect(function()
gui.Enabled = false
end)
I don't know how to do the changing, would it be BackgroundTransparency? How would you change the transparency from 0 to 1 in 0.01 increments?
I tried to make the gui fade with a for loop, changing the BackgroundTransparency but that didn't work, this is that code:
local button = script.Parent
local gui = script.Parent.Parent.Parent
button.MouseButton1Down:Connect(function()
for i = 0, 100, 1 do
gui.Frame.BackgroundTransparency + 0.01
wait(0.01)
gui.Enabled = false
end
end)
I don't know why it isn't working.
If I have a typo or something, please tell me.
Thanks!
The loop solution has a few typos, here it is fixed:
local button = script.Parent
local gui = script.Parent.Parent.Parent
button.MouseButton1Down:Connect(function()
for i = 0, 100 do
gui.Frame.BackgroundTransparency += 0.01 -- += adds 0.01 each time
task.wait(0.01) -- better than wait(0.01)
end
gui.Enabled = false
end)
However, this is not an ideal solution. A better system would use Roblox's TweenService to change the gui's transparency. Tweens are less jittery, are easier to modify, and have lots of customisation properties including repeating, changing length of time, and style of easing (e.g. going faster at first, then slower near the end; see Easing Styles on the Roblox docs).
local TweenService = game:GetService("TweenService")
local button = script.Parent
local gui = script.Parent.Parent.Parent
local tweenInfo = TweenInfo.new(
2, -- Time
Enum.EasingStyle.Linear, -- Easing Style
Enum.EasingDirection.Out -- Easing Direction
-- See https://create.roblox.com/docs/reference/engine/datatypes/TweenInfo for more available properties
)
local tween = TweenService:Create(
gui.Frame, -- Instance to tween
tweenInfo, -- TweenInfo
{ Transparency = 1 } -- What we want to change
)
button.MouseButton1Down:Connect(function()
tween:Play()
tween.Completed:Wait() -- Wait until tween is complete
gui.Enabled = false
end)
Though both of these solutions change only the transparency of the background, so the child elements, such as the Playbutton, will stay visible until the gui is disabled. You may wish to replace the Frame with a CanvasGroup, which also changes the transparency of its children when its GroupTransparency property is changed.
local tween = TweenService:Create(
gui.CanvasGroup, -- Instance to tween
tweenInfo, -- TweenInfo
{ GroupTransparency = 1 } -- What we want to change
)

Remove a screenGUI when unequipping

I already made a question on cooldown a weapon and I made a screenGUI to show the player when they can shoot again implementing the same debounce code. The problem is I've got no clue on how to delete the screengui/textlabel from the screen. As every tool I'm planing on doing has its own GUI, if the screenGUI of one tool doesn't delete, it will overlap with the same tool's GUI/ other tools GUI.
I already tried hiding the text label as stated in this question like this
player.PlayerGui.ScreenGui.TextLabel.Visible = false but
1) It only makes it disappear first time its unequipped and
2) Im afraid that given it doesn't get deleted, but rather hidden, after some time, stacked hidden GUIs will somehow affect the games smoothness in some way.
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local tool = script.Parent
--Creaets a text label with the text Block Ready! on it when the player
local function onEquip()
print("screengui1")
local screenGui = Instance.new("ScreenGui")
screenGui.Parent = player.PlayerGui
local textLabel = Instance.new("TextLabel")
textLabel.Parent = screenGui
textLabel.BackgroundTransparency = 0.85
textLabel.Position = UDim2.new(0, 1100, 0, 550)
textLabel.Size = UDim2.new(0, 150, 0, 50)
textLabel.BackgroundColor3 = BrickColor.White().Color
textLabel.Text = "Block ready!"
end
local isGunOnCooldown = false
local cooldownTime = 3 --seconds
mouse.Button1Down:Connect(function()
-- debounce clicks so the text dont changes (its cooldown is the same as the gun cooldown the GUI is within)
if isGunOnCooldown then
return
end
-- change the text,
isGunOnCooldown = true
player.PlayerGui.ScreenGui.TextLabel.Text = "Reloading..."
-- start the cooldown and reset it along with the test
spawn(function()
wait(cooldownTime)
isGunOnCooldown = false
player.PlayerGui.ScreenGui.TextLabel.Text = "Block ready!"
end)
end)
local function onUnequip()
--code to delete the gui goes here
end
tool.Equipped:connect(onEquip)
tool.Unequipped:connect(onUnequip)
I just need explanation on how to delete the screenGUI that contains the textlabel shown to the player when they unequip the weapon
The easiest way to handle this is to keep a reference to the UIElement when you first create it. Then when you equip the tool, you simply set the Parent. When you unequip, you set the Parent to nil. This way, you know that there will always be one element, you are simply controlling when it is visible.
local function createAmmoUI()
--Creates a text label with the text Block Ready! on it when the player
local screenGui = Instance.new("ScreenGui")
local textLabel = Instance.new("TextLabel")
textLabel.Name = "Message"
textLabel.Parent = screenGui
textLabel.BackgroundTransparency = 0.85
textLabel.Position = UDim2.new(0, 1100, 0, 550)
textLabel.Size = UDim2.new(0, 150, 0, 50)
textLabel.BackgroundColor3 = BrickColor.White().Color
textLabel.Text = "Block ready!"
return screenGui
end
-- make a persistent UI element to show off how much ammo is left and when reload is done
local ammoUI = createAmmoUI()
local function onEquip()
-- when the tool is equipped, also show the UI
print("Equipping Tool to current Player")
ammoUI.Parent = player.PlayerGui
end
local function onUnequip()
-- when the tool is unequipped, also remove the UI from the screen entirely
print("Unequiping Tool UI")
ammoUI.Parent = nil
end
local isGunOnCooldown = false
local cooldownTime = 3 --seconds
mouse.Button1Down:Connect(function()
-- debounce clicks so the text dont changes (its cooldown is the same as the gun cooldown the GUI is within)
if isGunOnCooldown then
return
end
-- change the text,
isGunOnCooldown = true
ammoUI.Message.Text = "Reloading..."
-- start the cooldown and reset it along with the test
spawn(function()
wait(cooldownTime)
isGunOnCooldown = false
ammoUI.Message.Text = "Block ready!"
end)
end)
tool.Equipped:connect(onEquip)
tool.Unequipped:connect(onUnequip)

Displaying Image in Corona sdk

I've been making a game with Corona SDK. I'm trying display an image in the middle of the screen, but it displays in the random location. Image that I'm trying to display is circle.png. Please help me if you can.
Here is the code:
local composer = require( "composer" )
strong textlocal scene = composer.newScene()
local widget = require "widget"
widget.setTheme ("widget_theme_ios")
local score
local scoreEarn = 1
local lives = {}
local livesCount = 1
local balls = {}
local ballsCount = 0
local ballsSendSpeed = 65
local ballsTravelSpeed = 3500
local ballsIncrementSpeed = 1.5
local ballsMaxSendSpeed = 30
local timer_Counter
local onGameOver, gameOverBox, gameoverBackground, btn_returnToMenu
-- -------------------------------------------------------------------------------
-- "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 function ballTap(event)
end
local function ballDrag()
end
local function ballSend ()
end
local function ballsCollision ()
end
local function onCollision (event)
end
local function circleDamage ()
end
function gameOver ()
end
local background = display.newImageRect(sceneGroup, "images/gamescreen/background.png", 1600, 1200)
background.x = _CX
background.y = _CY
local cirlce = display.newImageRect(sceneGroup, "images/gamescreen/circle.png", 184, 179)
cirlce.x = _CX
cirlce.y = _CY
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
Just try this ,
local cirlce = display.newImageRect(sceneGroup, "images/gamescreen/circle.png", 184, 179)
cirlce.x = display.viewableContentWidth/2
cirlce.y = display.viewableContentHeight/2
Give This a try.
local cirlce = display.newImageRect("images/gamescreen/circle.png", 184, 179)
cirlce.x = centerX
cirlce.y = centerY

Corona SDK Trouble with Scene Change

ADDED LINK TO STORYBOARD PROJECT WITH ERROR
Project - http://forums.coronalabs.com/index.php?app=core&module=attach&section=attach&attach_id=2062
original topic - http://forums.coronalabs.com/topic/46884-scene-change-pleeeeease-help/
I have tried changing scenes so many times, it either makes the player glitch and move around anywhere, or I have attempt to applyforce (blah blah blah (don't remember)) a nil value, or bad argument expected proxy, and all this other crazy stuff. To keep things simpler for the both of us I've sent you the code without the scene changing as it is a complete mess. I've been trying to do this for weeks but can't get it right. I know it feels like I'm not doing anything by asking you what seems like impossible code, but I can't get the scene to change without tons of errors.
Please tell me the code to do:
local function onCollision( event )
if event.phase == "began" then
-- go to nex​t lua/scene completely obliterating this one as
-- if I'm opening a whole new game
end
return true
end
If you really don't want to do the code for me I'm willing to pay at this point
I just want to get past this... please
display.setStatusBar( display.HiddenStatusBar )
local physics = require( "physics" )
physics.start( )
physics.setGravity( 0, 15 ) -- set x & y gravity to 0
local background = display.newImage( "background.jpg" )
background.x = display.contentCenterX
background.y = display.contentCenterY
local ground = display.newImage( "ground.png" )
ground.x = display.contentCenterX
ground.y = 480
physics.addBody( ground, "static", {density=1, friction=1, bounce=0.3 } )
local flag = display.newImage( "flag.png" )
flag.x = display.contentCenterX
flag.y = 50
physics.addBody( flag, "static", {density=0, friction=1, bounce=0.3 } )
local player = display.newImage( "player.png" )
player.x = display.contentCenterX
player.y = 425
physics.addBody( player, {density=0, friction=1, bounce=0.3 } )
player.isFixedRotation = true
system.setAccelerometerInterval( 100.0 )
local tiltSpeed = 2
local function onTilt( event )
movementX = tiltSpeed * event.xGravity
player.x = player.x + movementX
-- prevent player from moving offscreen
if player.x <= 30 then
player.x = 30
elseif player.x >= 310 then
player.x = 310
end
end
local function onCollision( event )
if event.phase == "began" then
-- go to next lua/scene completely obliterating this one as if I'm opening a whole new game
end
return true
end
local function onScreenTouch( event )
if event.phase == "began" then
-- make player jump
player:applyForce( 0, -4, player.x, player.y )
end
end
Runtime:addEventListener( "accelerometer", onTilt )
Runtime:addEventListener( "touch", onScreenTouch )
flag:addEventListener("collision", onCollision )
You cannot leave the current scene during a collision. What you can do though, is make a timer call a function 1 millisecond after the collision.
Try this code instead for your collision event detector:
local function onCollision( event )
if event.phase == "began" then
function(sceneChange)
storyboard.gotoScene(Your next scene here")
end
timer.performWithDelay(1,sceneChange,1)
end
return true
end
'Hope that helps! Keep coding!
Just make a function that changes proceeds to the next scene
local function changeScene()
composer.gotoScene("nextScene")
end
local function onCollision( event )
if event.phase == "began" then
changeScene()
end
return true
end
I suggest using composer api its more updated than storyboard api.
As a advice, remove all eventlisteners you have called, especially those runtime eventlisteners you have. Even if you change scene, that event will still trigger, hence giving you and error because it reference it deleted. Rule of thumb, "If you don't need it, remove it."

Stop listening for 'x' seconds in corona

I have a fade-in/fade-out function based on a shake event, but if you shake it again during the function, it stacks the functions. What I would like is for it to wait until the function ends (5 seconds) and then being listening again. What would the code be for that?
This is what I have currently:
function fadeOut ( event )
transition.to(yes1, {time=2000, alpha=0})
transition.to(yes2, {time=2000, alpha=0})
...
transition.to(funny3, {time=2000, alpha=0})
transition.to(funny4, {time=2000, alpha=0})
timer.performWithDelay(2000, onShakeComplete)
end
responses = {yes1, yes2, yes3, yes4, yes5, yes6, yes7, yes8, yes9, yes10,
no1, no2, no3, no4, no5, maybe1, maybe2, maybe3, maybe4, maybe5,
funny1, funny2, funny3, funny4}
local shaking = false
-- reset shaking flag after a shake is completed
local function onShakeComplete()
shaking = false
end
local function onShake (event)
if event.isShake and not shaking then
shaking = true
local object = responses[math.random(1,20)]
transition.to(object, {time=2000, alpha=1})
timer.performWithDelay(4000, fadeOut)
end
end
Runtime:addEventListener("accelerometer", onShake)
-- true if we have a shake happening right now
local shaking = false
-- reset shaking flag after a shake is completed
local function onShakeComplete()
shaking = false
end
local function onShake (event)
if event.isShake and not shaking then
local object = responses[math.random(1,20)]
transition.to(object, {time=2000, alpha=1})
timer.performWithDelay(4000, fadeOut)
timer.performWithDelay(4000, onShakeComplete)
shaking = true
end
end

Resources