Corona SDK Trouble with Scene Change - events

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."

Related

error bad argument #1 to draw (drawable expected, got table), trying to animate a sprite for the main character

new to Lua and love. I'm trying to animate a character for my platform game. I know my key binds and all work but I have never animated before, so I don't even know if I'm going in the right direction or not. I've tried looking up guides so I can compare my code to someone else's but it seems that most of them are outdated. Originally my player was just a white rectangle but now im trying to actually give it a sprite.
Here's my main.lua
local STI = require("sti")
local anim8 = require('anim8')
require("MC")
function love.load()
map1 = STI("map/map1.lua", {"box2d"})
Physics = love.physics.newWorld(0,0)
Physics:setCallbacks(beginContact, endContact)
map1:box2d_init(Physics)
map1.layers.Solid.visible = false
background = love.graphics.newImage("assets/Base pack/bg.png")
mc:load()
end
function love.update(dt)
Physics:update(dt)
mc:update(dt)
end
function love.draw()
love.graphics.push()
love.graphics.scale(5,3)
love.graphics.draw(background)
love.graphics.pop()
map1:draw(0, 0, 2, 2)
love.graphics.push()
love.graphics.scale(2,2)
mc:draw()
love.graphics.pop()
end
function love.keypressed(key)
mc:jump(key)
if keypressed == "escape" then
love.event.quit(0)
end
end
function beginContact(a, b, collision)
mc:beginContact(a, b, collision)
end
function endContact(a, b, collision)
mc:endContact(a, b, collision)
end
I don't believe that there is anything wrong with my main but i think it's necessary to recreate the problem (sorry if it makes this too long). Now my mc.lua is where I'm having the problem since im trying to animate the player themselves by giving them a jump idle and walk animation, I think i will give them a damaged and death animation later.
local anim8 = require('anim8')
mc = {}
spr_mc_walk = love.graphics.newImage("assets/mc sprites/1 Pink_Monster/Pink_Monster_Walk_6.png")
local w = anim8.newGrid(32, 32, spr_mc_walk:getWidth(), spr_mc_walk:getHeight())
walk = anim8.newAnimation(w('1-6', 1), 0.1)
spr_mc_idle = love.graphics.newImage("assets/mc sprites/1 Pink_Monster/Pink_Monster_Idle_4.png")
local i = anim8.newGrid(32, 32, spr_mc_idle:getWidth(), spr_mc_idle:getHeight())
idle = anim8.newAnimation(i('1-4', 1), 0.1)
spr_mc_jump = love.graphics.newImage("assets/mc sprites/1 Pink_Monster/Pink_Monster_Jump_8.png")
local j = anim8.newGrid(32, 32, spr_mc_jump:getWidth(), spr_mc_jump:getHeight())
jump = anim8.newAnimation(j('1-8', 1), 0.1)
obj_mc = walk
function mc:load()
self.x = 100
self.y = 0
self.width = 20
self.height = 60
self.xvel = 0
self.yvel = 0
self.maxspeed = 200
self.acceleration = 4000 -- max speed
self.friction = 3900 -- how long it takes them to reach max speed
self.gravity = 1000
self.jumpAmount = -500
self.grounded = false
self.physics = {}
self.physics.body = love.physics.newBody(Physics, self.x, self.y, "dynamic")
self.physics.body:setFixedRotation(true)
self.physics.shape = love.physics.newRectangleShape(self.width, self.height)
self.physics.fixture = love.physics.newFixture(self.physics.body, self.physics.shape)
end
function mc:draw()
love.graphics.draw(obj_mc, self.x, self.y)
end
This is most of my mc or player function, except for movement and such but this has all the code that I'm confused with. I'm pretty sure I wrote the code right I'm just confused on how to actually implement it now that I have it written down. I thought just doing the draw function would actually draw the idle version of the character but then there's where I get the error. If you need anymore code or anymore details just let me know.
The error that this is happening at is
Error
MC.lua:41: bad argument #1 to 'draw' (Drawable expected, got table)
Traceback
[C]: in function 'draw'
MC.lua:41: in function 'draw'
main.lua:30: in function 'draw'
[C]: in function 'xpcall'
I haven't done any of that for a while, but I believe obj_mc, in this case, is a table of the frames. You need to loop through them during update.
local anim8timer = 0
local anim8index = 1
local anim8rate = 0.2 -- pick an animation rate that looks good for your game
function mc:update( dt )
anim8timer = anim8timer +dt -- add delta time
if anim8timer >= anim8rate then
anim8timer = anim8timer -anim8rate -- reset timer
anim8index = anim8index +1 -- next frame
if anim8index > #obj_mc then anim8index = 1 end -- loop frames
end
end
function mc:draw()
love.graphics.draw( obj_mc[ anim8index ], self.x, self.y )
end
They may have a built-in function that accomplishes some of that, so look for anything that resembles this in the Love2D forum.

