I am learning Corona and I am trying to use the collision event.
The target of the following program is that the rock is moving towards to the car using transition.to. And print a line to report the collision where it occurs.
However, it does not work. Moreover, I even cannot receive the message "enterenter", what is the reason why the program cannot even get into the enter function?
My code is as follow. Thank you in advance.
local composer = require( "composer" )
local scene = composer.newScene()
local physics = require "physics"
physics.start(); physics.pause()
local function onLocalCollision( self, event )
if ( event.phase == "began" ) then
print( self.myName .. ": collision began with " .. event.other.myName )
elseif ( event.phase == "ended" ) then
print( self.myName .. ": collision ended with " .. event.other.myName )
end
end
local widget = require "widget"
function scene:create( event )
print("entercreate")
local sceneGroup = self.view
local backgrd = display.newImage("background2.png",0,260)
backgrd:scale(3,3)
local car = display.newImage("car2.png",80,270)
physics.addBody(car,"static")
car.myName="Car"
local rock = display.newImage("rock.jpg",520,280)
rock:scale(0.05,0.05)
physics.addBody(rock,"static")
rock.myName="rock"
sceneGroup:insert(backgrd)
sceneGroup:insert(car)
sceneGroup:insert(rock)
transition.to(backgrd,{time=24000, x=-1800,onComplete=endScroll})
transition.to(rock,{time=4000, delay=2500,x=-40})
end
function scene:enter( event )
print("enterenter")
physics.start()
local sceneGroup = self.view
Runtime:addEventListener( "collision", onLocalCollision )
end
scene:addEventListener( "create", scene )
scene:addEventListener( "enter", scene )
return scene
Working code with a local and a global (Runtime) listener:
local widget = require "widget"
local composer = require( "composer" )
local scene = composer.newScene()
local physics = require "physics"
physics.start()
physics.setGravity( 0,0 )
local function onGlobalCollision( event )
local target = event.object1
local other = event.object2
if ( event.phase == "began" ) then
print( "GLOBAL: " .. target.name .. ": collision began with " .. other.name )
elseif ( event.phase == "ended" ) then
print( "GLOBAL: " .. target.name .. ": collision ended with " .. other.name )
end
end
local function onLocalCollision( event )
local target = event.target
local other = event.other
if ( event.phase == "began" ) then
print( "LOCAL: " .. other.name .. ": collision began with " .. target.name )
elseif ( event.phase == "ended" ) then
print( "LOCAL: " .. other.name .. ": collision ended with " .. target.name )
end
end
function scene:create( event )
print("scene:create")
local sceneGroup = self.view
local car = display.newRect( 100, 100, 100, 100 )
car.name = "car"
physics.addBody( car )
local rock = display.newRect( 250, 250, 100, 100 )
rock.name = "rock"
rock:setFillColor( 0.5, 0.5, 0.5 )
physics.addBody( rock )
rock:addEventListener( "collision", onLocalCollision )
sceneGroup:insert(car)
sceneGroup:insert(rock)
transition.to(rock,{time=4000, x = -40, y = -100})
Runtime:addEventListener( "collision", onGlobalCollision )
end
function scene:enter( event )
print("scene:enter")
local sceneGroup = self.view
end
scene:addEventListener( "create", scene )
scene:addEventListener( "enter", scene )
return scene
The problem that you have with your code is that the two bodies are static and two static bodies can't collide with each other and that there is nothing called scene:enter in composer (so that's why it doesn't gets called and therefor not the onLocalListener).
Some body types will — or will not — collide with other body types. In
a collision between two physical objects, at least one of the objects
must be dynamic, since this is the only body type which collides with
any other type. See the Physics Bodies guide for details on body
types.
https://docs.coronalabs.com/daily/guide/physics/collisionDetection/index.html
Here is some information about the Composer API and you'll that you should probably use scene:show:
https://coronalabs.com/blog/2014/01/21/introducing-the-composer-api-plus-tutorial/
Related
I created a new project in CoronaLabs Studio with Physics-Based Game starting options and everything loaded up as a beginner I don't get where should I put addEventListener() so I can make the box to be clickable or to be destroyed on click?
I tried a bunch of different ways to just place this line of code inside the script to make the box clickable virus:applyLinearImpulse( 0, -0.25, virus.x, virus.y )
Here is the level1.lua script.
In this case, I have
require("toast")
local composer = require( "composer" )
local scene = composer.newScene()
-- include Corona's "physics" library
local physics = require("physics")
--------------------------------------------
tapCount = 0
tapText = display.newText( tapCount, display.contentCenterX, 20, native.systemFont, 40 )
--------------------------------------------
local screenW, screenH, halfW = display.actualContentWidth, display.actualContentHeight, display.contentCenterX
function scene:create( event )
-- Called when the scene's view does not exist.
-- INSERT code here to initialize the scene e.g. add display objects to 'sceneGroup', add touch listeners, etc.
local sceneGroup = self.view
physics.start()
physics.pause()
local background = display.newImageRect("game-background.png", 1170, 658)
background.x = display.contentCenterX
background.y = display.contentCenterY
-- OFFSCREEN BOX, position it, and rotate slightly
local box = display.newImageRect( "box.png", 40, 40 )
box.x, box.y = 160, -100
box.rotation = 33
-- add physics
physics.addBody( box, { density=1.0, friction=0.3, bounce=0.2 } )
-- create a grass object and add physics (with custom shape)
local grass = display.newImageRect( "grass.png", screenW, 82 )
grass.anchorX = 0
grass.anchorY = 1
-- draw the grass at the very bottom of the screen
grass.x, grass.y = display.screenOriginX, display.actualContentHeight + display.screenOriginY
local grassShape = { -halfW,-34, halfW,-34, halfW,34, -halfW,34 }
physics.addBody( grass, "static", { friction=0.3, shape=grassShape } )
sceneGroup:insert( background )
sceneGroup:insert( grass )
sceneGroup:insert( box )
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
physics.start()
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
physics.stop()
elseif phase == "did" then
-- Called when the scene is now off-screen
end
end
function scene:destroy( event )
-- Called prior to the removal of scene's "view" (sceneGroup)
local sceneGroup = self.view
package.loaded[physics] = nil
physics = nil
end
---------------------------------------------------------------------------------
-- Listener setup
scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )
-----------------------------------------------------------------------------------------
return scene
If I have understood your question correctly,here's an example where you can click a box and destroy it.
function scene:create(event)
local function destroyMe(event)
display.remove(event.target)
event.target=nil
end
local box = display.newImageRect( "box.png", 40, 40 )
box.x, box.y = 160, 100
box.rotation = 33
-- add physics
physics.addBody( box, { density=1.0, friction=0.3, bounce=0.2 } )
box:addEventListener("tap",destroyMe)
end
If you're using touch event,then that event will have three phases.Hence be cautious.
I have just started a LUA a few weeks ago. I was able to create a simple character jumping with a score and then running this with the Corona Simulator. But I wanted to create a menu system so from main.lua which loads up menu.lua and from here it will go to Start (i.e. start the game i.e. to game.lua) and therefore I can play the game. But it doesn't appear. I have tried to add the eventListeners as shown below o
function scene:show( event )
local sceneGroup = self.view
local phase = event.phase
if ( phase == "will" ) then
-- Code here runs when the scene is still off screen (but is about to come on screen)
elseif ( phase == "did" ) then
-- Code here runs when the scene is entirely on screen
startButton:addEventListener( "tap", gotoGame )
highScoresButton:addEventListener( "tap", gotoHighScores )
end
end
Other than that I dont understand why the menu system won't go to Game.lua therefore I can play the game. Also I don't understand why there are errors when loading menu.lua I have used scenes and the composer management library and in theory it should work.
Image files are in one folder
main.lua File 1
local composer = require( "composer" )
-- Hide status bar
display.setStatusBar( display.HiddenStatusBar )
-- Seed the random number generator
math.randomseed( os.time() )
-- Go to the menu screen
composer.gotoScene("menu")
Menu.lua File 2
local composer = require( "composer" )
local scene = composer.newScene()
-- -----------------------------------------------------------------------------------
-- Code outside of the scene event functions below will only be executed ONCE unless
-- the scene is removed entirely (not recycled) via "composer.removeScene()"
-- -----------------------------------------------------------------------------------
local function gotoGame()
composer.gotoScene( "game" )
end
local function gotoHighScores()
composer.gotoScene( "highscores" )
end
-- -----------------------------------------------------------------------------------
-- Scene event functions
-- -----------------------------------------------------------------------------------
-- create()
function scene:create( event )
local sceneGroup = self.view
-- Code here runs when the scene is first created but has not yet appeared on screen
local background = display.newImageRect( sceneGroup, "background.png", 800, 1400 )
background.x = display.contentCenterX
background.y = display.contentCenterY
local title = display.newImageRect( sceneGroup, "title.png", 500, 80 )
title.x = display.contentCenterX
title.y = 200
local startButton = display.newText( sceneGroup, "Start", display.contentCenterX, 700, native.systemFont, 44 )
startButton:setFillColor( 0.82, 0.86, 1 )
local highScoresButton = display.newText( sceneGroup, "High Scores", display.contentCenterX, 810, native.systemFont, 44 )
highScoresButton:setFillColor( 0.75, 0.78, 1 )
startButton:addEventListener( "tap", gotoGame )
highScoresButton:addEventListener( "tap", gotoHighScores )
end
-- show()
function scene:show( event )
local sceneGroup = self.view
local phase = event.phase
if ( phase == "will" ) then
-- Code here runs when the scene is still off screen (but is about to come on screen)
elseif ( phase == "did" ) then
-- Code here runs when the scene is entirely on screen
startButton:addEventListener( "tap", gotoGame )
highScoresButton:addEventListener( "tap", gotoHighScores )
end
end
-- hide()
function scene:hide( event )
local sceneGroup = self.view
local phase = event.phase
if ( phase == "will" ) then
-- Code here runs when the scene is on screen (but is about to go off screen)
elseif ( phase == "did" ) then
-- Code here runs immediately after the scene goes entirely off screen
end
end
-- destroy()
function scene:destroy( event )
local sceneGroup = self.view
-- Code here runs prior to the removal of scene's view
end
-- -----------------------------------------------------------------------------------
-- Scene event function listeners
-- -----------------------------------------------------------------------------------
scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )
-- -----------------------------------------------------------------------------------
return scene
game.lua File 3
local composer = require("composer")
local scene = composer.newScene()
display.setStatusBar(display.HiddenStatusBar)
local physics = require "physics"
function updateScore()
score=score+1
scoreText.text = "Score: "..score
scoreText.x, scoreText.y=80,40
end
function onTouch(event)
if(event.phase=="began") then
if(event.x<player.x) then
player:setLinearVelocity(-30,-200)
updateScore()
else
player:setLinearVelocity(30,-200)
updateScore()
end
end
end
-- create()
function scene:create( event )
local sceneGroup = self.view
-- Code here runs when the scene is first created but has not yet appeared
physics.pause()
score=0
local scoreText
local ground = display.newImage("ground.jpg")
local player = display.newImage("player.png")
end
-- show()
function scene:show( event )
local sceneGroup = self.view
local phase = event.phase
if ( phase == "will" ) then
-- Code here runs when the scene is still off screen (but is about to come on screen)
elseif ( phase == "did" ) then
-- Code here runs when the scene is entirely on screen
physics.start()
scoreText=display.newText("Score:0",0,0,native.systemFont,40)
scoreText.x, scoreText.y=80,40
ground.x=460
ground.y=1300
physics.addBody(ground, "static")
player.x=360
player.y=120
physics.addBody(player)
Runtime:addEventListener("touch", onTouch)
end
end
-- hide()
function scene:hide( event )
local sceneGroup = self.view
local phase = event.phase
if ( phase == "will" ) then
-- Code here runs when the scene is on screen (but is about to go off screen)
elseif ( phase == "did" ) then
-- Code here runs immediately after the scene goes entirely off screen
end
end
-- destroy()
function scene:destroy( event )
local sceneGroup = self.view
-- Code here runs prior to the removal of scene's view
end
-- -----------------------------------------------------------------------------------
-- Scene event function listeners
-- -----------------------------------------------------------------------------------
scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )
-- -----------------------------------------------------------------------------------
return scene
When you create the scene with
function scene:create( event )
You always want to insert the objects (locals) into the sceneGroup doing this
sceneGroup:insert( object )
sceneGroup:insert( object2 )
Also I have the doubt that the event listener goes with touch and not tap (by looking on the doumentation):
startButton:addEventListener( "touch", gotoGame )
highScoresButton:addEventListener( "touch", gotoHighScores )
Anyway I suggest you to visit the documentation: it covers everything and it's euxhastive.
I am learning corona sdk
This is the following code
when the two objects overlaps it becomes 1 objects(Moves together), i have no clue whats going on...
-----------------------------------------------------------------------------------------
--
-- main.lua
--
-----------------------------------------------------------------------------------------
-- Your code here
local physics = require( "physics" )
physics.start()
local crate1 = display.newImage( "crate.png", display.contentCenterX, 100 )
crate1.name = "crate1"
local crate2 = display.newImage( "crate.png", display.contentCenterX + 100, 100 )
crate2.name = "crate2"
crate1:scale(0.2, 0.2)
crate2:scale(0.2, 0.2)
local bodyTouched = function(event)
if(crate1.name == event.target.name and event.phase == "moved")
then
print("Moved " , event.target.name )
crate1.x = event.x
crate1.y = event.y
elseif (crate2.name == event.target.name and event.phase == "moved")
then
print( "Moved ", event.target.name )
crate2.x = event.x
crate2.y = event.y
end
end
physics.addBody( crate1, "static")
physics.addBody( crate2, "static")
crate1:addEventListener( "touch", bodyTouched )
crate2:addEventListener( "touch", bodyTouched )
Please refer to the Corona SDK documentation.
https://docs.coronalabs.com/daily/guide/events/detectEvents/index.html#TOC
Section: Understanding Hit Events
In general you should read the documentation on anything you use.
Your touch event will propagate through all display objects that intersect with the event coordinate. The event will trigger all registered event listeners on its way.
To avoid having multiple listeners triggered your event listener bodyTouch has to return true which will tell Corona that you handled the event and no further listeners should be invoked.
I'm trying to detect collision on two object inside my scene:show function
This is my first set of objects which have a collision listener on it
for i = 1, table.maxn(layout.playgrid) do
physics.addBody( leftholes[i], "static" )
sceneGroup:insert(3,leftholes[i])
leftholes[i].name = "hole"
leftholes[i]:addEventListener( "collision", lis )
physics.addBody( rightholes[i], "static")
sceneGroup:insert(3,rightholes[i])
rightholes[i].name = "hole"
rightholes[i]:addEventListener( "collision", lis )
physics.addBody( topholes[i], "static" )
sceneGroup:insert(3,topholes[i])
topholes[i].name = "hole"
topholes[i]:addEventListener( "collision", lis )
physics.addBody(bottomholes[i], "static")
sceneGroup:insert(3,bottomholes[i])
bottomholes[i]:addEventListener( "collision", lis )
bottomholes[i].name = "hole"
end
and this is the object which will collision with the hole object
hand = display.newImage("assets/hand.png",350,490)
hand.name = "hand"
physics.addBody( hand, "static")
and that my collision listener
local function lis(event)
if event.phase == "began" and event.object2.name=="hand" then
print( "detected" )
local function tra( )
trans = display.newImage('assets/gray.png',indicesToOuterCordinate(layout.finalx,layout.finaly,layout.finalside,false))
physics.addBody( trans, "static")
sceneGroup:insert(trans)
hand:toFront()
end
end
end
Just check whether your are adding your collision listener with the RuntimeEvent listener .
If you does not add your collision with runtime event listeners your will not be detected .
local function onCollision( event )
if ( event.phase == "began" ) then
print( "began: " .. event.object1.myName .. " and " .. event.object2.myName )
elseif ( event.phase == "ended" ) then
print( "ended: " .. event.object1.myName .. " and " .. event.object2.myName )
end
end
Runtime:addEventListener( "collision", onCollision )
Hello all I am currently developing an application that I am going to use the perspective library with. I have imported the library and have written the correct code it seems but to no avail my camera is not working properly. I am attempting to get the camera to follow the main character you are moving around with the buttons. I added him and the background and a "tree" to the camera and set him as the focus but it still will not follow him. Here is my code please tell me what I have done wrong here and how to fix it.
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
local perspective = require( "perspective" )
local camera = perspective.createView()
local physics = require( "physics" )
--physics.setDrawMode( "hybrid" )
local function start( event )
if( event.phase == "ended" ) then
end
end
local bg
local floor
local leftwall
local rightwall
local player
local button1
local button2
local pausebtn
local tree
local function b1( event )
if( event.phase == "ended" ) then
player:applyLinearImpulse( -.01, -.1 )
end
end
local function b2( event )
if( event.phase == "ended" ) then
player:applyLinearImpulse( .01, -.1 )
end
end
local function playerCollision( event )
if( event.phase == "began" ) then
storyboard.gotoScene( "gameover" )
end
end
local function pause( event )
if( event.phase == "ended" ) then
storyboard.showOverlay( "pause" )
physics.pause()
end
end
function scene:createScene( event )
local group = self.view
physics.start()
bg = display.newImage( "bg.png", display.contentWidth/2, display.contentHeight/2, display.contentWidth, display.contentHeight )
camera:add(bg, 3, false)
player = display.newImage( "player.png", display.contentWidth/2, display.contentHeight/2, display.contentWidth, display.contentHeight )
player.collision = playerCollision
camera:add(player, 1, true)
tree = display.newImage( "tree.png", 200, 200)
camera:add(tree, 2, false)
floor = display.newRect( 285, 375, 570, 1 )
button1 = display.newImage( "button1.png", 50, 275 )
button2 = display.newImage( "button2.png", 515, 275 )
leftwall = display.newRect( 0, -1000, 1, 5000 )
rightwall = display.newRect( 570, 300, 1, 5000 )
pausebtn = display.newImage( "pausebtn.png", 540, 30 )
-- Physics
physics.addBody( player )
physics.addBody( floor )
floor.bodyType = "static"
physics.addBody( rightwall )
rightwall.bodyType = "static"
physics.addBody( leftwall )
leftwall.bodyType = "static"
group:insert(bg)
group:insert(player)
group:insert(floor)
group:insert(button1)
group:insert(button2)
group:insert(rightwall)
group:insert(leftwall)
group:insert(pausebtn)
group:insert(tree)
end
function scene:enterScene( event )
print( "game" )
button1:addEventListener( "touch", b1 )
button2:addEventListener( "touch", b2 )
player:addEventListener( "collision", playerCollision )
pausebtn:addEventListener( "touch", pause )
end
function scene:exitScene()
player = nil
camera:cancel()
end
function scene:destroyScene( event )
end
scene:addEventListener( "createScene", scene )
scene:addEventListener( "enterScene", scene )
scene:addEventListener( "exitScene", scene )
scene:addEventListener( "destroyScene", scene )
return scene
Looks like you are missing the call to camera:track() (which should probably go in the enterScene handler). You might also need camera:setBounds(false).
If this still doesn't fix issue, remove all code from your post that is not required in order to duplicate the problem. If you can boil it down to a small example that I can run, I can try and post update.