Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Fractals entertain and are fun to explore, as evidenced by this article's fractal applets. Learn how to use math-based fractals that imitate nature's geometry to enhance your Java games.
Euclidean geometry emphasizes circles, cubes and other simple shapes. This geometry is seen in buildings and other man-made objects. In contrast, the geometry of nature is more complex, but it does exhibit the property of self-similarity: Natural objects (such as clouds and coastlines) look similar at different levels. This self-similarity is also evidenced in mathematics, especially when working with complex numbers.
In 1975, IBM researcher Benoît Mandelbrot invented the term fractal, "a rough or fragmented geometric shape that can be subdivided in parts, each of which is (at least approximately) a reduced-size copy of the whole," to describe natural and math-based self-similarity. Mandelbrot also discovered what is regarded to be the most famous math-based fractal, the Mandelbrot set.
This article takes you on a tour of math-based fractals, including the Mandelbrot set. You will examine algorithms for recursively generating fractals and play with applets that implement the algorithms. One of the fractals demonstrated imitates nature's geometry by generating a mountain ridgeline. Perhaps you will use this fractal to create background terrain for one of your Java games.
I have created an infrastructure for generating and animating most of the fractals presented in this article. Before touring
the fractals and their applets, you should have a basic understanding of the infrastructure. Let's begin with the fractal
generator, which I've chosen to describe via the FractalGenerator interface in Listing 1.
Listing 1. The FractalGenerator interface
interface FractalGenerator
{
public void generate (Graphics2D g, int depth, int width, int height);
public int maxDepth ();
}
The methods of the FractalGenerator interface assume that a fractal is recursively generated: they are invoked by a fractal animator when it is time to generate
the fractal at a new depth. The depth ranges from 0 to a maximum positive integer (0 ends the recursion). At this point, a
java.awt.Graphics2D object's methods render the fractal in a rectangular area bounded by the upper-left-corner (0, 0) and dimensions width and height.
After creating an object from a class that implements FractalGenerator, a program connects this object to the fractal animator, which generates the fractal to a specific depth for each frame of
the fractal's animation. As you see in Listing 2, I have chosen to describe the fractal animator via FractalAnimator, a subclass of the javax.swing.JPanel container class:
Listing 2. FractalAnimator, a subclass of javax.swing.JPanel
class FractalAnimator extends JPanel {
final static int DEFAULT_DELAY = 500;
final static int MAX_DELAY = 1000;
final static int MIN_DELAY = 100;
final static int STEP = 100;
private final static Color PANEL_COLOR = new Color (255, 255, 225);
private FractalGenerator fg;
private volatile int depth, ms = DEFAULT_DELAY;
private volatile Thread animThd;
FractalAnimator (FractalGenerator fg)
{
this.fg = fg;
}
public void paintComponent (Graphics g)
{
Graphics2D g2d = (Graphics2D) g.create ();
Insets insets = getInsets ();
g2d.translate (insets.left, insets.top);
int width = getWidth ()-insets.left-insets.right;
int height = getHeight ()-insets.top-insets.bottom;
g2d.setColor (PANEL_COLOR);
g2d.fillRect (0, 0, width, height);
g2d.setColor (Color.black);
fg.generate (g2d, depth, width, height);
g2d.dispose ();
}
void setDelay (int ms)
{
if (ms < MIN_DELAY)
throw new IllegalArgumentException (ms+" < MIN_DELAY");
if (ms > MAX_DELAY)
throw new IllegalArgumentException (ms+" > MAX_DELAY");
this.ms = ms;
}
void start ()
{
animThd = new Thread (new Runnable ()
{
public void run ()
{
depth = -1;
Thread currThd = Thread.currentThread ();
while (currThd == animThd)
{
if (++depth > fg.maxDepth ())
depth = 0;
repaint ();
try
{
Thread.sleep (ms);
}
catch (InterruptedException e)
{
}
}
}
});
animThd.start ();
}
void stop ()
{
animThd = null;
}
}
The FractalAnimator class presents a simple API that includes a constructor and three additional methods. First, the constructor saves its fractal-generator
argument. The void setDelay(int ms) method then specifies a milliseconds delay that inversely determines the animation frame rate (higher delay, slower rate).
Finally, the void start() and void stop() methods initiate and terminate the animation.
Archived Discussions (Read only)