Hands up animation when stand on a brick [ROBLOX]

I need a script that can do an animation when you are standing on a brick. I just don't know how to do the animation. I can't find a free model with the animation I am looking for. Here is a preview of how I want the hands up. PREVIEW OF THE ANIMATION
The brick you are standing on is
script.Parent
There are two main ways of animation; The newer Animations and the older Joints.
The guide should be able to help you to getting started with animations. It even got a video.
If you want to use a old style Joint animation, something like this might work:
local Block = script.Parent
local function MakeFakeShoulder(Character, Side)
local Controller = { ["Stop"] = function() end }
local Torso = Character:findFirstChild("Torso")
local Arm = Character:findFirstChild(Side .. " Arm")
if not Torso or not Arm then return Controller end
local Shoulder = Torso:findFirstChild(Side .. " Shoulder")
if Shoulder then
local FakeShoulder = Instance.new("ManualWeld")
FakeShoulder.Name = "Fake " .. Side .. " Shoulder"
FakeShoulder.C0 = CFrame.new(1.5 * (Side == "Right" and 1 or -1),0.5,0)
FakeShoulder.C1 = CFrame.new(0,0.5,0) * CFrame.fromAxisAngle(Vector3.FromAxis(Enum.Axis.Z), math.rad(-180))
FakeShoulder.Part0 = Torso
FakeShoulder.Part1 = Arm
FakeShoulder.Parent = Torso
Shoulder.Parent = nil
function Controller:Stop()
Shoulder.Parent = Torso
FakeShoulder:Destroy()
end
end
return Controller
end
local function MakeFakeShoulders(Character)
local Controller = { }
local Right = MakeFakeShoulder(Character, "Right")
local Left = MakeFakeShoulder(Character, "Left")
function Controller:Stop()
Right:Stop()
Left:Stop()
end
return Controller
end
local function GetHumanoid(Part)
if Part.Parent == nil then return nil end
return Part.Parent:findFirstChild("Humanoid")
end
local CurrentlyTouching = { }
Block.Touched:connect(function(Part)
local Humanoid = GetHumanoid(Part)
if not Humanoid then return end
CurrentlyTouching[Humanoid] = CurrentlyTouching[Humanoid] or 0
CurrentlyTouching[Humanoid] = CurrentlyTouching[Humanoid] + 1
if CurrentlyTouching[Humanoid] > 1 then return end
local Controller = MakeFakeShoulders(Part.Parent)
while CurrentlyTouching[Humanoid] > 0 do
if GetHumanoid(Block.TouchEnded:wait()) == Humanoid then
CurrentlyTouching[Humanoid] = CurrentlyTouching[Humanoid] - 1
end
end
Controller:Stop()
end)
Note that if the ending touch do not register good enough, make a invisible CanCollide = false bounding part that is bigger than the visual part and put the script in that one instead,

Corona SDK game scenes

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

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

How to Listen to continuous touch events with Corona SDK

This seemed simple to do but I do not know how to monitor for continued touching. I want to touch the display or an image and as long as the user has not lifted his finger continue to rotate an Image. Here is a snip the code I have:
local rotate = function(event)
if event.phase == "began" then
image1.rotation = image1.rotation + 1
end
return true
end
Runtime:addEventListener("touch", rotate)
I want the rotation to occur until the finger is lifted from the screen.
Thanks for any advice.
How about this?
local crate = ...
local handle
local function rotate(event)
if event.phase == "began" and handle == nil then
function doRotate()
handle=transition.to(crate,
{delta=true, time=1000, rotation=360, onComplete=doRotate})
end
doRotate()
elseif event.phase == "ended" and handle then
transition.cancel(handle)
handle = nil
end
end
Runtime:addEventListener("touch", rotate)
This allows for better control of the rate of rotation. Relying on enterFrame might be problematic if you start dropping frames for some reason.
Also, the checks for handle and not handle are to accomodate multi touch. There are other ways (and better ways) to handle this but it's expedient (and shouldn't matter at all if you aren't using multitouch.)
I ended up doing this. Please post your answer if you have a better method !!
local direction = 0
function scene:move()
crate.rotation = crate.rotation + direction
end
Runtime:addEventListener("enterFrame", scene.move)
local function onButtonEvent( event )
if event.phase == "press" then
direction = 1 -- ( -1 to reverse direction )
elseif event.phase == "moved" then
elseif event.phase == "release" then
direction = 0
end
return true
end
local button = widget.newButton{
id = "rotate_button",
label = "Rotate",
font = "HelveticaNeue-Bold",
fontSize = 16,
yOffset = -2,
labelColor = { default={ 65 }, over={ 0 } },
emboss = true,
onEvent = onButtonEvent
}

Resources