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