TGC Codebase Backup



Ye olde water algorithm by Tinkerer

10th May 2005 13:38
Summary

This is a simple demo of a well-known water algorithm.



Description

This is a simple demo of a well-known water algorithm. Mouse1 adjusts the interference level, and mouse2 adjusts the interference type. Further options can be set by adjusting variables.

After an accidental typo, this algorithm started behaving a little like the memory foam you get on some wrist pads. I've preserved the alternate matrix behaviour, and it can be toggled by pressing the space bar.

<update 1.1> camera motion smoothed out.



Code
                                    ` This code was downloaded from The Game Creators
                                    ` It is reproduced here with full permission
                                    ` http://www.thegamecreators.com
                                    
                                    REM Project: water
REM Created: 10/05/2005 03:09:33
REM
REM ***** Main Source File *****
REM

rem set sync up
sync on : sync rate 60
rem hide the mouse pointer
hide mouse

rem declare the two arrays that will be used to hold height information
dim imgbuffer1(1024, 1024) AS FLOAT
dim imgbuffer2(1024, 1024) AS FLOAT
rem make this as big as your system can handle!
gridsize = 128
rem this value determines how large the matrix will be rendered
gridmultiplier = 8
rem fill the arrays with zeros
for z = 0 to gridsize + 1
   for x = 0 to gridsize + 1
      imgbuffer1(x, z) = 0.0
      imgbuffer2(x, z) = 0.0
   next x
next z
rem determine where the middle of the matrix will be
middle = gridsize / 2

rem set this to a value BELOW ZERO. Or don't and enjoy the fireworks.
rem 0.90 to 0.999 are "sensible" values.
damping AS FLOAT
damping = 0.99
rem making this higher will slow the wave frequency of the mouse+sine effect.
wavefreq AS FLOAT
wavefreq = 1
rem adjusting these two variables will determine how much mouse button 1 affects
rem the interference generators.
lowheight = 10
highheight = 100
rem you can customize your own water behaviour using the above three variables together

rem the current pattern value is stored here
pattern AS INTEGER
pattern = 0
rem the current algorithm (water or mousepad foam)
mtype = 0
rem the next two variables are used together to stop the pattern changing in a loop when
rem mouse 2 is held down.
clik AS INTEGER
clik = 0
lastclik AS INTEGER
lastclik = 0
rem the next two variables are used together to stop the matrix behaviour changing in a
rem loop when the spacebar is held down.
lastspace = 0
space = 0
rem a temporary variable. Used later on.
tmp AS FLOAT

rem current mouse position and mouse+sine wave generator height go here.
mouseposx AS INTEGER
mouseposz AS INTEGER
waveheight AS INTEGER
waveheight = lowheight

rem load matrix texture here
MImg = 1 : load image "wtex.jpg", MImg
rem calulate matrix size and place in these two variables
matrixsize AS FLOAT
matrixsize = gridsize * gridmultiplier
matrixmiddle AS FLOAT
matrixmiddle = matrixsize / 2.0
rem declare and set the matrix here
MObj = 1 : make matrix MObj, matrixsize, matrixsize, gridsize, gridsize
MImg = 1 : load image "wtex.jpg", MImg
prepare matrix texture MObj, MImg, 1,1
rem set the initial position of the camera here
position camera 0,(sin(timer() / 100.0) * 100.0) + matrixsize,300.0,(cos(timer() / 110.0) * 100.0) + matrixsize
rem main loop
do

   rem get the new mouse position
   mouseposx = mouseposx + (mousemovex() / 5)
   mouseposz = mouseposz + -(mousemovey() / 5)
   rem limit the mouse position to valid array indices
   if mouseposx > gridsize then mouseposx = gridsize
   if mouseposz > gridsize then mouseposz = gridsize
   if mouseposx < 1 then mouseposx = 1
   if mouseposz < 1 then mouseposz = 1

   rem pan the camera around slowly
   position camera 0,matrixmiddle - (sin(timer() / 100.0) * 200.0),300.0,(cos(timer() / 110.0) * 100.0)
   point camera matrixmiddle,-300,matrixmiddle

   rem calculate current wave generator values
   sinfreq = timer() / wavefreq
   sincalc = 0.0 + sin(sinfreq) * waveheight
   coscalc = 0.0 + cos(sinfreq) * waveheight

   rem capture mouse values and change pattern and waveheight values accordingly
   lastclik = clik
   clik = mouseclick()
   if clik <> lastclik
      select clik
         case 0
            waveheight = lowheight
         endcase
         case 1
            waveheight = highheight
         endcase
         case 2
            waveheight = lowheight
            inc pattern
         endcase
         case 3
            waveheight = highheight
            inc pattern
         endcase
      endselect
   endif
   if pattern > 2 then pattern = 0
   select pattern
      case 0
         print "Interference type: mouse + sine"
         imgbuffer1(mouseposx, mouseposz) = imgbuffer1(mouseposx, mouseposz) + sincalc
      endcase
      case 1
         print "Inteference type: rain"
         randomize timer()
         tx = rnd(gridsize - 1) + 1
         ty = rnd(gridsize - 1) + 1
         imgbuffer1(tx, ty) = imgbuffer1(tx, ty) + sincalc
      endcase
      case 2
         print "Interference type: none"
      endcase
   endselect
   rem get the spacebar state.
   lastspace = space
   space = spacekey()
   rem ignore if state is same as last state.
   if space <> lastspace
      if space = 1
         inc mtype
         if mtype > 1 then mtype = 0
      endif
   endif
   select mtype
      case 0
         print "Matrix behaviour: water"
      endcase
      case 1
         print "Matrix behaviour: memory foam"
      endcase
   endselect
   rem this is the place where algorithms are applied. Remarks left out for speed.
   rem the first set of embedded loops are for water, the second for a low rebound
   rem foam-like behaviour. The third set of loops is used by both behaviours to
   rem swap the contents of the two buffers.
   select mtype
      case 0
         for z = 1 to gridsize
            for x = 1 to gridsize
               imgbuffer2(x, z) = (imgbuffer1(x - 1, z) + imgbuffer1(x + 1, z) + imgbuffer1(x, z + 1) + imgbuffer1(x, z - 1)) / 2 - imgbuffer2(x, z)
               imgbuffer2(x, z) = imgbuffer2(x, z) * damping
            next x
         next z
      endcase
      case 1
         for z = 1 to gridsize
            for x = 1 to gridsize
               imgbuffer2(x, z) = (imgbuffer1(x - 1, z) + imgbuffer1(x + 1, z) + imgbuffer1(x, z + 1) + imgbuffer1(x, z - 1)) / 2 - imgbuffer2(x, z)
               imgbuffer2(x, z) = imgbuffer1(x, z) * damping
            next x
         next z
      endcase
   endselect
   for z = 1 to gridsize
      for x = 1 to gridsize
         tmp = imgbuffer1(x, z)
         imgbuffer1(x, z) = imgbuffer2(x, z)
         imgbuffer2(x, z) = tmp
         set matrix height MObj, x, z, imgbuffer2(x, z)
      next x
   next z
   rem done with water algorithm. Update matrix with new values.
   update matrix MObj
   rem print out a status display.
   set cursor 0,1 : print "mpx: "; mouseposx; " mpz: "; mouseposz; " fps: "; screen fps()
   rem flip the buffers.
   sync
   rem end of main loop
loop

end