stopping multiple collision which causes multiple events - lua

I am making a game and I am having problems where, when the character jumps on an object, a series of events happen. But, because it collides with the object multiple times, the events happen multiple times, which is what I do not want. What I want is for the event to happen once after the character jumps on the object and stays on top of the object. THEN, let the event happen again ONCE when the character jumps on another object.... etc.
Here is part of my code that is relevant:
function playerCollision( self, event )
--if hit bottom column, u get points
if event.target.type == "player" and event.other.type == "startColumn2" then
if event.phase == "began" then
print ("collided")
addColumns()
timer.performWithDelay(5000, addBody)
startColumn2: translate(-4, 0)
startcolumn2hit = true
end
end
if event.target.type == "player" and event.other.type == "bottomColumn" then
print ("hit column")
onPlatform = true
end
end
How would I make it so I can prevent multiple collisions?

On the first collision you can set a boolean flag on the object the player collided with. Here I'm adding alreadyCollided and check if we already have collided with it:
function playerCollision( self, event )
--if hit bottom column, u get points
if event.target.type == "player" and event.other.type == "startColumn2" then
if event.phase == "began" then
addColumns()
timer.performWithDelay(5000, addBody)
startColumn2: translate(-4, 0)
startcolumn2hit = true
end
end
if event.target.type == "player" and event.other.type == "bottomColumn" and not event.other.alreadyCollided then
event.other.alreadyCollided = true
-- Increase score etc...
end
end

Related

Corona SDK While loop crash

What is wrong with this code that it crashes the simulator?
I'm new to Corona SDK, but I know alot of Lua from Roblox.
local x,y,touching,active = 2,2,false,true
local background = display.newImage("Icon.png",(display.pixelWidth/2)+30,y)
background:scale(60,60)
print("Started")
function move()
y=y+1
end
function onObjectTouch(event)
if event.phase == "began" then
touching = true
while touching == true do
timer.performWithDelay( 1000, move)
end
elseif event.phase == "ended" then
touching = false
end
return true
end
background:addEventListener("touch",onObjectTouch)
Corona is event based. You essentially lock up the touch event in a while loop which prevents the ended phase from triggering to break your endless loop.
Corona has a Runtime event called "enterframe". It is called 30-60 times a second (probably less depending on the work it is doing) that is essentially an update method.
Using your logic:
function onObjectTouch(event)
if event.phase == "began" then
touching = true
elseif event.phase == "ended" then
touching = false
end
end
funtion EnterFrame(event)
if touching == true then
timer.performWithDelay( 1000, move)
end
end
There are other ways to accomplish this by setting a dynamic objects velocity when the touch is started and setting that velocity to 0 when the touch ends.

Event.target collides only once, not multiple times

When I run the onCollision function, it seems that it collides with the 'ground' multiple times, even though its not moving. How can I make it so once the object hits the ground, it only collides with it 'once'?
I would like to give a 'score' every time it hits the ground, but because it hits the ground multiple times, my score seems to keep going up.
here is part of the code:
function playerCollision( self, event )
if ( event.phase == "began" ) then
--if hit bottom column, u get points
if event.target.type == "player" and event.other.type == "bottomColumn" then
print ("hit column")
onPlatform = true
else
--if hit anything else, gameOver
--composer.gotoScene( "restart" )
print ("hit ground")
end
end
end
I didnt find anything wrong with your code, just try to add only this statement, hope it may work.
function playerCollision( self, event )
if ( event.phase == "began" ) then
--if hit bottom column, u get points
if event.target.type == "player" and event.other.type == "bottomColumn" then
print ("hit column")
onPlatform = true
return true -- try adding this
else
--if hit anything else, gameOver
--composer.gotoScene( "restart" )
print ("hit ground")
end
end
end

Non stopping movement

I've been having some trouble with player movement. The thing is, movement is controlled by four arrow-buttons and while one of them is pressed, the character moves in that direction. However, if the player doesn't lift his finger before moving away from the button, the player moves indefinitely. The code is the following:
function moveright(self,event)
self.x=self.x+2
end
function rightkeypressed(event)
if event.phase == "began" then
knight.enterFrame = moveright
Runtime:addEventListener("enterFrame",knight)
end
if event.phase == "ended" or event.phase == "cancelled" then
Runtime:removeEventListener("enterFrame",knight)
end
end
rightkey:addEventListener("touch",rightkeypressed)
This is the same for all four directions.
Very Simple once you understand the touch listeners
if event.phase == "ended" or event.phase == "cancelled" then
knight.enterFrame = moveright
Runtime:addEventListener("enterFrame",knight)
Runtime:removeEventListener("enterFrame",knight)
end
That should work if you have any questions or is not working just ask

Can someone test my Corona project and identify the issue with my jump function?

