TGC Codebase Backup



Fractals by The Wendigo

16th Nov 2004 20:28
Summary

Create fractals for your projects.



Description

Fractals are beautiful, mathmatical graphs that have captured our eyes for decades. You may have seen many fractals on screensavers and for wallpaper. You may have even played a game on one and didn't even know it! That's right, fractals are present more than you might think. Fractals can be used for random terrain generation, folliage and random decor, and even galaxies to name a few. I hope this code will benefit you and your projects as they are mine.

The fractal included for this demonstration is the Madnelbro set. You may easily change this to any fractal you wish, provided, you understand the math involved. I have tried hard to heavily comment this code and even explain some of the math to an extent. Enjoy!



Code
                                    ` This code was downloaded from The Game Creators
                                    ` It is reproduced here with full permission
                                    ` http://www.thegamecreators.com
                                    
                                    Rem Project: Mandelbrot
Rem Created: 11/16/2004 3:00:56 PM

Rem The Mandelbrot set is a very interresting fractal.  There are many different fractals
Rem available, but this is one is one of the most commonly seen.  You may have seen it
Rem in wallpapers, screensavers, and may have even seen parts of it (without even knowing)
Rem as terrain.
Rem This example will show you how the mandelbrot set can be created for your own DarkBasic
Rem projects which can be used for a variety of different purposes including terrain generation,
Rem galaxy making, or folliage plotting.

#Constant FRACT_WIDTH = 512.0
#Constant FRACT_HEIGHT = 512.0
#Constant FRACT_ITERATIONS = 256

set text opaque

Rem This is our main loop.  Each fractal call will show a fractal image
Rem at that given, X position, Y position, and Scale(inverse zoom) factor, respecitvely
do
   Fractal(0,0,4)
   wait 5000
   Fractal(-.371505859375, -.644072265625, .001)
   wait 5000
   Fractal(.18359375, .5859375, .001)
   wait 5000
   Fractal(.1843069296875,.586176051757813,.001)
   wait 5000
loop

Function Fractal(PosX as float, PosY as float, Scale as float)

   perc as float

   Rem Scaled position
   dx as float
   dy as float
   px as float
   py as float

   Rem Scaler (modified a tad)
   nScale as float
   nScale = Scale / 2

   Rem Scale the position (if you don't understand this, just ignore it for now)
   dx = ((PosX + nScale) - (PosX - nScale)) / FRACT_WIDTH
   dy = ((PosY + nScale) - (PosY - nScale)) / FRACT_HEIGHT

   Rem go through and plot some fractal pixels!
   for y = 0 to FRACT_HEIGHT - 1

      Rem System stuff (Ignore)
      perc = (y / FRACT_HEIGHT) * 100
      text 0, FRACT_HEIGHT, str$(int(perc)) + "%"
      sync
      if escapekey() then exitfunction

      Rem Now back to fractals
      for x = 0 to FRACT_WIDTH - 1
         Rem Scale the pixel appropriately (this is Source plotting)
         px = x
         py = y
         px = (PosX-nScale) + px * dx
         py = (PosY-nScale) + py * dy
         Rem Plot the pixel!
         Rem NOTE: Obviously, using the DOT command could be opitmized.  I'll leave that
         Rem to you
         Dot x, y, GetColor(MandelbrotPixel(px, py, FRACT_ITERATIONS))
      next x
   next y
EndFunction

Function MandelbrotPixel(x as float, y as float, Iterations as integer)

   Rem Plotting a pixel is a little more complex than just plotting any
   Rem old pixel anywhere.  A fractal is a graph of a Complex number, meaning
   Rem a number with a real part and an imaginary part (ie: A + Bi)

   Rem We will let A represent the real part of our number
   A as float
   Rem And B represent the imaginary part
   B as float
   Rem LastA is the last A position before we changed it
   LastA as float
   Rem Length is the distance from origin
   Length as float

   Rem Now step through a number of iterations and see if the numbers fly off into infinity
   i=0
   A=0
   B=0
   for i = 0 to Iterations-1

      Rem Now, The mandelbrot set is the function of NZ = Z*Z + C where NZ, Z and C are
      Rem complex numbers and C is a constant (meaning it wont change for this particular
      Rem iteration.

      Rem Z's parts will be A (real) and B (imaginary). and C is X (real) and Y (imaginary)
      Rem Therefore our equation will be:

      Rem (A + B)(A + B) + C
      Rem which turns into:  A*A + 2*A*B + B*B + X + Y
      Rem now, the square root of -1 is i, therefore and imaginary number (i) squared
      Rem would be -1 by definition.  That said, B*B is no longer imaginary. Therefore
      Rem B*B is now real and equal to -B*B.  This is important, because we now need to
      Rem seperate the real and imaginary parts and graph real on X and imaginary on Y

      Rem our formula seperated into real and imaginary parts (also, remember the last A!)
      LastA = A
      A = A*A - B*B + X
      B = 2*LastA*B + Y

      Rem now, in order for us to figure out what value our pixel will be, we need to
      Rem figure out its distance from the origin.  For a real number this is easy.  It
      Rem would be ABS(number), but for complex numbers, it's a little different:
      Length = A*A + B*B
      Rem NOTE: normally we would grab the sqrt() of length now, but this is not necissary
      Rem here and would slow down the overall process.

      Rem Now, if Length is less than 4, it is within the Mandelbrot set.  Otherwise, if
      Rem it passes 4, it will stretch out into infinity and will not lye within the set.
      if Length > 4 then exitfunction i
   next i

   Rem Bingo!  We should now have a value... what is that value?  Why, the number of iterations
   Rem ofcourse ;).  Simply return the value of i. (NOTE: My method is inverse of a normal Mandelbrot)
   Rem Also, you can change RESULT to eqaul iterations - 1 and you will get the maximum color value
   Rem to color in your mandelbrot set.  Heck, lets do that!
   `RESULT = i
   RESULT = iterations - 1
EndFunction RESULT

Function GetColor(Value as integer)
   Rem This wraps the value to within 0-255 (provided Value isn't negative!)

   Rem This will make a firey Mandelbrot (fire! woohoo!)
   if Value <= 85 and Value >= 0 then Color = rgb(Value * 3, 0, 0)
   if Value <= 85+85 and Value > 85 then Color = rgb(255, Value * 3, 0)
   if Value <= 85+85+85 and Value > 85+85 then Color = rgb(255, 255, Value * 3)
EndFunction Color