#### Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

# Draggable physics objects.

edited September 2012 in General Posts: 3

How do I write a physics body that can be dragged with touch. Like the hockey pucks in touch hockey.

Tagged:

• Posts: 563

Have a look at the Physics Lab example that comes with Codea. Test 1 allows you to drag physics bodies.

• Posts: 3

Yes, I saw the physics lab example but when I drag the objects, they don't follow my finger it’s as if there was a rubber band between them and my finger. What I want is for the object to be below my finger in real time.

I could just set the bodies position to by my finger’s position, but that would lead to non-physical behavior because, the speed would be zero or some other value.

• edited September 2012 Posts: 489

Hello @kilobyte. You are correct that the `PhysicsDebugDraw:draw()` function models a 'rubber band' between the anchor and the touch, together with a drag on linear velocity (only, there is no drag on angular velocity).

Perhaps you need to model different behaviour: (1) a force applied to the centre of mass (to avoid torque) in the same direction as that from the anchor to the touch, that increases rapidly in strength as the distance between the touch and the anchor increases; (2) a damping effect that is strong when the distance between the touch and the anchor is small; and (3) perhaps, the effect of a touch that has ended is considered to be complete only once the anchor reaches the point where the touch was when it ended.

(Update) Having experimented, the basic problem is this:

A finger can move very rapidly over the surface of the viewer. A body with mass that follows such a finger closely can have very significant kinetic energy, with corresponding implications for any other bodies that it collides with. Perhaps, given that, in your circumstances, 'non-physical' behaviour is more desirable than physical behaviour.

• Posts: 3

I think the best quote that refers to the problem with setting the position is, “If you manually set the position of a body, then you are teleporting the body.” In other words when I set the position, no collision detection happens.

Posts: 587

What you want is a critically dampened spring system. The issues comes with the amount of force you apply to maintain the bodies position. If the force is too low you get oscillation, if it's too high you get overshooting. Getting it right is mainly about tweaking, but as @mpilgrem says you won't get 1:1 movement without some serious amount of kinetic energy, which means you'll likely cause high energy collisions, making things fly away at high speeds. I'd say look at the code in PhysicsLab that applies the force but try tweaking the values to get faster response and less oscillation then use it in your own project.

• Posts: 39

In addition to @John 's critically dampened spring system:
This is a well known design issue in many engineering problems.
There's a real world-parameter (the position of an object) that needs to follow a target value (the touch position). This requires a control system, one which a system- and controlsengineer could design. See: http://en.wikipedia.org/wiki/Control_engineering

The basics is this:
The difference between the actual, current value and the wanted, target value is called the Errorsignal. The bigger this number, the farther off your object is.
This number is then used to compute a Force that aims to decrease the Errorsignal. If the errorsignal is zero, the object is in place.
The trick is designing an algorithm that computes this Force. The physics example uses a simple lineair gain (Force = Error * constant) and includes a dampening force.
A PID controller may improve the response a lot.

• Posts: 123

The above said is absolutelay true for dynamic objects. Maybe you sometimes want to drag static objects like obstacles too. in that case you also cant move the object directly, but you can simply delete the object at the old position and recreate it at the new position. but you should also be careful dragging it not too,fast to not move dynamic objects into your static objects. for my project it was no problem as i only had thin lines and it was ok, if the ball goes through the line when i move the line fast over the ball. This would not work for dynamic objects e.g. for a racket, as you would loose the kinetic energy.

• edited September 2012 Posts: 371

Is this what you are looking for?

``````function setup()
watch("CurrentTouch.deltaX")
ball = physics.body(CIRCLE, 50)
ball.x = WIDTH / 2
ball.y = HEIGHT / 2
physics.gravity(0,0)
walls = {
physics.body(EDGE, vec2(0, 0), vec2(WIDTH, 0)),
physics.body(EDGE, vec2(0, 0), vec2(0, HEIGHT)),
physics.body(EDGE, vec2(WIDTH, HEIGHT), vec2(WIDTH, 0)),
physics.body(EDGE, vec2(WIDTH, HEIGHT), vec2(0, HEIGHT)),
}
for k, v in ipairs(walls) do
v.restitution = 1
end
bodies = {}
for i = 1, 100 do
bodies[i] = physics.body(CIRCLE, 10)
bodies[i].position = vec2(math.random(WIDTH), math.random(HEIGHT))
end
end

function draw()
background(0, 0, 0, 255)
fill(255, 255, 0, 255)
ellipse(ball.x, ball.y, 100)
ball.linearVelocity = vec2(0,0)
fill(255, 0, 0, 255)
for k, v in ipairs(bodies) do
ellipse(v.x, v.y, 20)
end
end

function touched(touch)
if touch.state == MOVING then
ball.linearVelocity = vec2(touch.deltaX, touch.deltaY) / DeltaTime
end
end
``````
• Posts: 39

Here's a really, really, really, crude simulation of a PID controller.
You can experiment with the different parameters.

``````-- PID Controller
function setup()
Body.type = DYNAMIC
Body.position = vec2(WIDTH/2,HEIGHT/2)
Body.gravityScale = 0

target = vec2(0,0)
touching = false
E = vec2(0,0)
D = vec2(0,0)
Force = vec2(0,0)
integral = vec2(0,0)
olderr = vec2(0,0)

parameter("DGain",0,2,1) -- strength of the friction
parameter("EGain",0,2,1) -- overall strength of the control
parameter("EP",0,2,1) -- strength of the lineair component
parameter("EI",0,2,1) -- strength of the integral component
parameter("EIt",0,2,1) -- speed of the integral component
parameter("ED",0,100,1) -- strength of the differential component
parameter("EDt",0,2,1) -- sensitivity of the differential component
end

function draw()
background(0, 0, 0)
stroke(255,255,255,255)
strokeWidth(2)
fill(125,125,125,255)

updatebody()
end

function touched(touch)
if touch.state == ENDED then
touching = false
integral = vec2(0,0)
else
touching = true
target.x = touch.x
target.y = touch.y
end
end

function updatebody()
if touching == true then
-- compute E
local Error = target - Body.position
E = Errorsignal(Error)
else
-- no E - force
E = vec2(0,0)
end
D = Friction()
Force = E + D
Body:applyForce(Force)
end

-- computes a force dependant on the Error (difference between target and actual position)
function Errorsignal(Err)
return (Err * EP + EI*Icontroller(Err) + ED*Dcontroller(Err) ) * EGain
end

-- computes the friction force
function Friction()
local anchor  = Body.position
local velocity = Body:getLinearVelocityFromWorldPoint(anchor)
local friction = -1 * velocity * DGain
return friction
end

-- simulates an integral controller. the longer object is off-target, the bigger the steering.
-- good for eliminating static offsets, bad for stability
function Icontroller(Err)
integral = integral + Err * EIt * DeltaTime
return integral
end

-- simulates a differential controller. reacts on the speed with which Err changes.
-- good for tracking fast changes & stability. Not so good at static offsets
function Dcontroller(Err)
local diff = (Err - olderr) * EDt * DeltaTime
olderr = Err
return diff
end
``````