Control Physics object using finger

Hello everyone!

I want to make my player object (physics object) follow the finger movements of the player in y-axis only but I fail to do so. I constantly see an annoying flick when the player reaches the destination. Also, after re-scaling the object (and its physics body), yVelocity acts in the opposite direction for all values, like negative value makes the object move up at first but after re-scaling, it moves towards the bottom.

Can anyone help me with the code? I’d be grateful for any help provided. It’d be great if code works with Runtime touch listener.

note: I tried to do it without physics the first time but that code isn’t working as needed right now, so I’m not posting it here.

Thank you in advance.

Hi @bgmadclown,

There are far too many factors in this to understand what’s going on, so we’ll need to see some code. We don’t know how you’ve set up the object, how you’re handling the touch, what type of physics body you’re using, etc. etc. Please specify these important details and we can go from there.

Thanks,

Brent

Hi Brent,

I’m using “dynamic” body for the player object.

player = display.newImageRect( "assets/player.png", 102, 101 ) physics.addBody( player, "dynamic", {radius = player.width / 2} )

I handle touch controls via Runtime listener.

Runtime:addEventListener( "touch", controlPlayer )

and the controlPlayer function:

function controlPlayer(event) if (event.phase == "began") then if (event.x \<= display.contentCenterX) then if (event.y \> player.y) then player.yVelocity = -player.height / 2 else player.yVelocity = player.height / 2 end end elseif (event.phase == "moved") then if (event.x \<= display.contentCenterX) then if (event.y \> player.y) then player.yVelocity = -player.height / 2 else player.yVelocity = player.height / 2 end end elseif (event.phase == "ended") then if (event.x \<= display.contentCenterX) then player.yVelocity = 0 end end end

and the movePlayer function:

local function movePlayer() player:setLinearVelocity( 0, player.yVelocity ) end

I call movePlayer in every cycle in the game loop.

Also, I manipulate the character’s scale (in the game loop)

local function scalePlayer(valueScaleDown) player.xScale = player.xScale - valueScaleDown player.yScale = player.yScale - valueScaleDown physics.removeBody( player ) physics.addBody( player, "dynamic", {radius = (player.width / 2) \* player.xScale} ) end

Hope you can guide me to the right direction from here Brent :slight_smile:

Thanks,

Serkan

Hi Serkan,

Do you prefer that the player follows (matches) the exact Y location of the touch? Or do you prefer that as the user moves the touch around, the player more gradually “catches up” with the touch point?

Brent

Well, if I can get hands on the catching up code, I think I can handle the exact location code and try them both to see how it turns out.

Well, the “direct position” method would involve directly setting the player’s Y position to the touch Y position, and while that’s generally OK, it also carries some risk because you’re trying to move a physics object around somewhat forcibly outside of what the physics engine would prefer. So, an alternative method would be to use a touch joint, which would accomplish the “follow/catch-up” method in a more graceful manner, and play nicer with the physics engine.

Conveniently, Corona ambassador Matt Webster wrote a tutorial which outlines this (see the first section):

https://coronalabs.com/blog/2015/03/03/tutorial-solutions-to-common-physics-issues/

Brent

So, do you think something like this(without the throwing) should help me solve the problem?

Edit: Thanks to Brent, what I read above led me to an old thread I’ve posted and got answer. Here it is -> forums.coronalabs.com/topic/57339-swipe-to-throw-object-without-dragging/

Sorry, that’s my bad. Above code didn’t work for me because of the scaling issue I mentioned earlier. Yesterday, I forgot to clear out the comment lines before trying it out. After doing that, everything gets out of control.

I tried working everything out with a permanent joint that is not related to the player object, which, by the way, works great- but whenever I open the scaling code in the game loop, there’s that annoying flicker again when I try to control the player with finger movement.

By the way, I assume we don’t have a chance to scale physics objects without removing the body first. If there’s a way that we can do it without removing the body, I guess the above solution would work.

Hi @bgmadclown,

I don’t see your updated code (perhaps you removed it), but if I had to guess, it’s exactly as you say: when you remove the physics body to create a smaller/larger version, it will automatically destroy the touch joint.

I’m not sure how you created a “joint that’s not related to the player object” unless you just have an invisible object and the player object follows its x/y position in runtime step. I suppose that would work… in fact, that might be a better solution because then the touch joint properties won’t be affected by the altered mass of the body and it would be more consistent.

Brent

Yes, I’ve just deleted it because it won’t work and it’s not very different from the code in that forum post.

That’s what I’ve done actually but it also didn’t work as expected. I used that invisible body to move the object but when the player reached its destination point, it moved a bit upwards/downwards like it couldn’t stop before passing the destination and returned back to the destination point. Also, it flickers a little when the scaling is in place and you move your finger.

By the way, if I remove scaling, it all works fine without those problems I mention. I guess the main problem is because I remove the physics body and add it again. It probably would have worked if there was a way to scale physics body without removing it first but I’m not sure about that :slight_smile:

Hi @bgmadclown,

