Here's my entry. The idea is to get the marble onto the purple platform. Follow the green path - the start is at the front left of the table.
Arrow keys to tilt the table, space key to nudge the marble just incase it gets stuck.
Oh - by the way, it's hard, but possible, I promise!
`Global rotation functions by Lower Logic
gosub display
`udt's
type balltype
x as float
y as float
z as float
vx as float
vy as float
vz as float
omega as float `angular velocity
endtype
myball as balltype
type boardtype
omega as float `angular velocity
endtype
board as boardtype
gosub make_ball
gosub make_background
gosub make_textures
gosub make_board
gosub set_ball_properties
gosub set_ground_properties
gosub make_vectors
gosub make_spirit_levels
do
gosub control_board
gosub collision
gosub move_ball
gosub move_camera
gosub apply_friction
gosub update_spirit_levels
gosub nudge
gosub replace
sync
loop
nudge:
if spacekey()=1 then position object ball,object position x(ball)+5,object position y(ball),object position z(ball)
return
replace:
if object position y(ball)<-100
position object ball,0,20,0.1
myball.vx=0
myball.vy=0
myball.vz=0
endif
return
make_spirit_levels:
pitchback=free_image()
create bitmap 1,100,100
word$="PITCH"
ink rgb(180,180,255),0
text 50-text width(word$)/2.0,0,word$
box 0,50,100,100
get image pitchback,0,0,100,100,1
delete bitmap 1
sprite pitchback,100,668,pitchback
set sprite alpha pitchback,130
pitch=free_image()
create bitmap 1,100,100
ink -1,0
box 0,49,100,51
get image pitch,0,0,100,100,1
delete bitmap 1
sprite pitch,150,718,pitch
offset sprite pitch,50,50
rollback=free_image()
create bitmap 1,100,100
word$="ROLL"
ink rgb(180,180,255),0
text 50-text width(word$)/2.0,0,word$
box 0,50,100,100
get image rollback,0,0,100,100,1
delete bitmap 1
sprite rollback,824,668,rollback
set sprite alpha rollback,130
roll=free_image()
create bitmap 1,100,100
ink -1,0
box 0,49,100,51
get image roll,0,0,100,100,1
delete bitmap 1
sprite roll,874,718,roll
offset sprite roll,50,50
return
update_spirit_levels:
rotate sprite pitch,-anglex#
rotate sprite roll,anglez#
return
apply_friction:
dec myball.vx,myball.vx*friction#
dec myball.vz,myball.vz*friction#
return
move_camera:
position object cameradummy,object position x(ball),object position y(ball),object position z(ball)
rotate object cameradummy,0,0,0
rotate_gx(cameradummy,anglex#)
move object cameradummy,-100
move object up cameradummy,100
point object cameradummy,object position x(ball),object position y(ball),object position z(ball)
roll object left cameradummy,anglez#
position camera object position x(cameradummy),object position y(cameradummy),object position z(cameradummy)
set camera to object orientation cameradummy
set object to camera orientation cube
pitch object up cube,45
return
make_background:
background=free_image()
create bitmap 1,500,500
ink rgb(0,255,0),0
for n=0 to 499 step 10
line n,0,n,500
line 0,n,500,n
next n
get image background,0,0,500,500,1
delete bitmap 1
cube=free_object()
make object cube cube,-500
texture object cube,background
return
make_vectors:
vleft=1
vright=2
vahead=3
vbehind=4
vabove=5
vbelow=6
null=make vector3(vleft)
null=make vector3(vright)
null=make vector3(vahead)
null=make vector3(vbehind)
null=make vector3(vabove)
null=make vector3(vbelow)
set vector3 vleft,-10,0,0
set vector3 vright,10,0,0
set vector3 vahead,0,0,10
set vector3 vbehind,0,0,-10
set vector3 vabove,0,10,0
set vector3 vbelow,0,-10,0
return
collision:
`repeat for each vector 1 to 6
for n=1 to 6
`store xyz coordinates around ball
x#=object position x(ball)+x vector3(n)
y#=object position y(ball)+y vector3(n)
z#=object position z(ball)+z vector3(n)
dist#=intersect object(ground,object position x(ball),object position y(ball),object position z(ball),x#,y#,z#)
if dist#=0 then dist#=1000
if dist#<=2.5
`if collision in a certain direction is detected, then reverse the velocity in that direction, and multiply by dampening amount
overlap#=2.5-dist#
if n=1
myball.vx=-myball.vx*damp#
position object ball,object position x(ball)+overlap#,object position y(ball),object position z(ball)
endif
if n=2
myball.vx=-myball.vx*damp#
position object ball,object position x(ball)-overlap#,object position y(ball),object position z(ball)
endif
if n=3
myball.vz=-myball.vz*damp#
position object ball,object position x(ball),object position y(ball),object position z(ball)-overlap#
endif
if n=4
myball.vz=-myball.vz*damp#
position object ball,object position x(ball),object position y(ball),object position z(ball)+overlap#
endif
if n=5
myball.vy=-myball.vy*damp#
position object ball,object position x(ball),object position y(ball)-overlap#,object position z(ball)
endif
if n=6
myball.vy=-myball.vy*damp#
position object ball,object position x(ball),object position y(ball)+overlap#,object position z(ball)
endif
endif
next n
return
move_ball:
dec myball.vy,gravity#
inc myball.vx,sin(anglez#)/mass#
inc myball.vz,sin(-anglex#)/mass#
if myball.vx>2.5 then myball.vx=2.5
if myball.vx<-2.5 then myball.vx=-2.5
if myball.vz>2.5 then myball.vz=2.5
if myball.vz<-2.5 then myball.vz=-2.5
if abs(myball.vx)<0.005 then myball.vx=0
if abs(myball.vz)<0.005 then myball.vz=0
position object ball,object position x(ball)+myball.vx,object position y(ball)+myball.vy,object position z(ball)+myball.vz
rotate_gz(ball,(-17*myball.vx))
rotate_gx(ball,(17*myball.vz))
`set light to follow ball
position light 1,object position x(ball),object position y(ball)+40,object position z(ball)
`update ball reflection
position object ball2,object position x(ball),-object position y(ball)+1,object position z(ball)
rotate_gz(ball2,(17*myball.vx))
rotate_gx(ball2,(-17*myball.vz))
return
control_board:
if leftkey()=1 and anglez#>-25 then dec anglez#,board.omega
if rightkey()=1 and anglez#<25 then inc anglez#,board.omega
if upkey()=1 and anglex#>-25 then dec anglex#,board.omega
if downkey()=1 and anglex#<25 then inc anglex#,board.omega
return
set_ball_properties:
gravity#=0.05
damp#=0.4
mass#=6.0
friction#=0.004
return
set_ground_properties:
board.omega=0.4
return
make_textures:
blue=free_image()
create bitmap 1,10,10
ink rgb(180,180,255),0
box 0,0,10,10
get image blue,0,0,10,10
delete bitmap 1
red=free_image()
create bitmap 1,10,10
ink rgb(255,0,0),0
box 0,0,10,10
get image red,0,0,10,10
delete bitmap 1
green=free_image()
create bitmap 1,10,10
ink rgb(0,255,0),0
box 0,0,10,10
get image green,0,0,10,10
delete bitmap 1
magenta=free_image()
create bitmap 1,10,10
ink rgb(255,0,255),0
box 0,0,10,10
get image magenta,0,0,10,10
delete bitmap 1
return
make_board:
`dummy
cameradummy=free_object()
make object cube cameradummy,1
hide object cameradummy
`ground
ground=free_object()
make object box ground,200,2,200
texture object ground,blue
set object transparency ground,5
set alpha mapping on ground,50
`all other board objects attached as limbs for simplicity with collision
`back
temp=free_object()
make object box temp,200,10,5
make mesh from object 1,temp
delete object temp
add limb ground,1,1
delete mesh 1
offset limb ground,1,0,0,100
texture limb ground,1,red
`front
temp=free_object()
make object box temp,200,10,5
make mesh from object 1,temp
delete object temp
add limb ground,2,1
delete mesh 1
offset limb ground,2,0,0,-100
texture limb ground,2,red
`left
temp=free_object()
make object box temp,5,10,200
make mesh from object 1,temp
delete object temp
add limb ground,3,1
delete mesh 1
offset limb ground,3,-100,0,0
texture limb ground,3,red
`right
temp=free_object()
make object box temp,5,10,200
make mesh from object 1,temp
delete object temp
add limb ground,4,1
delete mesh 1
offset limb ground,4,100,0,0
texture limb ground,4,red
limb=4
for z=1 to 20
for x=1 to 20
read data$
if data$<>"000"
inc limb
temp=free_object()
if data$="0xr"
make object box temp,10,4,10
data$="02r"
else
make object box temp,10,2,10
endif
make mesh from object 1,temp
delete object temp
add limb ground,limb,1
delete mesh 1
offset limb ground,limb,-105+x*10,val(left$(data$,2))*2-1,105-z*10
if mid$(data$,3)="r" then texture limb ground,limb,red
if mid$(data$,3)="g" then texture limb ground,limb,green
if mid$(data$,3)="b" then texture limb ground,limb,blue
if mid$(data$,3)="m" then texture limb ground,limb,magenta
`reflection
temp=free_object()
make object box temp,10,2,10
position object temp,-105+x*10,-val(left$(data$,2))*2-1,105-z*10
if mid$(data$,3)="r" then texture object temp,red
if mid$(data$,3)="g" then texture object temp,green
if mid$(data$,3)="b" then texture object temp,blue
if mid$(data$,3)="m" then texture object temp,magenta
set object transparency temp,1
set alpha mapping on temp,20
endif
next x
next z
return
make_ball:
`make ball
create bitmap 1,256,256
ink -1,0
box 0,0,128,128
box 128,128,256,256
ballimage=free_image()
get image ballimage,0,0,256,256,1
delete bitmap 1
ball=free_object()
make object sphere ball,5,20,20
texture object ball,ballimage
scale object texture ball,2,2
position object ball,0,20,0.1
`ball reflection
ball2=free_object()
make object sphere ball2,5,20,20
texture object ball2,ballimage
scale object texture ball2,2,2
set object transparency ball2,5
set alpha mapping on ball2,20
return
display:
set display mode 1024,768,32
hide mouse
sync on
sync rate 60
autocam off
color backdrop 0
position camera 0,20,-100
make light 1
set light range 1,200
hide light 0
set ambient light 50
return
function free_object()
repeat
inc n
until object exist(n)=0
endfunction n
function free_image()
repeat
inc n
until image exist(n)=0
endfunction n
remstart Rotate_GX
This function rotates the given object around the global (world) x axis by
the given amount.
Param obj The object to rotate
Param amount# The angle to rotate the object by
remend
function rotate_GX(obj as integer,amount# as float)
rem get normal vectors for X, Y, and Z axes of the object
x#=object position x(obj):y#=object position y(obj):z#=object position z(obj)
move object right obj,1
xx#=object position x(obj)-x#:xy#=object position y(obj)-y#:xz#=object position z(obj)-z#
move object left obj,1:move object up obj,1
yx#=object position x(obj)-x#:yy#=object position y(obj)-y#:yz#=object position z(obj)-z#
move object down obj,1:move object obj,1
zx#=object position x(obj)-x#:zy#=object position y(obj)-y#:zz#=object position z(obj)-z#
move object obj,-1
rem rotate the vectors
xx1#=xx#
xy1#=xy#*cos(amount#)-xz#*sin(amount#)
xz1#=xz#*cos(amount#)+xy#*sin(amount#)
zx1#=zx#
zy1#=zy#*cos(amount#)-zz#*sin(amount#)
zz1#=zz#*cos(amount#)+zy#*sin(amount#)
rem calculate angle z
zr#=atanfull(xy1#,xx1#)
rem calculate angle y
xx2#=xx1#*cos(zr#)+xy1#*sin(zr#)
xy2#=xy1#*cos(zr#)-xx1#*sin(zr#)
xz2#=xz1#
zx2#=zx1#*cos(zr#)+zy1#*sin(zr#)
zy2#=zy1#*cos(zr#)-zx1#*sin(zr#)
zz2#=zz1#
yr#=atanfull(xx2#,xz2#)-90
rem calculate angle x
zx3#=zx2#*cos(yr#+90)-zz2#*sin(yr#+90)
zy3#=zy2#
xr#=atanfull(zy3#,zx3#)+180
if xr#+1>xr# and yr#+1>yr# and zr#+1>zr#
rotate object obj,xr#,yr#,zr#
endif
endfunction
remstart Rotate_GY
This function rotates the given object around the global (world) y axis by
the given amount.
Param obj The object to rotate
Param amount# The angle to rotate the object by
remend
function rotate_GY(obj,amount#)
rem get normal vectors for X, Y, and Z axes of the object
x#=object position x(obj):y#=object position y(obj):z#=object position z(obj)
move object right obj,1
xx#=object position x(obj)-x#:xy#=object position y(obj)-y#:xz#=object position z(obj)-z#
move object left obj,1:move object up obj,1
yx#=object position x(obj)-x#:yy#=object position y(obj)-y#:yz#=object position z(obj)-z#
move object down obj,1:move object obj,1
zx#=object position x(obj)-x#:zy#=object position y(obj)-y#:zz#=object position z(obj)-z#
move object obj,-1
rem rotate the vectors
xx1#=xx#*cos(amount#)+xz#*sin(amount#)
xy1#=xy#
xz1#=xz#*cos(amount#)-xx#*sin(amount#)
zx1#=zx#*cos(amount#)+zz#*sin(amount#)
zy1#=zy#
zz1#=zz#*cos(amount#)-zx#*sin(amount#)
rem calculate angle z
zr#=atanfull(xy1#,xx1#)
rem calculate angle y
xx2#=xx1#*cos(zr#)+xy1#*sin(zr#)
xy2#=xy1#*cos(zr#)-xx1#*sin(zr#)
xz2#=xz1#
zx2#=zx1#*cos(zr#)+zy1#*sin(zr#)
zy2#=zy1#*cos(zr#)-zx1#*sin(zr#)
zz2#=zz1#
yr#=atanfull(xx2#,xz2#)-90
rem calculate angle x
zx3#=zx2#*cos(yr#+90)-zz2#*sin(yr#+90)
zy3#=zy2#
xr#=atanfull(zy3#,zx3#)+180
if xr#+1>xr# and yr#+1>yr# and zr#+1>zr#
rotate object obj,xr#,yr#,zr#
endif
endfunction
remstart Rotate_GZ
This function rotates the given object around the global (world) z axis by
the given amount.
Param obj The object to rotate
Param amount# The angle to rotate the object by
remend
function rotate_GZ(obj,amount#)
rem Rotating around the global Z axis is trivial
rem as it is the first rotation anyway in the default ZYX rotation order
rotate object obj,object angle x(obj),object angle y(obj),object angle z(obj)+amount#
endfunction
data "000","11g","12g","13g","14g","15g","16g","17g","18g","19g","000","11g","12g","13g","14g","15g","16g","17g","000","000"
data "000","11g","000","000","000","000","000","000","000","20g","000","10g","000","000","000","000","000","18g","19g","20g"
data "000","11g","000","02g","02g","02g","02g","000","000","21g","000","09g","000","000","000","000","000","000","000","21g"
data "000","11g","000","02g","02g","02g","02g","000","000","22g","000","08g","000","000","000","000","000","000","000","22g"
data "000","11g","000","02g","02g","02g","02g","000","000","23g","000","07g","06g","05g","04g","000","000","000","000","23g"
data "000","11g","000","03g","000","02g","02g","000","000","24g","000","000","000","000","03g","000","000","000","000","24g"
data "000","11g","000","04g","000","02g","02g","000","000","25g","000","000","000","000","02g","000","000","000","000","25g"
data "000","11g","000","05g","000","02g","02g","000","000","000","000","000","000","02r","01g","02r","000","000","000","26g"
data "000","11g","000","06g","000","02r","01g","02r","000","20r","20r","02r","02r","02r","000","02r","000","000","000","27g"
data "000","11g","000","07g","000","02r","000","02r","20r","18g","08g","08g","02g","000","000","02r","000","000","000","28g"
data "000","11g","000","08g","000","02r","000","02r","20r","18g","08g","08g","02g","000","000","02r","000","000","000","29g"
data "000","11g","000","09g","000","02r","000","02r","000","20r","20r","02r","02r","02r","02r","02r","000","000","000","30g"
data "000","11g","000","10g","000","02r","000","02r","000","000","000","000","000","000","000","000","000","000","000","31g"
data "13r","11g","11g","11g","13r","02r","000","02r","000","06r","06r","000","000","000","000","000","000","000","000","000"
data "13r","13r","000","13r","13r","04r","02g","02g","03g","04g","04g","000","000","000","000","000","000","000","000","000"
data "000","000","000","000","000","04r","03r","000","000","04g","04g","000","04b","04b","04b","000","000","000","000","10g"
data "02r","02r","02r","02r","02r","0xr","04r","05r","06r","04g","04g","000","04b","02m","04b","000","10g","10g","10g","10g"
data "000","000","000","000","000","01g","02g","03g","04g","04g","04g","000","04b","04b","04b","000","000","000","000","10g"
data "000","000","02r","02r","02r","02r","000","000","000","000","000","000","000","000","000","000","000","000","000","10g"
data "000","000","000","000","000","000","000","000","000","000","000","000","000","000","000","000","000","000","000","10g"
