I did my best to document this little demo. Use mouse to look around, and arrow keys the move around. Left mouse button to throw the sphere.
These are standard physics equations of projectile motion.
x = v*cos(a)*t
y = v*sin(a)*t-0.5*G*t^2
autocam off
sync on
sync rate 60
hide mouse
player_height# = 100.0 : rem height of the player's eyes
grav_str# = 1.0 : rem gravity strength
obj_size# = 10.0 : rem size of throwing object (in this case, the sphere's radius)
make matrix 1, 1000,1000,40,40
make object sphere 1, obj_size#*2
DO
gosub player_controls
gosub camera_status
rem if left mouse button clicked, initialize the variables for
rem throwing the object.
rem tx#,ty#,tz# are the object's starting positon (character's current position).
rem tYA# is the character's Y rotation.
rem tPitch# is the characters X rotation or the angle at which the character
rem is looking either up or down.
rem T# is the time index. Since the object is just starting to be thrown,
rem current time is 0 seconds.
rem F# is the amount of force that's used to throw the object.
rem tpx# is just a temp variable that needs to be reset.
if mouseclick() and throw = 0
throw=1
tx# = x#
tz# = z#
ty# = get ground height(1,x#,z#)+player_height#
tYA# = a#
tPitch# = 360.0-camera angle x()
T# = 0.0
F# = 40.0
tpx# = 0
endif
if throw = 1 then gosub throw_translocator
sync
LOOP
REM control player's movement
PLAYER_CONTROLS:
runspeed#=0.0
if shiftkey()=1 then runspeed#=6.0
if upkey()=1
x#=newxvalue(x#,a#,6+runspeed#)
z#=newzvalue(z#,a#,6+runspeed#)
endif
if downkey()=1
x#=newxvalue(x#,a#,-6-runspeed#)
z#=newzvalue(z#,a#,-6-runspeed#)
endif
if leftkey()=1
x#=newxvalue(x#,wrapvalue(a#-90.0),5.0+runspeed#)
z#=newzvalue(z#,wrapvalue(a#-90.0),5.0+runspeed#)
endif
if rightkey()=1
x#=newxvalue(x#,wrapvalue(a#+90.0),5.0+runspeed#)
z#=newzvalue(z#,wrapvalue(a#+90.0),5.0+runspeed#)
endif
RETURN
REM control player's angle of site/rotation and position
CAMERA_STATUS:
rem rotate camera according to mouse
a#=wrapvalue(a#+(mousemovex()/3.0))
rem position and rotate camera
cxa#=cxa#+(mousemovey()/3.0)
if cxa#<-90.0 then cxa#=-90.0
if cxa#>90.0 then cxa#=90.0
position camera x#,get ground height(1,x#,z#)+player_height#,z#
rotate camera wrapvalue(cxa#),a#,0
RETURN
REM iterator sub to constantly update position of thrown object
throw_translocator:
rem store old positions
oldtpx#=tpx#
oldtx#=tx#
oldtz#=tz#
rem TPX# is the distance the object has traveled from the origin
TPX#=F#*COS(tPitch#)*T#
rem TPY# is the height of the object's arc.
TPY#=F#*SIN(tPitch#)*T#-(0.5*grav_str#)*(T#^2)
rem dist# is the distance that the object has traveled during this iteration
dis#=abs(oldtpx#-tpx#)
rem tx# and tz# transforms that distance from 2D into a 3D distance based
rem on the character's Y rotation.
tx#=newxvalue(tx#,tYA#,dis#)
tz#=newzvalue(tz#,tYA#,dis#)
rem increment time index
inc T#
rem positions the object
position object 1,tx#,ty#+TPY#,tz#
rem stop movement if object hits ground
if object position y(1)<=obj_size#
throw=0
rem make sure object's last position is above ground
position object 1,oldtx#,obj_size#,oldtz#
endif
RETURN