I’m getting some really weird results when calling body:applyForce each frame.
I’m currently trying to work through Chapter 6 of Nature of Code, and I know it’s not practical, but I’m calling body:applyForce on every touch event, just to be as close to the Processing examples as possible.
At the moment my main.lua file is this:
require "physics" physics.start() physics.setGravity(0,0) require "vehicle" local v=vehicle.create() Runtime:addEventListener("touch",function(event) if event.phase=="moved" or event.phase=="began" then v:setTarget(event.x,event.y) end end)
and vehicle.lua looks like this:
local M={} vehicle=M local display=display local math=math require "physics" local physics=physics setfenv(1,M) local maxSpeed=10 local maxForce=10 function create() local img=display.newImage("img/car.png") physics.addBody(img) function img:steer() if not self.targetX then return end local dx,dy=self.targetX-self.x,self.targetY-self.y local d2=dx\*dx+dy\*dy local invMag=maxSpeed/d2^0.5 dx=dx\*invMag dy=dy\*invMag local vx,vy=self:getLinearVelocity() local sx,sy=dx-vx,dy-vy local force2=sx\*sx+sy\*sy if force2\>maxForce\*maxForce and force2\>0 then local r=maxForce/(force2^0.5) sx=sx\*r sy=sy\*r end -- self:setLinearVelocity(vx+sx,vy+sy) self:applyForce(sx,sy,self.x,self.y) end local target function img:setTarget(x,y) self.targetX=x self.targetY=y if target then target:removeSelf() end target=display.newCircle(x,y,20) target:setFillColor(255,0,0) self:steer() end function img:update() self:steer() end return img end return M
When I run it using applyForce calls in vehicle:steer the thing quickly gets juddery and flies of the screen (slowly) if I replace it with the simple call to setLinearVelocity the thing works fine. Am I doing something wrong, or is this a bug with the the applyForce call?
Hi again, the more I look at your code, the more I think you will actually ALSO want to move the force calculations over to the enterframe callback too, otherwise, you’ll quickly over-accelerate.
Here is another mod to your code:
local M={} vehicle=M local display=display local math=math require "physics" local physics=physics setfenv(1,M) local maxSpeed=10 local maxForce=10 function create() local img=display.newImage("img/car.png") physics.addBody(img, { density = 1 } ) --EFM function img:steer( event ) if not self.targetX then return end local dx,dy=self.targetX-self.x,self.targetY-self.y local d2=dx\*dx+dy\*dy local invMag=maxSpeed/d2^0.5 dx=dx\*invMag dy=dy\*invMag local vx,vy=self:getLinearVelocity() local sx,sy=dx-vx,dy-vy local force2=sx\*sx+sy\*sy if force2\>maxForce\*maxForce and force2\>0 then local r=maxForce/(force2^0.5) sx=sx\*r sy=sy\*r end -- self:setLinearVelocity(vx+sx,vy+sy) self:applyForce(sx,sy,self.x,self.y) end --EFM begin img.enterFrame = img.steer Runtime:addEventListener( "enterFrame", img) --EFM end local target function img:setTarget(x,y) self.targetX=x self.targetY=y if target then target:removeSelf() end target=display.newCircle(x,y,20) target:setFillColor(255,0,0) --EFM self:steer() end --EFM function img:update() --EFM self:steer() --EFM end return img end return M
I’m not sure if you’re interested, but I wouldn’t mind seeing the whole project and poking at it. If so, I can be reached here:
Work beautifully! It looks like that adding the density of 1 really made the difference. Does Corona not supply a sensible default?
Regards sharing the project, at the moment you’ve seen 100% of it. What I’ll do though is stick it up on GitHub as it grows. I’ve decided to just work through that Nature of Code book I linked to (starting at Chapter 6) and write it in Lua. I want to get a bit more experience writing these sorts of agents. After that I’m going to have a go at implementing Jump Point Search! (one day I may tie everything together for a game!)
If I recall, Corona used to have density defaulted to 1.0, but then along the way I noticed that value stopped getting set. I’m not sure now as I always set it by default to be sure I get what I’m looking for.
Note: Your relative mass will be the width x height x density of the object, so don’t be surprised if you get different responses from objects that take more or less screen space.
Hi again, the more I look at your code, the more I think you will actually ALSO want to move the force calculations over to the enterframe callback too, otherwise, you’ll quickly over-accelerate.
Here is another mod to your code:
local M={} vehicle=M local display=display local math=math require "physics" local physics=physics setfenv(1,M) local maxSpeed=10 local maxForce=10 function create() local img=display.newImage("img/car.png") physics.addBody(img, { density = 1 } ) --EFM function img:steer( event ) if not self.targetX then return end local dx,dy=self.targetX-self.x,self.targetY-self.y local d2=dx\*dx+dy\*dy local invMag=maxSpeed/d2^0.5 dx=dx\*invMag dy=dy\*invMag local vx,vy=self:getLinearVelocity() local sx,sy=dx-vx,dy-vy local force2=sx\*sx+sy\*sy if force2\>maxForce\*maxForce and force2\>0 then local r=maxForce/(force2^0.5) sx=sx\*r sy=sy\*r end -- self:setLinearVelocity(vx+sx,vy+sy) self:applyForce(sx,sy,self.x,self.y) end --EFM begin img.enterFrame = img.steer Runtime:addEventListener( "enterFrame", img) --EFM end local target function img:setTarget(x,y) self.targetX=x self.targetY=y if target then target:removeSelf() end target=display.newCircle(x,y,20) target:setFillColor(255,0,0) --EFM self:steer() end --EFM function img:update() --EFM self:steer() --EFM end return img end return M
I’m not sure if you’re interested, but I wouldn’t mind seeing the whole project and poking at it. If so, I can be reached here:
Work beautifully! It looks like that adding the density of 1 really made the difference. Does Corona not supply a sensible default?
Regards sharing the project, at the moment you’ve seen 100% of it. What I’ll do though is stick it up on GitHub as it grows. I’ve decided to just work through that Nature of Code book I linked to (starting at Chapter 6) and write it in Lua. I want to get a bit more experience writing these sorts of agents. After that I’m going to have a go at implementing Jump Point Search! (one day I may tie everything together for a game!)
If I recall, Corona used to have density defaulted to 1.0, but then along the way I noticed that value stopped getting set. I’m not sure now as I always set it by default to be sure I get what I’m looking for.
Note: Your relative mass will be the width x height x density of the object, so don’t be surprised if you get different responses from objects that take more or less screen space.