Object Imitating the location movement of the Touch Offset in a "touch" Listener

Hi.

I am making a program that the circle made with display object shape, will detect and imitate or mimic the X and Y movement of the touch (am talking about the event.x and event.y of a “touch” listener) throughout the entire stage or the device’s screen, but then, the results of my codes seems unwanted for me.

Here are some of the many codes I have tried:

In the first try, the event.x and event.y attracts the circle’s X and Y location like a magnet.

**local Drag

local Ball = display.newCircle( display.contentCenterX, display.contentCenterY, 100 )
Ball:setFillColor(0, 0.7, 0.8, 1)

Drag = function ( event )
local phase = event.phase

if ( phase == “moved” ) then
Ball.x = event.x
Ball.y = event.y
end
end

Runtime:addEventListener(“touch”, Drag)**

In the second try; the Ball repels away from the touch and to it’s current location.

**local Drag

local Ball = display.newCircle( display.contentCenterX, display.contentCenterY, 100 )
Ball:setFillColor(0, 0.7, 0.8, 1)

Drag = function ( event )
local phase = event.phase

if ( phase == “moved” ) then
Ball.x = event.x - event.xStart
Ball.y = event.y - event.yStart
end
end

Runtime:addEventListener(“touch”, Drag)**

In the third try, It is almost perfect, The Ball mimics or emitates the the touch’s X and Y movements, but then at the same time it is Glitching or blinking to change location and more.

**local Drag

local Ball = display.newCircle( display.contentCenterX, display.contentCenterY, 100 )
Ball:setFillColor(0, 0.7, 0.8, 1)

Drag = function ( event )
local phase = event.phase

if ( phase == “moved” ) then
Ball.x = event.x - ( event.xStart + Ball.x )
Ball.y = event.y - ( event.yStart + Ball.y )
end
end

Runtime:addEventListener(“touch”, Drag)**

My resolution is, I want the ball to mimic or emitate the X and Y movement of the touch.(event.x and event.y). I hope I can have some awesome and plight solving formula from you. I thank you with high respect

Hey :slightly_smiling_face:

Im not completely sure if this is what you meant, but I hope it works:

if event.phase == “began” then
Ball.x1, Ball.y1 = event.x, event.y
elseif event.phase == “moved”
Ball.x2, Ball.y2 = event.x, event.y
Ball.x, Ball.y = Ball.x + (Ball.x2 - Ball.x1), Ball.y + (Ball.y2 - Ball.y1)
Ball.x1, Ball.y1 = Ball.x2, Ball.y2
end

1 Like

Wow, Thank you very2 much, this code you provide does exactly what I want for the Ball.

But I do have a bit difficulties in trying to understand your code, if you don’t mind, can I have some descriptions? I will thoroughly appreciate it. But once again, thank you very much.

im really glad i could help🤗
sure, no problem:
first you need a way to track the touch as it moves throught the screen. for this i used (ball.x1, ball.y1) => previoussly detected point of touch and (ball.x2, ball.y2) => currently detected point of touch. you calculate the distance between these two points => (ball.x2 - ball.x1, ball.y2 - ball.y1), and then add this distance to the current coordinates of the ball => ball.x = ball.x + (ball.x2 - ball.x1) and ball.y = ball.y + (ball.y2 - ball.y1).

i hope im making sense! :blush: in math these are called vectors. i know people generally hate math, but one piece of really good advice i think i could give you, could be to look up vectors, maybe through some youtube tutorials. they are very simple and incredibly valuable if you are making 2d games.

You are very welcome!

1 Like

Quite understandable proV, thank you so much​:purple_heart::blue_heart::gift_heart:! I wish you a good day, and hope to see you again.

1 Like

Hi again, your convenience is so valuable to me, and I can’t stop thanking you for that.

Now, I’ve tried to implement composer scene, but every time I go to the scene where the Ball is, and perform it’s Runtime touch listener very advance, the x1 and y1 of the ball turns out to be a nil value, and the “began” phase looks like it has been ignored.

When I wait a few seconds and perform the touch Listener, everything seems to be fine.

This is because of the transition effect I have written in seeBall.lua composer.gotoScene(“Ball”, {effect = “crossFade”, time = 300})

But when I remove the transition effect, just composer.gotoScene(“Ball”), the touch Listener works as expected, no matter how advanced I got to perform it.

Here are my codes:

** The main.lua**

local composer = require( “composer” )

display.setStatusBar( display.HiddenStatusBar)

composer.gotoScene( “seeBall” )

