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