Here's my first stab at this challenge. Thought I'd have a go at some proper Newtonian physics!
The rocket has two thrusters, working independently. By using the two thrusters skillfully, you can control both the angular and linear forces you need to steer the rocket. Try getting it to fly to the side for a while, then try to get it to hover, or land gracefully on the landing pad - it's quite tricky to begin with, but after a bit of practice you can get quite good at it.
left thruster: leftkey
right thruster: rightkey
Rem Project: lunar lander
Rem Created: 02/03/2006 17:00:52
Rem ***** Main Source File *****
sync on
sync rate 0
autocam off
hide mouse
color backdrop 0
position camera 0,0,-50
gosub values
gosub make_ship
gosub make_moon
gosub make_particles
gosub make_landing_pad
starttime=timer()
do
gosub timer_maths
gosub controls
gosub physics
gosub collision
gosub position_particles
text 0,0,str$(screen fps())
sync
loop
timer_maths:
newtime=timer()-starttime
dt=newtime-oldtime
oldtime=newtime
return
make_ship:
ship=free_object()
make object cylinder ship,size#
uppersection=free_object()
make object cylinder uppersection,size#
position object uppersection,0,size#,0
glue object to limb uppersection,ship,0
nose=free_object()
make object cone nose,size#
position object nose,0,size#*2,0
glue object to limb nose,ship,0
booster1=free_object()
make object cylinder booster1,size#/2.0
scale object booster1,100,200,100
position object booster1,-size#*(3/4.0),0,0
glue object to limb booster1,ship,0
booster1nose=free_object()
make object cone booster1nose,size#/2.0
position object booster1nose,-size#*(3/4.0),size#*(3/4.0),0
glue object to limb booster1nose,ship,0
booster2=free_object()
make object cylinder booster2,size#/2.0
scale object booster2,100,200,100
position object booster2,size#*(3/4.0),0,0
glue object to limb booster2,ship,0
booster2nose=free_object()
make object cone booster2nose,size#/2.0
position object booster2nose,size#*(3/4.0),size#*(3/4.0),0
glue object to limb booster2nose,ship,0
dummy=free_object()
make object cube dummy,1
make mesh from object 1,dummy
delete object dummy
add limb ship,1,1
hide limb ship,1
offset limb ship,1,-size#*(3/4.0),-size#/2.0,0
add limb ship,2,1
hide limb ship,2
offset limb ship,2,size#*(3/4.0),-size#/2.0,0
`xrotate object ship,-90
`fix object pivot ship
return
make_moon:
moon=free_object()
make object plain moon,300,50
xrotate object moon,-90
repeat
position object moon,0,object position y(moon)-0.1,0
until object screen y(moon)>screen height()-30
color object moon,rgb(150,130,110)
return
make_landing_pad:
pad=free_object()
make object cube pad,4
position object pad,0,object position y(moon)+2,0
color object pad,rgb(255,0,0)
return
make_particles:
box 0,0,10,10,rgb(255,0,0),rgb(255,255,0),rgb(255,155,0),rgb(255,255,255)
get image 1,0,0,10,10
make particles 1,1,10,12
set particle floor 1,0
set particle life 1,6
hide particles 1
make particles 2,1,10,12
hide particles 2
set particle floor 2,0
set particle life 2,6
set particle gravity 1,20
set particle gravity 2,20
return
values:
size#=2
height#=size#
radius#=size#/2.0
thrust#=0.01
mass#=1000.0
g#=0.00001 `acceleration due to gravity
moi#=((3/80.0)*mass#*height#^2)+((3/20.0)*mass#*radius#^2) `moment of inertia for solid cone through z-axis
return
controls:
thruster1#=0
thruster2#=0
hide particles 1
hide particles 2
if leftkey()=1 then thruster1#=thrust#:show particles 1
if rightkey()=1 then thruster2#=thrust#:show particles 2
return
physics:
`calculate angular motion
torque#=(thruster1#-thruster2#)*radius#-rotationaldamping# `clockwise
angularacceleration#=torque#/moi#
angularvelocity#=angularvelocity#+angularacceleration#*dt
angle#=angle#+angularvelocity#*dt
zrotate object ship,-angle#
`calculate linear motion
weight#=mass#*g#
xresultantforce#=(sin(angle#)*(thruster1#+thruster2#))-friction#
yresultantforce#=cos(angle#)*(thruster1#+thruster2#)-weight#+reactionforce#
xlinearacceleration#=xresultantforce#/mass#
ylinearacceleration#=yresultantforce#/mass#
xlinearvelocity#=xlinearvelocity#+xlinearacceleration#*dt
ylinearvelocity#=ylinearvelocity#+ylinearacceleration#*dt
xposition#=xposition#+xlinearvelocity#*dt
yposition#=yposition#+ylinearvelocity#*dt
position object ship,xposition#,yposition#,0
return
position_particles:
position particles 1,limb position x(ship,1),limb position y(ship,1),0
position particles 2,limb position x(ship,2),limb position y(ship,2),0
rotate particles 1,0,0,-angle#
rotate particles 2,0,0,-angle#
return
collision:
`sides of screen
if object screen x(ship)>screen width() or object screen x(ship)<0
xposition#=-xposition#*0.9
endif
`pad
if object collision(ship,pad)=1 then collision=1 else collision=0
if collision=1 and object position y(ship)<object position y(pad)+object size y(pad)/2.0
xlinearvelocity#=0
endif
`bottom of screen
if object position y(ship)<object position y(moon)+size# or collision=1
reactionforce#=weight#
ylinearvelocity#=0
friction#=xlinearvelocity#*0.95
rotationaldamping#=angularvelocity#*0.95
else
reactionforce#=0
friction#=0
rotationaldamping#=0
endif
return
return
function free_object()
repeat
inc n
until object exist(n)=0
endfunction n
function free_entity()
repeat
inc n
until sprite exist(n)=0 and image exist(n)=0
endfunction n
Ignore this:
autocam off
sync on
position camera 0,0,-100
make object sphere 1,20
make object cone 2,5
position object 2,0,50,0
do
text 0,0,str$(ang#)
if leftkey()=1 then dec ang#
if rightkey()=1 then inc ang#
if ang#>180 then dec ang#,360
if ang#<-180 then inc ang#,360
rotate object 2,0,0,-ang#
bearing#=atanfull((object position x(2)-object position x(1)),(object position y(2)-object position y(1)))
text 0,20,str$(bearing#)
if upkey()=1 then thrust#=0.1 else thrust#=0
move object up 2,thrust#
sync
loop