If your object is moving a bit past the destination point, then returning, it’s because you haven’t set the properties on the touch joint to handle that. Touch joints behave like a “rubber band” or “spring” and you need to tell them how to behave. It’s possible to adjust both how fast the object will move toward the destination touch point (like how powerful the spring is), and also how much flexibility the spring will have. So, you need to just tinker with the properties of the joint until it feels right… all of those properties are documented in the guides and docs on our site.

As for your scaling, are you literally destroying and re-creating the physics body on every single game step? If so, that’s just not feasible and it’s going to kill your performance. Tell me more about how your scaling should work, how often it needs to occur, etc. and I’ll probably have some advice on how to best handle it.

Brent

Hi Brent,

Well, I should take a look into that then. I guess you mean “damping ratio” and “frequency” values, right? By the way, I don’t need to adjust those values if I don’t use scaling in runtime. It all works well if I omit the scaling code.

Yes, I’m doing scaling in every single step. Think of something like agar.io. That’s how the scaling works. Player scales down over time.
I know it kills the performance, especially when I include physics in the code but sadly, I couldn’t find another way to scale the physics body in runtime.

Hi @bgmadclown,

Yes, adjust those properties of the touch joint to make it behave as you need.

For scaling, since it’s very important to your design, I can suggest a few other methods which would help performance:

  1. (more simple but not ideal performance) – Adjust the scale on a timer instead of every frame step. I can’t imagine the scale changes so drastically between one frame and the next that you need to destroy/re-create every frame.

  2. (more complex but best performance) – Create the body from a series of circular bodies in a concentric “ring”, as a multi-element body. This would resemble like a shooting/archery target, where each body element would be slightly larger than the one before it. Then, using pre-collision handling and PhysicsContact, conditionally check which element is “on” and either choose to honor the collision of disregard it. In other words, the overall body would always remain the same internally, but you would decide which “level of circle size” best matches the size of the visual object.

Brent

Hi @bgmadclown,

There are far too many factors in this to understand what’s going on, so we’ll need to see some code. We don’t know how you’ve set up the object, how you’re handling the touch, what type of physics body you’re using, etc. etc. Please specify these important details and we can go from there.

Thanks,

Brent

Hi Brent,

I’m using “dynamic” body for the player object.

player = display.newImageRect( "assets/player.png", 102, 101 ) physics.addBody( player, "dynamic", {radius = player.width / 2} )

I handle touch controls via Runtime listener.

Runtime:addEventListener( "touch", controlPlayer )

and the controlPlayer function:

function controlPlayer(event) if (event.phase == "began") then if (event.x \<= display.contentCenterX) then if (event.y \> player.y) then player.yVelocity = -player.height / 2 else player.yVelocity = player.height / 2 end end elseif (event.phase == "moved") then if (event.x \<= display.contentCenterX) then if (event.y \> player.y) then player.yVelocity = -player.height / 2 else player.yVelocity = player.height / 2 end end elseif (event.phase == "ended") then if (event.x \<= display.contentCenterX) then player.yVelocity = 0 end end end

and the movePlayer function:

local function movePlayer() player:setLinearVelocity( 0, player.yVelocity ) end

I call movePlayer in every cycle in the game loop.

Also, I manipulate the character’s scale (in the game loop)

local function scalePlayer(valueScaleDown) player.xScale = player.xScale - valueScaleDown player.yScale = player.yScale - valueScaleDown physics.removeBody( player ) physics.addBody( player, "dynamic", {radius = (player.width / 2) \* player.xScale} ) end

Hope you can guide me to the right direction from here Brent :slight_smile:

Thanks,

Serkan

Hi Serkan,

Do you prefer that the player follows (matches) the exact Y location of the touch? Or do you prefer that as the user moves the touch around, the player more gradually “catches up” with the touch point?

Brent

Well, if I can get hands on the catching up code, I think I can handle the exact location code and try them both to see how it turns out.

Well, the “direct position” method would involve directly setting the player’s Y position to the touch Y position, and while that’s generally OK, it also carries some risk because you’re trying to move a physics object around somewhat forcibly outside of what the physics engine would prefer. So, an alternative method would be to use a touch joint, which would accomplish the “follow/catch-up” method in a more graceful manner, and play nicer with the physics engine.

Conveniently, Corona ambassador Matt Webster wrote a tutorial which outlines this (see the first section):

https://coronalabs.com/blog/2015/03/03/tutorial-solutions-to-common-physics-issues/

Brent

So, do you think something like this(without the throwing) should help me solve the problem?

Edit: Thanks to Brent, what I read above led me to an old thread I’ve posted and got answer. Here it is -> forums.coronalabs.com/topic/57339-swipe-to-throw-object-without-dragging/

Sorry, that’s my bad. Above code didn’t work for me because of the scaling issue I mentioned earlier. Yesterday, I forgot to clear out the comment lines before trying it out. After doing that, everything gets out of control.

I tried working everything out with a permanent joint that is not related to the player object, which, by the way, works great- but whenever I open the scaling code in the game loop, there’s that annoying flicker again when I try to control the player with finger movement.

By the way, I assume we don’t have a chance to scale physics objects without removing the body first. If there’s a way that we can do it without removing the body, I guess the above solution would work.