`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"