The seeBall.lua

local composer = require(“composer”)

local scene = composer.newScene()

local SeeBall

local gotoGameWorld = function ()
composer.gotoScene(“Ball”, {effect = “crossFade”, time = 300})
end

local tapTheSeeBall = function( event )

if (event.numTaps > 1) then

  transition.to( SeeBall, { alpha = 0.9, size = 30, time = 90, onComplete =
  function()
      transition.to( SeeBall, { alpha = 1, size = 50, time = 10 } )
  end } )

elseif (event.numTaps == 1) then

  transition.to( SeeBall, {alpha = 0.9, size = 30, time = 90, onComplete =
  function()

      transition.to( SeeBall, { alpha = 1, size = 50, time = 10, onComplete =
      function()

          timer.performWithDelay(5, gotoGameWorld)
      end
      } )
  end
  } )

end
return true
end

function scene:create ( event )
local sceneGroup = self.view
local phase = event.phase

SeeBall = display.newText(sceneGroup, "SEE BALL", display.contentCenterX, display.contentCenterY, native.systemFontBold, 50)

SeeBall:addEventListener("tap", tapTheSeeBall)

end

function scene:show( event )

local sceneGroup = self.view
local phase = event.phase

if (phase == “will”) then

elseif (phase == “did”) then

end
end

function scene:hide( event )

local sceneGroup = self.view
local phase = event.phase

if (phase == “will”) then

elseif (phase == “did”) then

end
end

function scene:destroy ( event )

local sceneGroup = self.view

end

scene:addEventListener( “create”, scene )
scene:addEventListener( “show”, scene )
scene:addEventListener( “hide”, scene )
scene:addEventListener( “destroy”, scene)

return scene

And the Ball.lua

local composer = require(“composer”)

local scene = composer.newScene()

local Ball

local bounder = 100

local LLCX = display.actualContentWidth
local LLCR = LLCX - bounder
local LLCL = ( LLCX - LLCX ) + bounder

local LLCY = display.screenOriginY
local LLCT = LLCY + bounder
local LLCB = (display.contentHeight - LLCY) - bounder

local Drag

–local watch = display.newText( "event.time: ", display.contentCenterX, Ball.y - 100, system.nativeFontBold, 50 )
Drag = function ( event )
local phase = event.phase

if ( phase == “began” ) then
display.currentStage:setFocus( Ball )

Ball.x1 = event.x
Ball.y1 = event.y

elseif ( phase == “moved” ) then
display.currentStage:setFocus( nil )

Ball.x2 = event.x
Ball.y2 = event.y

Ball.x = Ball.x + ( Ball.x2 - Ball.x1 )
Ball.y = Ball.y + ( Ball.y2 - Ball.y1 )

Ball.x1 = Ball.x2
Ball.y1 = Ball.y2--]]

if ( Ball.x >= LLCR ) then
  Ball.x = LLCR

elseif ( Ball.x <= LLCL ) then
  Ball.x = LLCL
end

if ( Ball.y <=LLCT ) then
  Ball.y = LLCT

elseif ( Ball.y >= LLCB ) then
  Ball.y = LLCB
end

elseif ( phase == “ended” or phase == “cancelled” ) then
display.currentStage:setFocus( nil )
end
return true
end

function scene:create( event )
local sceneGroup = self.view

Ball = display.newCircle(sceneGroup, display.contentCenterX, display.contentCenterY, 100 )
Ball:setFillColor(0, 0.7, 0.8, 1)

Runtime:addEventListener(“touch”, Drag)

end

function scene:show ( event )
local sceneGroup = self.view
local phase = event.phase

if ( phase == “will” ) then

elseif ( phase == “did” ) then

end

end

function scene:hide ( event )
local sceneGroup = self.view
local phase = event.phase

if ( phase == “will” ) then

elseif ( phase == “did” ) then

end

end

function scene:destroy ( event )

local sceneGroup = selfdisplay.view

end

scene:addEventListener( “create”, scene )
scene:addEventListener( “show”, scene )
scene:addEventListener( “hide”, scene )
scene:addEventListener( “destroy”, scene)

return scene

I’m getting an error message showing that the x1 and y1 of the Ball is a nil value, meaning, the “began” phase was ignored.

I want the Runtime touch listener perform fine and as expected even though it has been performed very advanced just as after loading it’s composer scene even with transition time. Thank you very much again😊

