I would like to make a device which will propel a body in a certain direction. My question is; should use motor joints and other bodies to catapult the body or should i just use body:applyForce()
with some simple maths for angle and force. I am looking for the most realistic affect(favouring realisticness(realisim?) over efficiency. Thanks in advance for any answers.
@Coder See this link. Sounds like it might be close to what you want.
http://codea.io/talk/discussion/5197/starter-game-2#Item_2
Thanks, that seems to be the cleanest approach
Edit: sorry if I was a little cryptic in my question
@Coder just something different if you’re open to another approach, sling shot with a ball and towers of squares, this was one of my first projects:
--# Main
-- flick
-- Use this function to perform your initial setup
function setup()
displayMode(FULLSCREEN)
scr = vec2()
scr.x = 0
scr.y = 0
vel = vec2()
PhysCreate:setup()
-- ball
ball = physics.body(CIRCLE,40)
ball.x = WIDTH/4
ball.y = HEIGHT/2
ball.interpolate = true
ball.friction = 1
ball.restitution = 0.35
ballup = vec2(ball.x,ball.y+40)
ang=vec2(0,40)
-- walls
vert={vec2(WIDTH*5,HEIGHT),vec2(0,HEIGHT),vec2(0,0),vec2(WIDTH*5,0),vec2(WIDTH*5,HEIGHT)}
floor = physics.body(CHAIN,unpack(vert))
-- store catapult variables
pos = vec2(150,400)
tpos = vec2(150,400)
force = 0
-- create boxes in grid
bodies = {}
local y = 1
local x = 1
for i = 1,45 do
bodies[i] = PhysCreate:create(vec2(600+x*200,y*40),vec2(2,2))
-- x < n, n sets the grid width
if x < 5 then
x=x+1
else
y=y+1
x=1
end
end
end
function touchPos()
--print(vec2(CurrentTouch.x,CurrentTouch.y))
if CurrentTouch ~= nil then
return vec2(CurrentTouch.x,CurrentTouch.y)
else
return vec2(150,400)
end
end
function moveScreen()
if ball.x > WIDTH - 300 - scr.x then
scr.x = WIDTH - 300 - ball.x
elseif ball.x < scr.x*-1 + 40 then
scr.x = 40 - ball.x
end
translate(scr.x,0)
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)
moveScreen()
-- start touch and store first position
if CurrentTouch ~= nil and CurrentTouch.state == BEGAN and touchPos().x < 300 then
holding = 1
if touchPos().x > 40 then
pos = touchPos()
end
end
-- keep ball in the air while in red zone
if ball.x < 300 then
if ball.y < 100 then
ball.linearVelocity = vec2(ball.linearVelocity.x*0.3,(100-ball.y)*5)
end
end
-- grab ball and set force
if holding == 1 then
local bl = (touchPos()-vec2(ball.x,ball.y)):normalize()
ball.linearVelocity = bl*touchPos():dist(vec2(ball.x,ball.y))*10
force = touchPos():dist(pos)*0.1
end
-- release catapult and set ball velocity
if holding == 1 and CurrentTouch.state == ENDED and touchPos():dist(vec2(ball.x,ball.y)) < 40 then
vel = (pos-touchPos())*force
ball.linearVelocity = vel
holding = 0
end
-- Set catapult starting variable if in red zone
if ball.x > 300 and CurrentTouch.state == BEGAN and touchPos().x < 300 and holding == 0 then
holding = 1
elseif ball.x > 300 and touchPos().x > 300 and CurrentTouch.state == MOVING then
holding = 0
end
-- draw boxes
PhysCreate:draw()
-- draw gui
-- catapult area (red zone)
line(300,0,300,HEIGHT)
strokeWidth(0)
fill(250,50,50,50)
rect(-100,0,400,HEIGHT)
-- catapult
if holding == 1 then
strokeWidth(15)
fill(255)
line(scr.x*-1+pos.x,pos.y,scr.x*-1+touchPos().x,touchPos().y)
strokeWidth(3)
fill(186, 186, 186, 255)
ellipse(scr.x*-1+pos.x,pos.y,30)
end
-- draw ball
strokeWidth(5)
fill(100)
ellipse(ball.x,ball.y,80)
ang = ang:rotate(ball.angularVelocity/2000)
ballup = ball.position + (ang):normalize()*35
line(ball.x,ball.y,ballup.x,ballup.y)
end
--# PhysCreate
PhysCreate = class()
function PhysCreate:init(x)
self.x = x
end
function PhysCreate:setup()
Di = 0
DTbl = {}
end
function PhysCreate:create(vpos,vsize)
local vert = {vec2(-10*vsize.x,10*vsize.y),vec2(-10*vsize.x,-10*vsize.y),
vec2(10*vsize.x,-10*vsize.y),vec2(10*vsize.x,10*vsize.y)}
local p = physics.body(POLYGON,unpack(vert))
p.mass = 2
p.x = vpos.x
p.y = vpos.y
p.w = vsize.x*10*2
p.h = vsize.y*10*2
p.interpolate = true
p.sleepingAllowed = false
p.m = mesh()
local mr = p.m:addRect(p.x,p.y,p.w,p.h,0)
p.m:setRectTex(mr,0,0,1,1)
Di = Di + 1
DTbl[Di] = {p.m,mr,p}
end
function PhysCreate:draw()
for i=1,#DTbl do
local d = DTbl[i]
d[1]:draw()
d[1]:setRect(d[2],d[3].x,d[3].y,d[3].w,d[3].h,d[3].angle/57.3)
end
end
function PhysCreate:touched(touch)
-- Codea does not automatically call this method
end