Thanks for that info Golelorn. Very interesting stuff
For my purposes it's working. I changed the gravity and it seems to give me a consistent result. I'm sure the longer the path the less accurate it will be (It is already not very accurate but good enough for a game i think)
These are the calculations;
1. Speed / 31.5 (From the SetObject3DPhysicsLinearVelocity() function)
2. Friction * 1.99 (From the GetObject3DPhysicsFriction() function)
3. Gravity * .035 (From the Set3DPhysicsGravity() function, Default is -10)
// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts
SetClearColor(0x80, 0x80, 0x80)
#option_explicit
#constant TRUE 1
#constant FALSE 0
type color
r as float
g as float
b as float
endtype
type point
x as float
y as float
z as float
endtype
type aim
newpath as integer[]
oldpath as integer[]
dpath as integer[]
mode as integer
start as integer
plane as integer
target as integer
ball as integer
dir as point
last as point
cursor as point
friction as float
steps as integer
speed as float
endtype
global gravity as integer = -5
create3DPhysicsWorld()
Set3DPhysicsGravity( 0, gravity, 0 )
aim as aim
aim.ball = CreateObjectSphere(1.5, 8, 8)
SetObjectColor(aim.ball, 0xff, 0, 0, 0xff)
SetObjectVisible(aim.ball, 0)
aim.plane = CreateObjectPlane(15, 15)
SetObjectPosition(aim.plane, 0, 0, 30)
aim.target = CreateObjectPlane(1, 1)
SetObjectPosition(aim.target, 0, 0, 0)
SetObjectColor(aim.target, 0xff, 0, 0, 0xff)
aim.start = CreateObjectBox(1, 1, 1)
SetObjectColor(aim.start, 0, 0xff, 0, 0xff)
SetObjectPosition(aim.start, 0, 0, -10)
SetCameraPosition(1, 0, 5, GetCameraZ(1))
SetCameraLookAt(1, 0, 0, 0, 0)
#constant AIM_MODE_FIRE 0
#constant AIM_MODE_TRACK 1
do
aim.speed = 100
AimPath(aim)
Print( str(ScreenFPS()) + " " + str(aim.steps + 1))
Step3DPhysicsWorld()
Sync()
loop
function AimPath(aim ref as aim)
world as point
depth as float
current as point
last as point
i as integer
cam as point
plane as point
z as float
o as integer
n as integer
cam.x = GetCameraX(1)
cam.y = GetCameraY(1)
cam.z = GetCameraZ(1)
plane.x = GetObjectX(aim.plane)
plane.y = GetObjectY(aim.plane)
plane.z = GetObjectZ(aim.plane)
depth = Distance(plane, cam)
world.x = Get3DVectorXFromScreen( GetPointerX(), GetPointerY() ) * Depth + cam.x
world.y = Get3DVectorYFromScreen( GetPointerX(), GetPointerY() ) * Depth + cam.y
world.z = Get3DVectorZFromScreen( GetPointerX(), GetPointerY() ) * Depth + cam.z
SetObjectPosition(aim.target, world.x, world.y, GetObjectZ(aim.plane) - 0.1)
SetObjectLookAt(aim.start, world.x, world.y, GetObjectZ(aim.plane) - 0.1, 0)
if aim.friction = 0
Delete3DPhysicsBody(aim.ball)
aim.dir = GetObjectDirectionVector(aim.start, 1, 1)
SetObjectPosition(aim.ball, GetObjectX(aim.start), GetObjectY(aim.start), GetObjectZ(aim.start))
Create3DPhysicsDynamicBody(aim.ball)
SetObjectShapeSphere(aim.ball)
aim.friction = GetObject3DPhysicsFriction( aim.ball ) * 1.98
endif
for i=0 to aim.dpath.length
DeleteObject(aim.dpath[i])
next
aim.dpath.length = -1
last.x = GetObjectX(aim.start)
last.y = GetObjectY(aim.start)
last.z = GetObjectZ(aim.start)
aim.dir = GetObjectDirectionVector(aim.start, 1, aim.speed / 31.5)
for i=0 to 12
aim.dir.x = aim.dir.x * aim.friction
aim.dir.y = aim.dir.y * aim.friction
aim.dir.z = aim.dir.z * aim.friction
inc aim.dir.y, gravity * .035
current.x = last.x + aim.dir.x
current.y = last.y + aim.dir.y
current.z = last.z + aim.dir.z
DrawEllipse(last.z * 10 + 200, last.y * -10 + 100, 3, 3, 0x0000ff, 0x0000ff, 1)
DrawLine(last.z * 10 + 200, last.y * -10 + 100, current.z * 10 + 200, current.y * -10 + 100, 0x0000ff, 0x0000ff)
aim.dpath.insert(Draw3DLine(last, current, 1, 0xff, 0, 0))
last = current
next
select aim.mode
case AIM_MODE_FIRE
Delete3DPhysicsBody(aim.ball)
aim.dir = GetObjectDirectionVector(aim.start, 1, 1)
SetObjectPosition(aim.ball, GetObjectX(aim.start), GetObjectY(aim.start), GetObjectZ(aim.start))
Create3DPhysicsDynamicBody(aim.ball)
SetObjectShapeSphere(aim.ball)
SetObject3DPhysicsLinearVelocity(aim.ball, aim.dir.x, aim.dir.y, aim.dir.z, 100)
aim.mode = AIM_MODE_TRACK
aim.last.x = GetObjectX(aim.start)
aim.last.y = GetObjectY(aim.start)
aim.last.z = GetObjectZ(aim.start)
endcase
case AIM_MODE_TRACK
current.x = GetObjectX(aim.ball)
current.y = GetObjectY(aim.ball)
current.z = GetObjectZ(aim.ball)
aim.newpath.insert(Draw3DLine(aim.last, current, 0, 0, 0xff, 0))
aim.last = current
z = GetObjectZ(aim.plane)
if aim.newpath.length > 11
for i=0 to aim.oldpath.length
DeleteObject(aim.oldpath[i])
next
for i=0 to aim.newpath.length
SetObjectVisible(aim.newpath[i], 1)
next
aim.oldpath = aim.newpath
aim.newpath.length = -1
aim.mode = AIM_MODE_FIRE
aim.steps = aim.oldpath.length
endif
endcase
endselect
for i=0 to aim.oldpath.length - 1
o = aim.oldpath[i]
n = aim.oldpath[i + 1]
DrawEllipse(GetObjectZ(o) * 10 + 200, GetObjectY(o) * -10 + 100, 3, 3, 0x00ff00, 0x00ff00, 1)
DrawLine(GetObjectZ(o) * 10 + 200, GetObjectY(o) * -10 + 100, GetObjectZ(n) * 10 + 200, GetObjectY(n) * -10 + 100, 0x00ff00, 0x00ff00)
next
endfunction
function Draw3DLine(fp as point, tp as point, vis as integer, r as integer, g as integer, b as integer )
o as integer
dist as float
angley as float
o = CreateObjectPlane(.5,.5)
RotateObjectLocalX(o, 90)
SetObjectPosition(o, 0, 0, .25)
FixObjectPivot(o)
SetObjectPosition(o, fp.x, fp.y, fp.z)
setobjectcolor(o, r, g, b, 0xff)
dist = sqrt((fp.x - tp.x)^2 + (fp.y - tp.y)^2 + (fp.z - tp.z)^2 )
SetObjectScale(o, 1, 1, dist * 2)
SetObjectLookAt(o, tp.x, tp.y, tp.z, 0)
SetObjectVisible(o, vis)
endfunction o
function Distance(fp as point, tp as point)
dist as float
dist = sqrt((fp.x - tp.x)^2 + (fp.y - tp.y)^2 + (fp.z - tp.z)^2 )
endfunction dist
Function GetObjectDirectionVector( objID as integer, direction as integer, speed as float)
vector as point
tempObj as integer
tempObj = CreateObjectBox( 1.0, 1.0, 1.0 )
SetObjectPosition( tempObj, GetObjectWorldX( objID ), GetObjectWorldY( objID ), GetObjectWorldZ( objID ) )
SetObjectRotation( tempObj, GetobjectWorldAngleX( objID ), GetobjectWorldAngleY(objID), GetobjectWorldAngleZ( objID ) )
select direction
case 1 :
MoveObjectLocalZ( tempObj, speed )
endcase
case 2 :
MoveObjectLocalZ( tempObj, -speed)
endcase
case 3 :
MoveObjectLocalY( tempObj, speed )
endcase
case 4 :
MoveObjectLocalY( tempObj, -speed )
endcase
case 5 :
MoveObjectLocalX( tempObj, speed )
endcase
case 6 :
MoveObjectLocalX( tempObj, -speed )
endcase
endselect
vector.x = GetObjectWorldX( tempObj ) - GetObjectWorldX( objID )
vector.y = GetObjectWorldY( tempObj ) - GetObjectWorldY( objID )
vector.z = GetObjectWorldZ( tempObj ) - GetObjectWorldZ( objID )
DeleteObject(tempObj)
EndFunction vector