I'm all very new to this and everything in this project is just placeholders and scrap work. Some of you may recognize some of the graphics used from other Corona tutorials, but it's to help me get better, so don't be too judgemental. Here's a link to the download for the Corona Simulator: http://www.mediafire.com/download/6a78bsewgwsiyp2/GooMan.rar
Anyways, here's my issue. The jump button seems fine at first. If I hold it down, the character constantly jumps. And if I let go, he stops. If I simultaneously hold down jump while pushing one of the arrow buttons, he'll jump in that direction. However, it seems as though if I jump once, then I hit the jump button again RIGHT as the character is making contact with the ground, that he won't jump. There's a sudden lack of responsiveness. I literally have to pause slightly and wait for the character to fully hit the ground before I can make another successful jump. Why?
And here's all the relevant code for you to look at:
I have this at the beginning to help define my goo character's position:
local spriteInAir = false
local yspeed = 0
local oldypos = 0
local holding = false
I then created the jump button.
local bJump = display.newImage("Images/jumpbutton.png")
bJump.x = 445
bJump.y = 265
bJump.xScale = 0.78
bJump.yScale = 0.78
Followed up by creating an enterFrame Runtime Event which will update my goo character's position in the Y. Running the game at 60fps if that's relevant.
function checkSpeed()
yspeed = sprite.y - oldypos
oldypos = sprite.y
if yspeed == 0 then
spriteInAir = false
else
spriteInAir = true
end
end
Runtime:addEventListener( "enterFrame", checkSpeed )
Then the meat of it all. Created a function called hold which tells the game to not only make my goo character jump, but to keep my goo character constantly jumping as long as the bJump button is held down. Works perfectly. The "jumping" function is a touch event that listens for the hold function, and all of it is executed by the bJump button listening to the jumping function.
local function hold()
if holding and spriteInAir == false then
sprite:applyForce( 0, -8, sprite.x, sprite.y )
sprite:setLinearVelocity(0, -350)
spriteInAir = true
return true
end
end
local function jumping( event )
if event.phase == "began" then
display.getCurrentStage():setFocus( event.target )
event.target.isFocus = true
event.target.alpha = 0.6
Runtime:addEventListener( "enterFrame", hold )
holding = true
elseif event.target.isFocus then
if event.phase == "moved" then
elseif event.phase == "ended" then
holding = false
event.target.alpha = 1
Runtime:removeEventListener( "enterFrame", hold )
display.getCurrentStage():setFocus( nil )
event.target.isFocus = false
spriteInAir = false
return true
end
end
return true
end
bJump:addEventListener("touch",jumping)
Anyone who can help me identify this problem, I'd greatly appreciate it!
You're using a velocity check to detect if the character is on the ground. It can take a short while to set it back to zero after colliding with Box2D, so the better way to do it is to use a collision sensor:
sprite.grounded = 0 -- Use a number to detect if the sprite is on the ground; a Boolean fails if the sprite hits two ground tiles at once
function sprite:collision(event)
if "began" == event.phase then
-- If the other object is a ground object and the character is above it...
if event.other.isGround and self.contentBounds.yMax < event.other.contentBounds.yMin + 5 then
sprite.grounded = sprite.grounded + 1 -- ...register a ground collision
end
elseif "ended" == event.phase then
-- If the other object is a ground object and the character is above it...
if event.other.isGround and self.contentBounds.yMax < event.other.contentBounds.yMin + 5 then
sprite.grounded = sprite.grounded - 1 -- ...unregister a ground collision
end
end
end
sprite:addEventListener("collision")
Then, in your jump function, just check to see if sprite.grounded > 0. If it is, the player is grounded.

Touch Hold Event In corona SDK

I was wondering how I would check if the user has touched the screen, but is holding their touch down and is not moving. Please help if you have anything I can go from. Ive been looking around and have yet to find anything to handle this.
You can use/modify this: (It's what Rob Miracle says)
local holding = false
local function enterFrameListener()
if holding then
-- Holding button
-- Code here
-- Code here
-- Code here
else
-- Not holding
-- Code here
-- Code here
-- Code here
end
end
local function touchHandler( event )
if event.phase == "began" then
display.getCurrentStage():setFocus( event.target )
event.target.isFocus = true
Runtime:addEventListener( "enterFrame", enterFrameListener )
holding = true
elseif event.target.isFocus then
if event.phase == "moved" then
elseif event.phase == "ended" then
holding = false
Runtime:removeEventListener( "enterFrame", enterFrameListener )
display.getCurrentStage():setFocus( nil )
event.target.isFocus = false
end
end
return true
end
I believe its obvious what touchHandler function is ^^
You will need a touch listener added to either an object covering your whole screen or you can add it to the system's RunTime.
See this guide: http://docs.coronalabs.com/guide/events/detectEvents/index.html#hit
Now, there are three "Phases" for these touch events. You get one when the press starts ("began"), one if the person moves their finger ("moved") and when they stop touching, there is an "ended" phase.
Depending on what you are trying to do, if you are say moving something while holding the button down, then you can set a flag like:
if event.phase == "began" then
pressed = true
elseif event.phase == "ended" then
pressed = false
end
Then where ever you're moving you can check to see "if pressed then move".

Resources