remstart
   ==============================================================
   =  Title  : Reflective Cube Screen Saver
   =  Author : Latch
   =  Date   : 04/27/2007
   =  Update : 04/28/2007
   =  Version: .01
   ==============================================================
   Comments    Improved my mirror code with an idea
               presented by Rigo - Thanks Rigo!
   ==============================================================
remend
 
rem =============================================================
rem = SET UP DISPLAY
rem =============================================================
   autocam off
   set display mode 640,480,16
   sync on
   sync rate 0
   hide mouse
 
rem =============================================================
rem = MAIN
rem =============================================================
_main:
   gosub _init
 
   repeat
      gosub _face_cube
      gosub _reflect
 
      cls
      text 0,0,str$(screen fps())
      `text 0,20,str$(angy1#)
      `text 0,40,str$(cangy#)
      `text 0,60,str$(abs(angy1#-cangy#))
      sync
   until break_silence()=1
   delete sprite 1
   delete sprite 2
   delete sprite 101
   delete matrix 1
   delete image 1
   delete image 2
   delete image 3
   delete image 100
   delete image 101
   for obj=1 to 13
      delete object obj
   next obj
   set camera view 0,0,screen width(),screen height()
   backdrop off
   cls 0
   sync
 
   end
 
   _init:
      x1=100
      y1=50
      x2=440
      y2=330
      xdir=1
      sx=-1
      ydir=1
      sy=-1
      randomize timer()
      gosub _texture
      gosub _floor
      gosub _reflective_cube
      gosub _objects
      set camera view x1,y1,x2,y2
      position camera 500,0,500
   return
   _floor:
      make matrix 1,1000,1000,10,10
      position matrix 1,0,-30,0
      prepare matrix texture 1,100,1,1
      `randomize matrix 1,20
   return
   _texture:
      rem checkerboard
      create bitmap 1,65,65
      cls RGB(128,128,128)
      ink 0,0
      box 0,0,32,32
      box 33,33,64,64
      get image 100,0,0,65,65
      ink rgb(0,255,0),0
      delete bitmap 1
 
      create bitmap 1,screen width(),screen height()
      cls 0
      get image 101,x1,y1,x2+1,y2+1
      delete bitmap 1
 
      set current bitmap 0
      sprite 101,x1,y1,101
      set sprite 101,0,0
      sprite 1,-900,-900,100
      sprite 2,-900,-900,100
      set sprite 1,0,0
      set sprite 2,0,0
      mirror sprite 1
   return
   _reflective_cube:
      make object plain 1,80,80
      make object plain 2,80,80
      yrotate object 2,90
      position object 1,500,40,660
      position object 2,460,40,700
   return
   _objects:
      rem objects to reflect
         rem left side
         objects(3,4,150,0,1000,0)
         rem right side
         objects(5,7,200,800,1000,0)
         rem bottom
         objects(8,10,1000,0,150,0)
         rem top
         objects(11,13,1000,0,100,900)
   return
   _rotate_camera:
      yang#=wrapvalue(yang#+.5)
      camx#=camera position x()
      camz#=camera position z()
      centerx#=500
      centerz#=700
      dist#=sqrt((centerx#-camx#)^2+(centerz#-camz#)^2)
      newcamx#=dist#*cos(yang#+90)+centerx#
      newcamz#=-1*dist#*sin(yang#+90)+centerz#
      position camera newcamx#,camera position y(),newcamz#
      point camera centerx#,0,centerz#
      sync
   return
   _face_cube:
      yrotate camera camy#
      gosub _rotate_camera
      if sx+x2 >= screen width() then xdir=-1
      if sx+x1 <=0 then xdir=1
      sx=sx+1*xdir
      if sy+y2 >= screen height() then ydir=-1
      if sy+y1 <= 0 then ydir=1
      sy=sy+1*ydir
      get image 1,x1,y1,x2,y2
      sprite 2,x1+sx,y1+sy,1
      sprite 1,x1+sx*-1,y1+sy*-1,1
      sync
   return
   _reflect:
      cangy#=camera angle y()
      camx#=camera position x()
      camy#=camera position y()
      camz#=camera position z()
      angy1#=object angle y(1)
      angy2#=object angle y(2)
      if abs(angy1#-cangy#)>90 and abs(angy1#-cangy#)< 180
         move object 1,80
         yrotate object 1,(angy1#+180)
      endif
      if abs(angy2#-wrapvalue(cangy#))>90
         move object 2,80
         yrotate object 2,wrapvalue(angy2#+180)
      endif
      position camera object position x(1),object position y(1),object position z(1)
      cangy2#=360-cangy#
      yrotate camera wrapvalue(cangy2#+180)
      get image 2,x1,y1,x2,y2
      texture object 1,2
      sync
      position camera object position x(2),object position y(2),object position z(2)
      yrotate camera wrapvalue(cangy2#)
      get image 3,x1,y1,x2,y2
      texture object 2,3
      position camera camx#,camy#,camz#
   return
   function objects(obstart,obend,x,xlimit,z,zlimit)
      for obj=obstart to obend
         choice=rnd(3)+1
         select choice
            case 1
               make object cube obj,rnd(100)+25
               position object obj,rnd(x)+xlimit,31,rnd(z)+zlimit
               color object obj,rgb(rnd(255),rnd(255),rnd(255))
            endcase
            case 2
               make object sphere obj,rnd(100)+25
               position object obj,rnd(x)+xlimit,31,rnd(z)+zlimit
               color object obj,rgb(rnd(255),rnd(255),rnd(255))
            endcase
            case 3
               make object cylinder obj,rnd(100)+25
               position object obj,rnd(x)+xlimit,31,rnd(z)+zlimit
               color object obj,rgb(rnd(255),rnd(255),rnd(255))
            endcase
            case 4
               make object cone obj,rnd(100)+25
               position object obj,rnd(x)+xlimit,31,rnd(z)+zlimit
               color object obj,rgb(rnd(255),rnd(255),rnd(255))
            endcase
         endselect
      next obj
   endfunction
   function break_silence()
      result=0
      if mousemovex() <> 0 or mousemovey() <> 0 or mousemovez() <>0 then result=1
      if scancode()<>0 then result=1
   endfunction result