Hello again :slightly_smiling_face: I appreciate that! Will try my best to help again​:slightly_smiling_face:
Yes, I agree, I think “began” was ignored because of the transition effect from one scene to another. This happens to me too sometimes. Maybe try this small change:

function scene:create( event )
local sceneGroup = self.view

Ball = display.newCircle(sceneGroup, display.contentCenterX, display.contentCenterY, 100 )
Ball:setFillColor(0, 0.7, 0.8, 1)

end

function scene:show ( event )
local sceneGroup = self.view
local phase = event.phase

if ( phase == “will” ) then

elseif ( phase == “did” ) then
Runtime:addEventListener(“touch”, Drag)
end

This just adds the event listener in scene:show(), phase = “did” instead of in scene:create(). So the event listener function would be added once the transition to the scene is complete. This way x1 and x2 would not be ignored. You can start moving the ball once the transition to the scene is complete.

Another option might be to do this:

elseif ( phase == “moved” ) then
display.currentStage:setFocus( nil )–btw I think you can skip this line

Ball.x2 = event.x
Ball.y2 = event.y

if not Ball.x1 and not Ball.y1 then
print(“began was ignored”)
Ball.x1 = event.x
Ball.y1 = event.y
end

Ball.x = Ball.x + ( Ball.x2 - Ball.x1 )
Ball.y = Ball.y + ( Ball.y2 - Ball.y1 )

Ball.x1 = Ball.x2
Ball.y1 = Ball.y2

If the “began” phase was ignored, you try to catch that error in the “moved” phase, by giving Ball.x1 and Ball.y1 the values of event.x and event.y. Maybe a little messy, but no error :grin:

But I think the First solution is better, to be honest😁 hope I could help!
Have a great day!:blush:

1 Like

Thank you :green_heart::blue_heart: so much for the code remedies, proV.

Please don’t get disappointed😊, because I’ve already tried the first solution and it doesn’t work.

However, the Second Option is so **WONDERFUL.**:heart_eyes:

		if ( phase == "began" ) then
				display.currentStage:setFocus( Ball )

				Ball.x1 = event.x
				Ball.y1 = event.y

		elseif ( phase == "moved" ) then
				display.currentStage:setFocus( nil )

				Ball.x2 = event.x
				Ball.y2 = event.y

				if ( not Ball.x1 or not Ball.y1 ) then ---changed to or instead of and
  					Ball.x1 = event.x
  					Ball.y1 = event.y
				end

				Ball.x = Ball.x + ( Ball.x2 - Ball.x1 )
				Ball.y = Ball.y + ( Ball.y2 - Ball.y1 )

				Ball.x1 = Ball.x2
				Ball.y1 = Ball.y2
		end

But now it is not understandable, because I’m thinking that this might make the Ball unmovable from it’s X and Y location, knowing that **Ball.x1, ** and Ball.x2, are both equal to event.x, also **Ball.y1, ** and Ball.y2, are both equal to event.y, and all are in the same phase; the “moved” phase. How does it still copy the touch’s movement location?

This is a help for me as a beginner. thank you, proV, truly appreciate it a lot.

Oooo cool man, im glad i could help again! :slightly_smiling_face:
yes, youre right, the first one was a bad solution, i apologyse for that :grin:
but im glad the second one worked!

yes, good question! so the ball will still imitate the movement of the touch, it will still work like before! but its true that the ball might be unmovable just one time(!) in the beginning of the touch for a split second => if the began phase was ignored! dont worry, it will be visually unnoticed and no error will occur.

the Drag function is constantly being called as the touch is being moved on the screen(you can add this line print(“Drag called”)

Drag = function(event)
print(“Drag called”)



end

and look in the console when its being called).
And the function is constantly moving the ball during the touch by these small distances/vectors(currentTouch - previous touch). if the began phase was ignored, instead of an error the ball will be unmoved for that first call of the function. You can test it forever, there will be no error i promise!

the change to or instead of and is great! i didnt want to confuse you too much so i added both. you could also skip the “or not Ball.y1” if you wish. if one of them is nil, the other one will be nil as well for sure. if began was ignored both of them are nil :slightly_smiling_face:

oh of course, no problem! i like helping if i can :slightly_smiling_face: dont worry, youll be killing it in no time!

1 Like

Thanks proV, now I’m getting enlightened time by time.

Only problem now is I can’t check and view the states of the code in the console, the fact is, I’ve been using solar2d without the corona console.

Im glad you mentioned it, but now, maybe I’m going to create another topic for this “console” problem, and I hope to see you there again. Thank you proV.

1 Like