--include box2d library
require "box2d"
--let's create separate scene and hold everything there
--then it will be easier to reuse it if you want to use SceneManager class
scene = gideros.class(Sprite)
-- for creating objects using shape
-- as example - bounding walls
function scene:wall(x, y, width, height)
local wall = Shape.new()
--define wall shape
wall:beginPath()
--we make use (0;0) as center of shape,
--thus we have half of width and half of height in each direction
wall:moveTo(-width/2,-height/2)
wall:lineTo(width/2, -height/2)
wall:lineTo(width/2, height/2)
wall:lineTo(-width/2, height/2)
wall:closePath()
wall:endPath()
wall:setPosition(x,y)
--create box2d physical object
local body = self.world:createBody{type = b2.STATIC_BODY}
body:setPosition(wall:getX(), wall:getY())
body:setAngle(wall:getRotation() * math.pi/180)
local poly = b2.PolygonShape.new()
poly:setAsBox(wall:getWidth()/2, wall:getHeight()/2)
local fixture = body:createFixture{shape = poly, density = 1.0,
friction = 0.1, restitution = 0.2}
wall.body = body
wall.body.type = "wall"
--add to scene
self:addChild(wall)
--return created object
return wall
end
-- for creating objects using image
-- as example - ball
function scene:ball(x, y)
--create ball bitmap object from ball graphic
local ball = Bitmap.new(Texture.new("./ball.png"))
--reference center of the ball for positioning
ball:setAnchorPoint(0.5,0.5)
ball:setPosition(x,y)
--get radius
local radius = ball:getWidth()/2
--create box2d physical object
local body = self.world:createBody{type = b2.DYNAMIC_BODY}
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.1, restitution = 0.2}
ball.body = body
ball.body.type = "ball"
--add to scene
self:addChild(ball)
--return created object
return ball
end
--running the world
local worldspeed = 1/60
local frame_count = 0
local speed_ratio = 5
function scene:onEnterFrame()
-- frame_count % speed_ratio do not work on this snippet?
frame_count = frame_count + 1
if frame_count < speed_ratio then
return true
else
frame_count = 0
end
-- all code above equals frame_count % speed_ratio == 0
-- edit the step values if required. These are good defaults!
self.world:step(worldspeed, 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
--get body coordinates
local bodyX, bodyY = body:getPosition()
--apply coordinates to sprite
sprite:setPosition(bodyX, bodyY)
--apply rotation to sprite
sprite:setRotation(body:getAngle() * 180 / math.pi)
end
end
end
--on scene initialization
function scene:init()
--create world instance
self.world = b2.World.new(0, 10, true)
local screenW = application:getContentWidth()
local screenH = application:getContentHeight()
--create bounding walls outside the scene
self:wall(0,screenH/2,10,screenH)
self:wall(screenW/2,0,screenW,10)
self:wall(screenW,screenH/2,10,screenH)
self:wall(screenW/2,screenH,screenW,10)
--create ball
self.ball_instance = self:ball(100, screenH - 20)
--set up debug drawing
local debugDraw = b2.DebugDraw.new()
self.world:setDebugDraw(debugDraw)
self:addChild(debugDraw)
--run world
self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
self:addEventListener(Event.MOUSE_DOWN, self.onMouseDown, self)
end
-- create a mouse joint on mouse down
function scene:onMouseDown(event)
if self:hitTestPoint(event.x, event.y) then
local x, y = self.ball_instance:getPosition()
local xVect = 0
local yVect = 200*100
self.ball_instance.body:applyForce(xVect, yVect, x, y)
end
end
local scene_instance = scene.new()
stage:addChild(scene_instance)