Touch Event detection issue - lua

when you add event listener to an object and moved outside that object event.phase == "ended" will not be trigger because it detected outside the object.
my question: is there a way we can detect event.phase == "ended" even if the user releases the touch outside the object or is there any other way we can detect if the user has lifted their finger without using Runtime event listener?

You can try the following method:
local bg = display.newRect(0,0,display.contentWidth,display.contentHeight)
local rect = display.newRect(100,200,100,100)
rect:setFillColor(0)
local isRectTouched = false;
local function bgTouch_function(e)
if(isRectTouched == true and e.phase == "ended")then
isRectTouched = false;
print("Started on Rect and ended outside")
end
end
bg:addEventListener("touch",bgTouch_function)
local function rectTouch_function(e)
if(e.phase == "began" or e.phase == "moved")then
isRectTouched = true;
print("began/moved .... rect")
else
isRectTouched = false;
print("ended .... rect")
end
end
rect:addEventListener("touch",rectTouch_function)
Keep coding.................. 😃

I would recommend using the built in setfocus method which will allow you to bind a touch event to a specific display object. Which allows you to get events even if you move off the object. You can read up on this method here Happy coding.
local function bind(event)
if event.phase=='began' then
display.getCurrentStage():setFocus(event.target)
end
if event.phase=='moved' or event.phase=='began' then
elseif event.phase=='ended' then
display.getCurrentStage():setFocus(nil)
-- Whatever you want to do on release here
end
end

Related

Corona SDK - How to remove an item(Coins) when collide with an object(player)?

I started learning and developing games using Corona SDK recently and right now I am facing an issue to collect coins in the gameplay. When the player object collides with the coin object the coin should be removed/disappeared. I tried the below code which is not successful whenever the coin collides with the player it throws an error
Attempt to call method 'translate' (a nil value)
Below is the code I used,
------Create Coins------
function coin()
token = display.newImage(sceneContainer, "gold.png")
token.x = math.random(320, 720)
token.y = math.random(160, 260)
token.myName = "token"
physics.addBody( token, "dynamic", { bounce=0, friction=1, radius=20 })
local function muovi()
token:translate(-2, 0)
end
Runtime:addEventListener( "enterFrame", muovi )
end
tmr = timer.performWithDelay(5000, coin, 0)
------Collision Function------
function onCollision( event )
if ( event.phase == "began" ) then
if event.object1.myName == "player" and event.object2.myName == "token" then
event.object2:removeSelf()
print("hitting 1")
elseif event.object1.myName == "token" and event.object2.myName == "player" then
event.object1:removeSelf()
print("hitting 1")
end
end
end
Runtime:addEventListener( "collision", onCollision)
Look at the gotchas in the Corona Documentation.
As a best practice, you should set the associated variable(s) to nil
after calling object:removeSelf().
When an object is removed, the rendering-related resources of the
removed object are deleted immediately. What remains of the object is
simply a plain Lua table with all non-display object properties — the
metatable is set to nil and all properties relating to display object
are removed. Thus, if there are still references to object in Lua,
they will simply be references to a normal Lua table.
Try setting the object to nil after calling removeSelf()
if ( event.phase == "began" ) then
if event.object1.myName == "player" and event.object2.myName == "token" then
event.object2:removeSelf()
event.object2 = nil
print("hitting 1")
elseif event.object1.myName == "token" and event.object2.myName == "player" then
event.object1:removeSelf()
event.object1 = nil
print("hitting 1")
end
end
end
If you read the second point you'll notice that you'll still have a plain Lua table with all non-display object properties, so my guess is that it is calling removeSelf twice. The first time it is removing the object from display, but it's not removing the myName field. Therefore when it's called a second time, it's trying to removeSelf again.

Touch function not working

local Gin2
local function Gin ( event )
if ( event.phase == "began" ) then
Gin2 = display.newImage("PNGs/Sprite/Gin")
Gin2.x = _H
Gin2.y = _W
end
return true
end
Runtime:addEventListener("touch", Gin )
Hello, so I've been trying to figure out this for some time, but with with no success. So as may guess the idea is to spawn an image by touching.Should I define the object that will be touch?
I have made a code for you to use. When you want to spawn an object via touch listener (Either Runtime event or a single event) you can use event.x and event.y to determine the touch point of the user. Below is the code.
NOTE: I made gin as a array for future use of your spawned object
local val = 1
local gin = {}
local spawnObject = function(event)
if(event.phase == "ended") then
gin[val] = display.newImage("PNGs/Sprite/Gin")
gin[val].x = event.x
gin[val].y = event.y
val = val + 1
end
end
Runtime:addEventListener( "touch", spawnObject )
You are using the 'functional listener' form and for 'touch' event you should not be using Runtime.
In your case, you need to change Runtime to the object that 'is to be touched'. I guess what you want to do is to move the image once it is touched.
so, firstly move
Gin2 = display.newImage("PNGs/Sprite/Gin")
up and out the function. then change Runtime to Gin2.

why eveyone do if event.phase == "began" then...?

