Anonymous avatar Anonymous committed 2639a27

TileGame is now Conway's Life

Comments (0)

Files changed (1)

src/main/java/sandbox/misc/TileGame.java

 import org.lwjgl.opengl.DisplayMode;
 import sandbox.common.BaseApp;
 import sandbox.common.TileSet;
+import scala.swing.Table;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
 
     TileSet tileset;
 
-    int width  = 50; // tiles wide to draw
+    int width = 50; // tiles wide to draw
     int height = 36; // tiles high to draw
 
+    boolean[][][] cells;
+
+    int currentLayer = 0;
+
     ByteBuffer meshBuf = BufferUtils.createByteBuffer(Float.SIZE * width * height * 8);
-    ByteBuffer texBuf  = BufferUtils.createByteBuffer(Float.SIZE * width * height * 8);
+    ByteBuffer texBuf = BufferUtils.createByteBuffer(Float.SIZE * width * height * 8);
 
     FloatBuffer mesh = meshBuf.asFloatBuffer();
     FloatBuffer texc = texBuf.asFloatBuffer();
     }
 
     public static void main(String[] args) {
-        TileGame s = new TileGame("Tiles!");
+        TileGame s = new TileGame("Conway's Life");
         s.setPerspectiveProjection(false);
         s.setOrthoScale(MATCH_VIEWPORT);
         s.setTargetFrameRate(60);
         s.doMain(args);
-
     }
 
     protected void createDisplay() throws LWJGLException {
             throw new RuntimeException(e);
         }
         buildMesh(tw, th);
-        populateTiles(0);
+        populateCells();
+    }
+
+    private void populateCells() {
+        cells = new boolean[2][width][height];
+        for (int y = 0; y < height; y++)
+            for (int x = 0; x < width; x++) {
+                cells[0][x][y] = rand.nextBoolean();
+            }
+    }
+
+    private boolean getCell(boolean[][] arr, int x, int y) {
+        while (x < 0) x += width;
+        while (x >= width) x -= width;
+
+        while (y < 0) y += height;
+        while (y >= height) y -= height;
+        return arr[x][y];
+    }
+
+    private int neighborhood(boolean[][] arr, int x, int y) {
+        int count = 0;
+        for (int yy = y - 1; yy <= y + 1; yy++)
+            for (int xx = x - 1; xx <= x + 1; xx++)
+                if (getCell(arr, xx, yy)) count++;
+
+        // don't count the current cell
+        if (getCell(arr, x, y)) count -= 1;
+        return count;
+    }
+
+
+    private boolean conwayRule(boolean cell, int neighbors) {
+        // Conway's life is classically described with these rules:
+        // * If a cell has less than 2 neighbors, it dies of loneliness
+        // * If a cell has four or more neighbors, it dies of overcrowding
+        // * If a cell has 2 or 3 neighbors, it continues to live
+        // * If an empty cell has three neighbors, a new cell is born
+        //
+        // Functionally it's easier to describe with just three rules:
+        // * Any cell (alive or dead) with exactly three neighbors is live
+        // * An existing live cell with two neighbors is live
+        // * All other cells/spaces are dead
+
+        // Ultimately it simplifies into a single expression:
+        return neighbors == 3 || cell && (neighbors == 2);
+    }
+
+    private boolean rule(boolean cell, int neighbors) {
+        return conwayRule(cell, neighbors);
+    }
+
+    private void generation() {
+        int src = currentLayer;
+        int dest = (src == 0) ? 1 : 0;
+
+        for (int y = 0; y < height; y++) {
+            for (int x = 0; x < width; x++) {
+                cells[dest][x][y] = rule(cells[src][x][y], neighborhood(cells[src], x, y));
+            }
+        }
+
+        for (int y = 0; y < height; y++) {
+            for (int x = 0; x < width; x++) {
+                cells[src][x][y] = false;
+            }
+        }
+
+        currentLayer = dest;
     }
 
     private void buildMesh(int tw, int th) {
     public void putTile(int x, int y, int tx, int ty) {
 //        System.out.printf("putTile(%d, %d, %d, %d)%n", x, y, tx, ty);
         texc.position((x + y * width) * 8);
-        float[] c = tileset.getTileCoords(tx,ty);
+        float[] c = tileset.getTileCoords(tx, ty);
         texc.put(c[0]);
         texc.put(c[1]);
 
         texc.put(c[3]);
     }
 
-    private void populateTiles(int offset) {
+    private void drawTiles(int layer) {
+        // gem tile
+        int tx = 4;
+        int ty = 15;
         for (int y = 0; y < height; y++)
             for (int x = 0; x < width; x++) {
-                int tx = (x + offset) % 16;
-                int ty = (y + offset) % 16;
-                putTile(x, y, tx, ty);
+                if (cells[layer][x][y])
+                    putTile(x, y, tx, ty);
+                else
+                    putTile(x, y, 0, 15);
             }
     }
 
-    int framecount = 0;
-    int offset = 0;
     @Override
     protected void render() {
-        framecount++;
-        if (framecount % 6 == 0) offset++;
-        populateTiles(offset);
+        generation();
+        drawTiles(currentLayer);
         tileset.getTexture().bind();
         glPushMatrix();
         glClear(GL_COLOR_BUFFER_BIT);
         glBegin(GL_QUADS);
         mesh.rewind();
         texc.rewind();
-        glColor3f(1,1,1);
+        glColor3f(0.5f, 0.5f, 1);
         for (int y = 0; y < height; y++)
             for (int x = 0; x < width; x++) {
                 glTexCoord2f(texc.get(), texc.get());
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.