I have a mad scheme for making an object move using applyForce and momentum. )Arrgh, results suggest that we need to file a bug report.)

We have established, more or less, that when we use the `applyForce` function on an entity, the force vector provided is applied for an interval equal to one DeltaTime, one draw cycle. There seem to be exceptions to this. I have seen two: one case is that sometimes I see a force of zero applied, and very rarely, I’ve seen double the expected amount.

I plan to ignore these variances, and proceed as if `applyForce` applies the force for a period of time DeltaTime.

In real world physics, and fake-world physics as well, objects have momentum. Mathematically,

``````momentum = mass * velocity
``````

This is often written, for reasons only physicists know, as:

``````p = m*v
``````

My own theory is:

Physicist 1
What shall we call momentum? How about “m”?
Physicist 2
Can’t use “m”, that’s mass. How about “n”?
Physicist 1
Used in counting one to n. Maybe “o”?
Physicist 2
Looks too much like zero. Let’s use “p”.
Physicist 1
“p” it is. (They clink glasses and drink.)

Note that momentum is a vector quantity. The momentum of something of mass 2 moving straight up at speed 1 is `<0,2,0>`, while if it is moving to the right, momentum is `<2,0,0>`.

It turns out, of course, that the momentum of something of mass one, moving at speed two, to the left, is `<-2,0,0>`. If those two things collide, the two momentums (momenta?) will cancel out and both objects will stop. The light object can stop the heavy one if it is going fast enough. If it were going even faster, the light object would push the heavy one back and keep on moving, although slowed down.

We saw that in the Michigan-Ohio game as Michigan’s runners pushed through or dragged two or three would-be blockers and tacklers. Go Blue.

Now it turns out, through a bit of math that we won’t explore here, that

``````impulse = change in momentum
``````

or

``````F*t = m*Δv
``````

Now `applyForce` is an impulse, with time t = DeltaTime (we believe). So it changes the momentum of the object to which it is applied, and we have seen that it mostly changes it by DeltaTime times the force applied. (Our sample ball had mass one, so that we could easily see these figures.)

Netting this all out, suppose we have an object of mass m, moving with vector velocity `v`. And suppose we want it to be moving with a new vector velocity, `w`. It turns out that if we take the new vector `w - v`, and whack the object hard enough with a force in that direction, it will, when all is said and done, be moving with velocity `w`.

How hard is hard enough? If I’m not mistaken–which is always a possibility–we need to scale the vector up by the mass, and we need to adjust for the time the force will be applied.

I think we need to hit the object with

``````force = m*(w-v)/DeltaTime
``````

Let’s try to make that concrete with a Codea program.

I’ll spare you the long story of what happened. I’ve spent hours playing with `applyForce` and asking questions about it on the forum. I am pretty confident in the program I’ll show below, and I think it shows the following:

1. Usually, the amount of force required to reverse the object is 0.5 times the object’s linear velocity, divided by DeltaTime. I believe this is telling me that the physics cycle time is 1/60th of a second, not the draw cycle time, which varies. I think physics time needs not to vary lest things change speed visibly on the screen.
2. Sometimes, *on both my fast iPads, every 7 or 8 seconds, `applyForce`, called inside `draw`, has no effect, and for a while thereafter, it has no effect. Then, 7 or 8 seconds later, it again starts to work.
3. Generally, `applyForce` called in `draw` takes effect, subject to the problem #2 above. Generally, using `applyForce` during `scene:update` does not take effect, but sometimes it does.

Toggling the provided parameter switches the program from applying force in `draw` to applying it inside the `update` method of the `Reporter`, that is, inside `scene:update`.

Here’s the program that I plan to submit as a bug report.

``````-- CoCraTu-008

function setup()
scene = craft.scene()
depth = 0
scene.physics.gravity = vec3(0,0,0)
createBall()
Delay = 2
BallTime = 0
Whacks = 0
parameter.boolean("ApplyInScene", true)
end

function update(dt)
scene.debug:line(vec3(-10,depth-1,0), vec3(10,depth-1,0), color(255))
scene:update(dt)
end

function draw()
if not ApplyInScene then
reverse("in draw")
end
update(DeltaTime)
scene:draw()
reporter:draw()
end

function reverse(message)
BallTime = BallTime + DeltaTime
if BallTime >= Delay then
local oldv = BallBody.linearVelocity
local newv = - oldv -- turn him around
local mass = BallBodyMass
local force = mass*(newv-oldv)*60 -- guess at physics time = 1/60
BallBody.sleepingAllowed = false
BallBody.awake = true
BallBody:applyForce(force)
Whacks = Whacks + 1
print(message.. " whack ", Whacks, force)
BallTime = 0
end
end

function createBall()
Ball = scene:entity()
BallBody = Ball:add(craft.rigidbody, DYNAMIC, 1) -- mass 1
BallBodyMass = 1
BallBody.linearVelocity = vec3(0,2,0)
BallBody.sleepingAllowed = false
Ball.position = vec3(0,depth,0)
Ball.model = craft.model.icosphere(1)
Ball.material = craft.material(asset.builtin.Materials.Standard)
Ball.material.diffuse = color(255,0,0)
end

Reporter = class()

function Reporter:init(entity)
self.entity = entity
self.lastDrawTime = ElapsedTime
self.lastFixTime = ElapsedTime
self.deltaFixTime = 0
self.applyDuration = 0
self.maxDuration = 0
end

function Reporter:update()
if ApplyInScene then
reverse("in scene")
end
self.lastDrawTime = ElapsedTime
end
end

function Reporter:draw()
pushStyle()
textAlign(LEFT)
textMode(LEFT)
fill(255)
text("Vel "..BallBody.linearVelocity.y, 400, 80)
text("Duration "..self.applyDuration, 400, 60)
text("Max Duration "..self.maxDuration, 400, 40)
if BallBody.awake then
text("Awake", 400,20)
else
text("Asleep", 400, 20)
end
popStyle()
end
`````` 