i see allways that people write in the collusion function (example):
local onCollision = function(event)
if event.phase == "began" then
event.object2:removeSelf();
event.object2 = nil;
end
end
Runtime:addEventListener("collision",onCollision);
why you dont just write:
local onCollision = function(event)
event.object2:removeSelf();
event.object2 = nil;
end
Runtime:addEventListener("collision",onCollision);
I dont understand what is the point?
consider this example,
local object = display.newImage( "ball.png" )
function object:touch( event )
if event.phase == "began" then
display.getCurrentStage():setFocus( self )
self.isFocus = true
elseif event.phase == "moved" then
print( "moved phase" )
elseif event.phase == "ended" or event.phase == "cancelled" then
display.getCurrentStage():setFocus( nil )
self.isFocus = false
end
end
return true
end
object:addEventListener( "touch", object )
If you doesn't add the phase your touch will be detected in all the three phase,
thus it executes all the statements with in function three times.
To avoid this we are using the phase.
In your case ,
local onCollision = function(event)
event.object2:removeSelf();
event.object2 = nil;
end
Runtime:addEventListener("collision",onCollision);
The code inside this will be called three times, this results in error. Since in began phase itself your object will be removed, when it comes to moved phase it will give you error, since object is already removed.
Please refer this, http://docs.coronalabs.com/api/event/touch/phase.html

Moving a character with Lua

I am new to Lua and am attempting to simulate a character moving.
I have the character moving left and right at the moment. I would like the character to move 16 pixels at a time. That works fine given that the user doesn't touch the phone rapidly. In that case, the character moves a random number of pixels.
my question is, how can i get the touch event to only register once at a time.
my code:
-- move character
function moveCharacter(event)
if event.phase == 'began' then
if event.x > character.x+8 then
transition.to(background, {time=800, x=background.x-16})
end
if event.x < character.x-8 then
transition.to(background, {time=800, x=background.x+16})
end
end
end
function touchScreen(event)
Runtime:removeEventListener('touch', moveCharacter)
if event.phase == 'began' then
Runtime:addEventListener('touch', moveCharacter)
end
end
Runtime:addEventListener('touch', touchScreen)
You can try this:
function moveCharEF()
if event.x > character.x+8 then
background.x = background - 16
end
if event.x < character.x-8 then
background.x = background + 16
end
end
function moveCharacter(event)
if event.phase == 'began' then
display.getCurrentStage():setFocus( event.target )
event.target.isFocus = true
Runtime:addEventListener( "enterFrame", moveCharEF )
elseif event.target.isFocus then
if event.phase == "ended" then
Runtime:removeEventListener( "enterFrame", moveCharEF )
display.getCurrentStage():setFocus( nil )
event.target.isFocus = false
end
end
end
function touchScreen(event)
Runtime:removeEventListener('touch', moveCharacter)
if event.phase == 'began' then
Runtime:addEventListener('touch', moveCharacter)
end
end
Runtime:addEventListener('touch', touchScreen)
By the way, I dont know about your application. So character may move too fast or too slow. Just change moveCharEF() function's related lines
Is it is what you looking for..?
local isTransitionInProgress = false
local function resetFlag()
isTransitionInProgress = false
end
function moveCharacter(event)
if(event.x > character.x+8 and isTransitionInProgress==false) then
isTransitionInProgress = true
transition.to(background, {time=800, x=background.x-16,onComplete=resetFlag()})
end
if(event.x < character.x-8 and isTransitionInProgress==false) then
isTransitionInProgress = true
transition.to(background, {time=800, x=background.x+16,onComplete=resetFlag()})
end
end
background:addEventListener("tap", moveCharacter)
Keep coding... :)
You can try using the "tap" listener instead of "touch". It only registers one touch at a time.
Runtime:addEventListener('tap', touchScreen)

Corona SDK: Restart an app only when user press "home"

Using corona SDK, i would like a clean restart of my app, everytime the user hits the homebutton.
If he/she receives a phonecall, pulls down the dropdownmenu and so on, I would like for the app to continue in its' current state.
Any suggestions?
Thanks,
/S
how i solved it!
suspendTime = 0
resumeTime = 0
function onSystemEvent( event )
if event.type == "applicationSuspend" then
suspendTime = os.time()
print(suspendTime)
elseif event.type == "applicationResume" then
resumeTime = os.time()
print(resumeTime)
print("deltaTime: "..resumeTime - suspendTime )
if(resumeTime - suspendTime > 30) then
local sceneName = storyboard.getCurrentSceneName()
if(sceneName ~= "levels.splash") then
print(sceneName)
print(resumeTime)
storyboard.gotoScene("levels.splash")
end
end
end
end
Runtime:addEventListener("system", onSystemEvent)
function onKeyEvent( event )
local keyname = event.keyName;
if (event.phase == "up" and (event.keyName=="back" or event.keyName=="menu" or event.keyName == "home" )) then
if keyname == "menu" then
os.exit()
end
end
return false
end
Runtime:addEventListener( "key", onKeyEvent )
This one will work for android.
I checked from http://docs.coronalabs.com/api/event/key/keyName.html, so there is no way to do that in iPhone.
But you can try this : get the time when application is suspended. And save it to documentes directory. Then when application is resume, check the time between two sessions. If there is more then half an hour, restart all things.

Resources