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.
Related
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
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.
local held = false
local function jumperTap ()
jumper:applyForce( 0, 200, jumper.x, jumper.y )
return false
end
Runtime:addEventListener( "tap", jumperTap )
local function holdListener(event)
held = true
jumper:applyForce( 0, 250, jumper.x, jumper.y )
return true
end
local function jumperTouch(event)
if (event.phase == "began") then
display.getCurrentStage():setFocus(jumper)
holdTimer = timer.performWithDelay( 500, holdListener )
elseif (event.phase == "moved") then
timer.cancel(holdTimer)
elseif (event.phase == "ended" or event.phase == "cancelled") then
display.getCurrentStage():setFocus(nil)
timer.cancel(holdTimer)
held = false
end
end
Runtime:addEventListener( "touch", jumperTouch )
I'm trying to have a tap and a touch and hold. When the touch and hold happens, the jumper will have more force applied to him so he can jump higher when the screen is touched and held. When the screen is tapped, he will have a shorter jump.
When I tap, the expected thing happens. When I tap and hold, the expected thing happens. I do have a few glaring issues though due to my novice-ness in Corona. They are...
- When I tap and hold, all goes well, but when I release, it glitches and what is performed is what seems to be a the tap event. Not sure why this is happening
- When I perform the tap event, I am able to perform it again while the object is in the air--this brings him down to the ground and the tap event seems to be performed again, but with less force.
Any and all help is greatly appreciated!
EDIT: I put return true and return false in just to try something different, but it didn't affect anything.
I recommend testing out a debounce in order to prevent the tap/tap+hold events from doubling up. By passing the functions through a global boolean you can make it so they can only tap while no tap events are occuring. Because based on your events it seems they happen regardless if they are currently in 'jump' mode or not.
Example:
debounce = false
function func1()
if debounce == false then
debounce = true
//event script
end
end
function event_ended()
debounce = false
end
So I have this cube which if the player clicks on a button moves. I also have this block which if the cube collides with, the cube will get sent back to a start position. I have tried my best but I can't seem to get both of them working correctly together. With my code, the cube get's glitchy and moves all over the screen between the block and start position. This is if the button is still pressed. If it is released at the same moment of collision it does work, but obviously the players won't be paying attention to that.
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
leftbutton:addEventListener( "touch", touchHandler )
This is the code for the collision:
function onCollision( event )
if ( event.phase == "began" ) then
transition.cancel( )
transition.moveTo( cube, {time = 0, x = 35, y = 35} )
end
return true
end
redblock:addEventListener( "collision", onCollision )
Also: whenever the cube falls on an edge of the redblock and starts spinning and gets sent back to start. It keeps spinning and it starts moving on its own.
I hope someone can help!
Thanks.
You are still in the "moved" phase during the collision hence why the block tries to reset, but is then dragged around afterwards. Once you detect the collision, you need to remove the event handler from the "leftbutton" so that the touch event is no longer in progress.
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".