Hi,
I've been playing around with box2d lately. I moved a ball sprite including its physics body to it's own separate class.
For some reason now when I am updating the physics and then updating the ball graphics it needs to be relative to the original location of the ball.
Below is the partial class code of the ball
function Ball:init(colour, x, y, vx, vy, world)
self.world = world
local filename = ballzFilename[colour]
-- Create ball bitmap object from ball graphic
local ball = Bitmap.new(Texture.new(filename, true))
-- Reference center of the ball for positioning
ball:setAnchorPoint(0.5, 0.5)
ball:setPosition(x, y)
ball:setScale(2.0)
-- Create box2d physical object
local radius = ball:getWidth() / 2
local body = self.world:createBody{type = b2.DYNAMIC_BODY,
fixedRotation = false
}
body:setPosition(ball:getX(), ball:getY())
body:setAngle(ball:getRotation() * math.pi/180)
local circle = b2.CircleShape.new(0, 0, radius)
local fixture = body:createFixture{shape = circle, density = 1.0,
friction = 0.0, restitution = 0.2}
body:setLinearVelocity(vx, vy)
local torqueDirection = -1
if math.random() > 0.5 then
torqueDirection = 1
end
body:applyTorque(-100 * torqueDirection)
body.type = "ball"
body.origx = x
body.origy = y
self.body = body
self:addChild(ball)
self:addEventListener(Event.MOUSE_DOWN, self.onMouseDown, self)
self:addEventListener(Event.MOUSE_MOVE, self.onMouseMove, self)
self:addEventListener(Event.MOUSE_UP, self.onMouseUp, self)
end |
This the update code used in the game play module:
function GameScreen:onEnterFrame(event)
--
-- Physics
self.world:step(1/60, 8, 3)
-- Iterate through all child sprites
for i = 1, self:getNumChildren() do
-- Get specific sprite
local sprite = self:getChildAt(i)
-- Check if sprite HAS a body (ie, physical object reference we added)
if sprite.body then
-- Update position to match box2d world object's position
-- Get physical body reference
local body = sprite.body
if body.type == "ball" then
local bodyx, bodyy = body:getPosition()
-- HACK!!!!!!!!!!!
-- Apply physics body coordinates to sprite
sprite:setPosition(bodyx-body.origx, bodyy-body.origy)
-- Apply rotation to sprite
sprite:setRotation(math.rad(body:getAngle()))
end
end
end
end |
I have to subtract the original position of the body from the current position for the sprite and physics body to line up.
The rotation is not working either.
This was working when it was not encapsulated within a class i.e. The position was not relative.
What am I missing here?
Thanks
Burak
Comments
The problem is because you have this hierachy:
stage -> GameScreen -> Ball -> ball(Bitmap)
So what you do, when you create ball(Bitmap) you set it at x1,y1 coordinates in Ball class coordinates
Then in GameScreen:onEnterFrame you set Balls coordinates to x2, y2,
thus relative to the GameScreen, you Ball object is at (x2, y2) and ball(Bitmap) inside it is at x1, y1 thus they sum
There are two ways to handle it:
1) don't set ball(Bitmap) coordinates at all, let it be at 0,0 and only change Ball object coordinates
2) create Ball:update method and only update ball(Bitmap) position there, leaving Ball object always at 0,0 coordinates
Hope that helps