Psychonauts 2 is a visual gem, one of those FEW games you play for a while on console aiming to relax, inspiring you to get back to the keyboard to recreate some effect from your code.


This is a little tribute to the broken hydrant fountain early in the game

uses "tbgl"


randomize timer


type FountainStream


  turn    as Single
  length  as Long
  offset  as Long
  phase   as single
  
  function Reinvent(maxPhase as single)
    me.turn   = rnd(0, 359)
    me.length = rnd(5, 30)
    me.offset = rnd(me.length * 0.5, me.length * 0.8)
    me.phase  = rndf(0,maxPhase)
  end function
  
  function Render()
    long i
    single curlTurn = 180/(me.length - me.offset)
    single cubeSize
    tbgl_pushMatrix
      tbgl_rotate me.turn, 0, 1, 0
      tbgl_translate 0, 0, 2
      
        for i = 1 to me.length * iif(me.phase*2 > 1, 1, me.phase*2)
          cubeSize = cos(i/(me.length*me.phase)*m_pi/2)


          tbgl_pushColor 64 * me.phase, 128 * me.phase, 255 * me.phase
            tbgl_box(cubeSize, cubeSize, cubeSize)
          tbgl_popColor
          tbgl_translate 0, 1.5+me.phase/10, 0
          
          if i > me.offset then tbgl_rotate curlTurn, 1, 0, 0
        next
     
    tbgl_popMatrix
  end function
  
end type




function tbMain()
  
  double frameRate
  
  dWord hWnd = tbgl_createWindowEx("Psychonauts 2 inspired fountain - press ESC to quit", 720, 720, 32, %TBGL_WS_WINDOWED)
  tbgl_showWindow


  ' -- Initialize lighting
  tbgl_useLighting(%TRUE)
  tbgl_useLightSource(%GL_LIGHT0, %TRUE)
  tbgl_setLightParameter(%GL_LIGHT0, %TBGL_LIGHT_POSITION, 15, 10, 15, 1)
  
  %NUM_FOUNTAINS = 16


  dim i as long
  dim f(%NUM_FOUNTAINS) as FountainStream
  for i = 1 to %NUM_FOUNTAINS
    f(i).Reinvent(0.5)
  next


  ' -- Main loop
  while tbgl_isWindow(hWnd) 
    frameRate = tbgl_getFrameRate


    tbgl_clearFrame 
      tbgl_camera(50, 50, 50, 0, 20, 0)
      
      tbgl_rotate timer*45, 0, 1, 0
      
      for i = 1 to %NUM_FOUNTAINS
        f(i).phase += 1/frameRate
        
        if f(i).phase > 0.999 then
          f(i).Reinvent(0.2)
        end if
        
        f(i).Render()
      next
      
    tbgl_drawFrame 


    ' -- ESCAPE key to exit application
    if tbgl_getWindowKeyState(hWnd, %VK_ESCAPE) then exit while


  wend


  tbgl_destroyWindow
end function
Petr