If you see nothing but text above this line, your browser probably doesn't support Java.
Click here to make full-sized.
The Game of Life is an example of a cellular automaton. This site is under heavy construction, as is the Applet itself. At the moment, it is possible to alter the resolution, to fill the grid with random data and to stop the game and single-step forwards. Planned for a new release are the ability to step backwards and to "paint" the grid with one's own patterns. There is also the possibility of adding a communications interface and allowing two people to run the Applet interactively across the Web. A friend of mine mentioned that some enterprising character had come up with a way to "play" Life competitively! More to come...
A Gallery (see below) of known patterns to drop in is gradually being added. At present, the Gallery button imports a small range of patterns, all of which so far have been recognised or developed by previous enthusiasts, for which credit mostly belongs to the sites listed below.
The drawing mechanism is partly complete, but is guaranteed to contain bugs in this release! If you press Stop, then press Clear, then draw a rectangle in the middle of the field by dragging the mouse, then press Start, you should see some pretty effects!
Have fun!
Click on the image to load it into the Applet at the top of the page. Go to the Applet and click Start to see the pattern in action.
The Gallery button uses a fragment of code which I adapted from another Life Applet written by Paul B. Callahan. This is an extraordinarily elegant idea which I wish I'd thought of myself - not having done so, I nicked it instead.
The code uses a Java class known as the PixelGrabber. The Applet loads the pattern in the form of a GIF image. The PixelGrabber class is then used to extract the pixel values from the image and pack it into an integer array. Once you have the image, you have the pattern, and the GIFs can even do double-duty as images in the HTML document. I am awestruck with admiration. Mr. Callahan's site is at The Java-Animated Life Archive .
import java.awt.image.PixelGrabber;
import java.awt.image.ImageObserver;
.
.
.
boolean getPixels(Image img, ImageObserver imgobs) {
int nWidth = img.getWidth(this);
int nHeight = img.getHeight(this);
// Wait until the dimensions actually become available
if (nWidth < 0 || nHeight < 0) {
return false;
}
// Space for the pixels to be grabbed into
int[] pixels = new int[nWidth * nHeight];
// da klever bit...
PixelGrabber pg = new PixelGrabber(img, 0, 0, nWidth, nHeight, pixels, 0, nWidth);
// Grab the pixels from the Image
try
{
pg.grabPixels();
}
catch (InterruptedException ex)
{
System.err.println("Interrupted while waiting for pixels!");
}
// Center the pattern - TODO: Resize if necessary
int nXOrg = (m_XCells - nWidth) / 2;
int nYOrg = (m_YCells - nHeight) / 2;
m_nStepCount = 0;
// Put the pattern into the middle of the field
for (int y = 0; y < nWidth; y++) {
for (int x = 0; x < nWidth; x++) {
// Look for black bits
if (-1 != pixels[y * nWidth + x]) {
// The pixels are stored in a semi-efficient sparse form.
// This approach can definitely be improved upon - more speed
// might be achieved by segregating the "islands" and skipping
// the calculations for ones which are static or repetitive.
int nPixel = (y + nYOrg) * m_XCells + nXOrg + x;
m_nSteps[m_nStepCount] = nPixel;
m_nPixels[m_nSteps[m_nStepCount++]] = 1;
}
}
}
return true;
}
void Gallery_actionPerformed(ActionEvent e) {
stop();
Reinitialise();
Clear();
// Load the gif file here
String sFile = "rpentomino.gif";
Image img = getImage(getCodeBase(), sFile);
// This rather odd-looking loop is necessary because the image's dimensions are
// not immediately available. Presumably, Java loads the body of the image asynchronously.
while (false == getPixels(img, this)) {
try {
Thread.sleep(200);
}
catch (InterruptedException ex)
{
}
}
// Paints the new pattern without redrawing panels and stuff.
Render(false);
}