Here's my entry. I worked on it during lunch breaks. Glad to have 3 weeks as I would not have been able to complete it in 2.
set display mode 1024,768,32
hide mouse
backdrop on
color backdrop 0
sync on
rem Create waypoints for movement of escalator
dim ramp1_y#(20)
dim ramp1_z#(20)
dim ramp1_a#(20)
dim Oramp(4)
dim Oleg(4)
dim Opad(10)
dim pad_pos(10)
rem Define Object numbers
temp=1
Oramp(1)=2
Oramp(2)=3
Oramp(3)=4
Oramp(4)=5
Oball=6
Oleg(1)=7
Oleg(2)=8
Oleg(3)=9
Oleg(4)=10
Obase=11
rem Define segments of escalator
obj=12
for x=1 to 10
Opad(x)=obj
inc obj
next x
Oramp1=22
Opost=23
global Oswing=24
Obox=25
rem Define Mesh numbers
Mboard=2
Mrampend=3
Mrampcyl=4
Mboxseg=5
Mball=6
Mswingarm=7
rem Define Image numbers
Iboard=2
Iball=3
Ibase=4
Instructions=5
rem Define textures
Tramp1_x#=0.0
Tramp1_y#=0.0
gosub make_objects rem Create and build all the objects
gosub get_elevator rem Get the waypoints for the escalator movement
position camera 0,30,-100
point camera 0,30,0
rem Set up the marble movements parameters
ball_x_start#=0.03 rem Starting speed for rolling marble
ball_x#=ball_x_start#
xaccel#=0.0002 rem Rate of acceleration for the marble on the ramps
xmax#=0.4 rem Maximum speed of the marble on the ramps
ball_y#=0.0 rem Marble speed for other axes
ball_z#=0.0
ball_z_start#=2.75 rem Marble position on the ramps
gravity#=0.008 rem Acceleration due to gravity
dir#=1.0 rem Direction of roll of the marble
mag#=0.6 rem Magnitude of force when collision with escalator
pmag#=0.8 rem Magnitude of force when collision with escalator paddles
rem Set up the swing arm movements
sdir#=1.0 rem Direction of swing
smax#=0.3 rem Maximum speed of the swing
sv#=0.0 rem Swing velocity
sa#=0.01 rem Acceleration of the swing velocity
sangle#=10.0 rem Starting angle of the swing arm
rangle#=-95.0 rem Limit of the swing arm motion
swingfull=0 rem Swing arm box has the marble 0=no, 1=yes
rem Define activity identifiers for collision detection and physics
ramps=1
escalator=2
swingarm=3
outofbox=4
activity=ramps rem Start the marble on the ramps
gosub position_objects rem Place all objects in the scene
gosub instructions
while not escapekey()
rem Move the camera around the object using the arrow keys
move_camera()
rem Animate the escalator
gosub move_ramp
rem Animate the swing arm
gosub move_swing
rem Get the current position of the marble
Oball_x#=object position x(Oball)
Oball_y#=object position y(Oball)
Oball_z#=object position z(Oball)
rem Calculate which ramp the marble is on based on the marble's height
effective_ramp=int(Oball_y#/20)+1
if effective_ramp>4 then effective_ramp=4
if effective_ramp<1 then effective_ramp=1
rem Move the marble horizontally
Oball_x#=Oball_x#+ball_x#*dir#
ball_x#=ball_x#+xaccel#
if ball_x#>xmax# then ball_x#=xmax# rem Limit the top speed of the marble
rem Apply gravity to the marble
ball_y#=ball_y#+gravity#
position object Oball,Oball_x#,Oball_y#-ball_y#,Oball_z#-ball_z#
if object position z(Oball)=ball_z_start# and effective_ramp>1
if activity=swingarm then activity=ramps
rem Check for collision of the marble with the ramp
if object collision(Oramp(effective_ramp),Oball)
if effective_ramp && 1 = 1 rem Check which direction to marble should be rolling on the ramp
if dir#=1.0
ball_x#=ball_x_start# rem Set starting speed of the marble if it landed on a new ramp
endif
dir#=-1.0
else
if dir#=-1.0
ball_x#=ball_x_start# rem Set starting speed of the marble if it landed on a new ramp
endif
dir#=1.0
endif
position object Oball,object position x(Oball),object position y(Oball)+ball_y#,object position z(Oball)
ball_y#=ball_y#*-0.5 rem Apply bounce friction to the marble
endif
rem Roll the marble in the direction of motion
zrotate object Oball,object angle z(Oball)-ball_x#*12.0*dir#
else
if object position z(Oball)<=76 and activity<>swingarm rem Marble is on escalator
if activity=ramps then activity=escalator
if activity=escalator
if object position x(Oball)>=ramp1_x#
dir#=0.0 rem Stop the marble in the center of the escalator
else
dir#=1.0 rem Keep the marble rolling until it reaches the center of the escalator
endif
rem Check for collision of the marble with the escalator paddles
found=0
for i=1 to 10
if object collision(Opad(i),Oball) then found=i
next i
if found>0
rem Calculate the direction of force on the marble and apply to the marble
ydir#=cos(object angle x(Opad(found))+90)*pmag#
zdir#=sin(object angle x(Opad(found))+90)*pmag#
position object Oball,object position x(Oball),object position y(Oball)+ydir#,object position z(Oball)+zdir#
endif
rem Check for collision of the marble with the escalator
if object collision(Oramp1,Oball)
if object position z(Oball)<64
temp#=ball_y#*mag#
ball_y#=ball_z#*mag#
ball_z#=temp#
else
ball_y#=-0.05
ball_z#=0.1
endif
rem Apply collision force to the marble
position object Oball,object position x(Oball),object position y(Oball)-ball_y#,object position z(Oball)-ball_z#
endif
endif
else
if activity=escalator then activity=swingarm
if activity=swingarm
ball_z#=0.0 rem Make ball fall straight down
if swingfull=0 rem Ball has not made contact with box yet
if object collision(Obox,Oball) rem If ball has landed in the box
position object Oball,limb position x(Oswing,Lhorzarm),object position y(Oball)-ball_y#,limb position z(Oswing,Lhorzarm)
swingfull=1 rem Swing the arm with the ball in the box
endif
else
rem Keep the ball in the box using the hidden limb on the swing arm
position object Oball,limb position x(Oswing,Lballholder),limb position y(Oswing,Lballholder),limb position z(Oswing,Lballholder)
endif
endif
endif
endif
if activity=outofbox rem Ball is falling out of the box onto the ramp
position object Oball,object position x(Oball),object position y(Oball)-ball_y#,object position z(Oball)-0.1
if object position z(Oball)<ball_z_start# rem When ball reaches the center of the ramp, keep it in the center
position object Oball,object position x(Oball),object position y(Oball)-ball_y#,ball_z_start#
activity=ramps
endif
endif
sync
endwhile
end
move_swing:
if activity=swingarm and swingfull=1 rem If ball is in the box, swing the arm
sv#=sv#-sa# rem Accelerate the swing arm for realistic physics
if abs(sv#)>smax# then sv#=sv#+sa# rem Limit the speed of the swing arm
rem Swing the arm
rotate object Oswing,object angle y(Oswing)/2.2,object angle y(Oswing)+sv#,object angle z(Oswing)
rem Pivot the joint holding the box
rotate limb Oswing,Lvertjoint,0,object angle y(Oswing)*-1.0+10.0,0
rem Rotate the box to stay in position with the end of the swing arm
yrotate object Obox,limb angle y(Oswing,Lvertjoint)
rem Swing arm reaches limit to dump marble onto ramp
if object angle y(Oswing)<= rangle#
swingfull=0
sv#=0.0
activity=outofbox
ball_y#=0.0
ball_x#=ball_X_start#
endif
else rem Swing arm back into starting position
sv#=sv#+sa# rem Accelerate the swing arm for realistic physics
if abs(sv#)>smax# then sv#=sv#-sa# rem Limit the speed of the swing arm
rem Swing the arm
rotate object Oswing,object angle y(Oswing)/2.2,object angle y(Oswing)+sv#,object angle z(Oswing)
rem Pivot the joint holding the box
rotate limb Oswing,Lvertjoint,0,object angle y(Oswing)*-1.0+10.0,0
rem Rotate the box to stay in position with the end of the swing arm
yrotate object Obox,limb angle y(Oswing,Lvertjoint)
rem Swing arm reaches starting position
if object angle y(Oswing)>= sangle#
yrotate object Oswing,object angle y(Oswing)-sv#
sv#=sv#*-0.5 rem Bounce the arm for realistic physics
endif
endif
return
move_ramp:
for i=1 to 10
rem Get position of the escalator segment
y#=object position y(Opad(i))
z#=object position z(Opad(i))
rem Check its distance to the next waypoint
dist#=sqrt((ramp1_y#(pad_pos(i))-y#)^2+(ramp1_z#(pad_pos(i))-z#)^2)
rem If it is close enough to the next waypoint
if dist#<0.5
rem Place the segment at the waypoint
position object Opad(i),ramp1_x#,ramp1_y#(pad_pos(i)),ramp1_z#(pad_pos(i))
rem Correctly orient the segment rotation to the waypoint
xrotate object Opad(i),ramp1_a#(pad_pos(i))
rem Point at the next waypoint
dec pad_pos(i)
if pad_pos(i)<1 then pad_pos(i)=20
else
rem Calculate the step of motion to move the segment towards the next waypoint
ydir#=(ramp1_y#(pad_pos(i))-y#)/dist#*0.2
zdir#=(ramp1_z#(pad_pos(i))-z#)/dist#*0.2
position object Opad(i),ramp1_x#,y#+ydir#,z#+zdir#
rem Slowly adjust the segment rotation to move towards the waypoint orientation
if object angle x(Opad(i))<>ramp1_a#(pad_pos(i))
angle#=ramp1_a#(pad_pos(i))-7*dist#
xrotate object Opad(i),angle#
endif
endif
next i
return
make_objects:
rem Make a board mesh for use with the ramp object
make object box temp,60,2,5
make mesh from object Mboard,temp
delete object temp
rem Make a wood texture for use with the objects
create bitmap temp,32,32
ink rgb(120,38,0),0
box 0,0,31,31
ink rgb(180,60,0),0
for x=1 to 50
dot rnd(31),rnd(31)
next x
get image Iboard,0,0,31,31
delete bitmap temp
rem Make ramps
make object Oramp(1),Mboard,Iboard
add limb Oramp(1),1,Mboard
offset limb Oramp(1),1,0,2,5
rotate limb Oramp(1),1,-45,0,0
texture limb Oramp(1),1,Iboard
xrotate object Oramp(1),22.5
fix object pivot Oramp(1)
set object collision to polygons Oramp(1)
instance object Oramp(2),Oramp(1)
instance object Oramp(3),Oramp(1)
instance object Oramp(4),Oramp(1)
set object collision to polygons Oramp(2)
set object collision to polygons Oramp(3)
set object collision to polygons Oramp(4)
rem Make marble
create bitmap temp,256,256
ink rgb(192,192,192),0
box 0,0,255,255
ink rgb(64,64,64),0
for x=1 to 500
dot rnd(255),rnd(255)
next x
get image Iball,0,0,255,255
delete bitmap temp
set current bitmap 0
make object sphere Oball,9,20,20
texture object Oball,Iball
set object Oball, 1,1,1,2,1,0,1
yrotate object Oball, 180
set object collision to spheres Oball
rem Make legs
make object cylinder Oleg(1),60
texture object Oleg(1),Iboard
instance object Oleg(2),Oleg(1)
instance object Oleg(3),Oleg(1)
instance object Oleg(4),Oleg(1)
scale object Oleg(1),3,100,3
scale object Oleg(2),3,100,3
scale object Oleg(3),3,120,3
scale object Oleg(4),3,120,3
rem Make base
size=1023
create bitmap 1,size+1,size+1
ink rgb(64,64,64),0
box 0,0,size,size
ink rgb(128,128,128),0
for x=0 to size step 3
line x,0,rnd(size),size
line 0,x,size,rnd(size)
next x
get image Ibase,0,0,size,size
delete bitmap 1
make object box Obase,70,5,50
texture object Obase,Ibase
rem Make escalator
make object box Opad(1),10,10,2
texture object Opad(1),Iboard
offset limb Opad(1),0,0,5,0
set object collision to polygons Opad(1)
rem Make all escalator segments
for x=2 to 10
instance object Opad(x),Opad(1)
offset limb Opad(x),0,0,5,0
set object collision to polygons Opad(x)
next x
rem Make escalator centre (base)
make object cylinder temp,10
scale object temp,140,100,140
make mesh from object Mrampend,temp
delete object temp
make object sphere temp,14
scale object temp,1,100,100
make mesh from object Mrampcyl,temp
delete object temp
make object box Oramp1,10,14,90
add limb Oramp1,1,Mrampend
offset limb Oramp1,1,0,0,45
rotate limb Oramp1,1,0,0,90
add limb Oramp1,2,Mrampend
offset limb Oramp1,2,0,0,-45
rotate limb Oramp1,2,0,0,90
add limb Oramp1,3,Mrampcyl
offset limb Oramp1,3,5,0,-45
add limb Oramp1,4,Mrampcyl
offset limb Oramp1,4,-5,0,-45
add limb Oramp1,5,Mrampcyl
offset limb Oramp1,5,5,0,45
add limb Oramp1,6,Mrampcyl
offset limb Oramp1,6,-5,0,45
texture object Oramp1,Iboard
xrotate object Oramp1,135
set object collision to polygons Oramp1
rem Make swing post
make object cylinder Opost,30
scale object Opost,8,100,8
texture object Opost,Iboard
rem Make swing
rem Define limbs
Lmainjoint=1
Lvertjoint=2
Lvertarm=3
Lboxjoint=4
Lhorzarm=5
Lballholder=6
make object cylinder temp,60
scale object temp,5,100,5
make mesh from object Mswingarm,temp rem create a mesh from the scaled object so that the scaling
delete object temp rem does not apply to limbs of the object
make object Oswing,Mswingarm,0 rem remake the object from the mesh of the scaled object
offset limb Oswing,0,0,30,0 rem Shift the main object so that it rotates from its end, not its middle
texture object Oswing,Iboard
make object sphere temp,10,20,20 rem Create object for use with making ball joints
make mesh from object Mball,temp rem Create mesh to use with add limb command
delete object temp
add limb Oswing,Lmainjoint,Mball rem Add the main joint for the swing arm
texture limb Oswing,Lmainjoint,Iball
add limb Oswing,Lvertjoint,Mball rem Add the joint for the vertical arm
scale limb Oswing,Lvertjoint,50,50,50 rem Shrink the vertical joint by half
offset limb Oswing,Lvertjoint,0,60,0 rem Position the vertical joint at the end of the main arm
texture limb Oswing,Lvertjoint,Iball
add limb Oswing,Lvertarm,Mswingarm rem Add the vertical arm
scale limb Oswing,Lvertarm,100,50,100 rem Shorten the vertical arm to the correct length
rotate limb Oswing,Lvertarm,0,0,90 rem Orient the vertical arm to vertical
offset limb Oswing,Lvertarm,15,0,0 rem Position the vertical arm at the vertical joint
texture limb Oswing,Lvertarm,Iboard
link limb Oswing,Lvertjoint,Lvertarm
add limb Oswing,Lboxjoint,Mball rem Add the joint for the horizontal arm
scale limb Oswing,Lboxjoint,100,200,100 rem Shrink the horizontal joint by half
offset limb Oswing,Lboxjoint,0,-25,0 rem Position the horizontal joint at the end of the horizontal arm
texture limb Oswing,Lboxjoint,Iball
link limb Oswing,Lvertarm,Lboxjoint
add limb Oswing,Lhorzarm,Mswingarm rem Add the horizontal arm
scale limb Oswing,Lhorzarm,100,10,100 rem Shorten the horizontal arm to the correct length
rotate limb Oswing,Lhorzarm,90,0,0 rem Orient the horizontal arm
offset limb Oswing,Lhorzarm,0,0,-5 rem Position the horizontal arm at the horizontal joint
texture limb Oswing,Lhorzarm,Iboard
link limb Oswing,Lboxjoint,Lhorzarm
add limb Oswing,Lballholder,Mball rem Add an invisible limb to hold the marble
offset limb Oswing,Lballholder,0,-150,0 rem Position the invisible limb
link limb Oswing,Lhorzarm,Lballholder
hide limb Oswing,Lballholder
rem Make swingarm catcher box
make object box temp,12,1,12 rem Make a side of the box
make mesh from object temp,temp rem Create a mesh to be used for all sides of the box
delete object temp
make object Obox,temp,0 rem Start building the box with one side
add limb Obox,1,temp rem Add one side to the box
add limb Obox,2,temp rem Add one side to the box
add limb Obox,3,temp rem Add one side to the box
add limb Obox,4,temp rem Add one side to the box
offset limb Obox,0,0,-3,0 rem Position a side of the box
offset limb Obox,1,5.5,3,0 rem Position a side of the box
offset limb Obox,2,0,3,5.5 rem Position a side of the box
offset limb Obox,3,-5.5,3,0 rem Position a side of the box
offset limb Obox,4,0,3,-5.5 rem Position a side of the box
rotate limb Obox,1,0,0,90 rem Orient the side of the box
rotate limb Obox,2,90,0,0 rem Orient the side of the box
rotate limb Obox,3,0,0,90 rem Orient the side of the box
rotate limb Obox,4,90,0,0 rem Orient the side of the box
make mesh from object temp,Obox rem Create a mesh so that object can be created with no limbs
delete object Obox
make object Obox,temp,Iboard rem Create box from mesh so it has no limbs
offset limb Obox,0,0,5,0 rem Change its axis of rotation position
xrotate object Obox,270 rem Point to open end of the box up
glue object to limb Obox,Oswing,Lhorzarm,1 rem Attach box to the swing arm
rotate object Oswing,90,0,0 rem Orient the entire swing arm obect to sit on the swing pole
fix object pivot Oswing rem Define the current orientation of the swing arm as absolute
set object collision to polygons Obox
return
get_elevator:
rem Get the waypoints for the escalator animation
ramp1_x#=35.0
for i=1 to 20
read ramp1_y#(i),ramp1_z#(i),ramp1_a#(i)
ramp1_y#(i)=ramp1_y#(i)-20.0
next i
return
position_objects:
hide object Oramp(1) rem Original design had 4 ramps, bottom ramp was removed so marble would fall onto escalator
position object Oramp(1),10,0,0
position object Oramp(2),-10,20,0
position object Oramp(3),10,40,0
position object Oramp(4),-10,60,0
zrotate object Oramp(1),5
zrotate object Oramp(2),-5
zrotate object Oramp(3),5
zrotate object Oramp(4),-5
position object Oleg(1),15,28,-3
position object Oleg(2),15,28,8.5
position object Oleg(3),-41,32,-2
position object Oleg(4),-41,32,7.5
position object Obase,-15,-5,0
position object Oball, -35,69,ball_z_start#
rem Place escalator paddles along top and bottom of the escalator
for x=1 to 5
position object Opad(x),ramp1_x#,ramp1_y#(1)+(x-1)*15,ramp1_z#(1)+(x-1)*15
xrotate object Opad(x),ramp1_a#(1)
pad_pos(x)=1
next x
for x=6 to 10
position object Opad(x),ramp1_x#,ramp1_y#(11)-(x-6)*15,ramp1_z#(11)-(x-6)*15
xrotate object Opad(x),ramp1_a#(11)
pad_pos(x)=11
next x
position object Oramp1,ramp1_x#,25,35
position object Opost,10,10,20
position object Oswing,10,25,20
return
instructions:
rem Draw cursor key buttons and label with instructions for camera movement
x=0:y=40
create bitmap temp,256,256
ink 0,0
box 0,0,255,255
ink rgb(128,255,128),0
box x,y+1,x+12,y+15
box x+244,y+1,x+255,y+15
box x,y+23,x+12,y+37
box x+244,y+23,x+255,y+37
box x,y+43,x+41,y+57
box x+43,y+43,x+55,y+57
box x+200,y+43,x+241,y+57
box x+243,y+43,x+255,y+57
set cursor x+15,y+0
print "move left"
set cursor x+155,y+0
print "move right"
set cursor x+15,y+22
print "zoom in"
set cursor x+155,y+22
print "zoom out"
set cursor x+70,y+43
print "up"
set cursor x+153,y+43
print "down"
set cursor 50,0
print "CAMERA CONTROLS"
ink 0,0
line x+1,y+8,x+6,y+3:line x+2,y+8,x+7,y+3
line x+1,y+8,x+6,y+13:line x+2,y+8,x+7,y+13
line x+1,y+8,x+11,y+8
line x+254,y+8,x+249,y+3:line x+253,y+8,x+248,y+3
line x+254,y+8,x+249,y+13:line x+253,y+8,x+248,y+13
line x+254,y+8,x+244,y+8
line x+6,y+25,x+3,y+28:line x+6,y+26,x+3,y+29
line x+6,y+25,x+10,y+29:line x+6,y+26,x+10,y+30
line x+6,y+25,x+6,y+35
line x+250,y+35,x+247,y+32:line x+250,y+34,x+247,y+31
line x+250,y+35,x+254,y+31:line x+250,y+34,x+254,y+30
line x+250,y+25,x+250,y+35
line x+50,y+45,x+47,y+48:line x+50,y+46,x+47,y+49
line x+50,y+45,x+54,y+49:line x+50,y+46,x+54,y+50
line x+50,y+45,x+50,y+55
set cursor x,y+43
print "SHIFT"
line x+250,y+55,x+247,y+52:line x+250,y+54,x+247,y+51
line x+250,y+55,x+254,y+51:line x+250,y+54,x+254,y+50
line x+250,y+45,x+250,y+55
set cursor x+200,y+43
print "SHIFT"
rem Convert instructions bitmap into a sprite for display on the screen
get image Instructions,0,0,256,256
delete bitmap temp
sprite 1,0,0,Instructions
return
rem Waypoints for escalator movement
data 10,10,135,70,70,135,72,71,115,75,72,95,77.5,71.5,75,79,70.5,55,80.5,69,35,81.7,67,15,82,65,355,81.5,62.5,335,80,60,315,20,0,315,17.9,-1.4,295,15,-2,275,12.5,-1.5,255,10.8,-0.6,235,9.4,0.8,215,8.3,2.9,195,8,5,175,8.5,7.5,155
function move_camera()
if leftkey()
turn camera left 90.0
move camera 1.0
point camera 0,30,0
endif
if rightkey()
turn camera right 90.0
move camera 1.0
point camera 0,30,0
endif
if upkey()
if not shiftkey()
move camera 0.5
else
position camera camera position x(),camera position y()+1.0,camera position z()
point camera 0,30,0
endif
endif
if downkey()
if not shiftkey()
move camera -0.5
else
position camera camera position x(),camera position y()-1.0,camera position z()
point camera 0,30,0
endif
endif
endfunction
( 2b || !2b ), that is the question. The answer: true