1 package eu.svjatoslav.sixth.e3d.examples.life_demo;
3 import eu.svjatoslav.sixth.e3d.geometry.Point3D;
4 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.base.AbstractCompositeShape;
5 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.base.SubShape;
8 * This is our 2D game of life world. It contains 2D array of {@link Cell}'s.
10 class Matrix extends AbstractCompositeShape {
13 * Empty space between cells.
15 private static final int BORDER = 5;
18 * Matrix size X and Y. (Amount of cells.)
20 private static final int SIZE = 30;
23 * Object marker in 3D scene. Allows to locate all stars from the scene.
25 private static final String GROUP_STARS = "stars";
28 * Object marker in 3D scene. Allows to locate surface on the scene.
30 private static final String GROUP_SURFACE = "surface";
33 * 2 dimensional matrix of cells
35 private final Cell[][] cells = new Cell[SIZE][];
37 public Matrix(final Point3D location) {
41 for (int x = 0; x < SIZE; x++) {
42 cells[x] = new Cell[SIZE];
45 for (int z = 0; z < SIZE; z++) {
46 // create cell and register it
47 final Cell cell = new Cell(getCellLocation(x, z));
53 setGroupForUngrouped(GROUP_SURFACE);
61 // mark every cell as inactive
62 for (int x = 0; x < SIZE; x++)
63 for (int y = 0; y < SIZE; y++)
64 cells[x][y].setActive(false);
66 // remove history stars
67 removeGroup(GROUP_STARS);
71 * Compute survived cells based on the rules of Conway's Game of Life.
73 private void computeSurvivedCells() {
75 for (int y = 0; y < SIZE; y++)
76 for (int x = 0; x < SIZE; x++)
79 for (int y = 0; y < SIZE; y++)
80 for (int x = 0; x < SIZE; x++)
81 cells[x][y].setActive(cells[x][y].survives);
85 private void processCell(int x, int y) {
86 int aliveNeighbours = countNeighbours(x, y);
88 if (cells[x][y].isActive()) {
89 cells[x][y].survives = ((aliveNeighbours == 2) || (aliveNeighbours == 3));
91 cells[x][y].survives = aliveNeighbours == 3;
95 private int countNeighbours(int x, int y) {
97 for (int ny = y - 1; ny <= y + 1; ny++)
98 for (int nx = x - 1; nx <= x + 1; nx++)
99 if (isCellAlive(nx, ny)) result++;
101 if (isCellAlive(x, y)) result--;
106 private boolean isCellAlive(int x, int y) {
107 if (x < 0) return false;
108 if (x >= SIZE) return false;
109 if (y < 0) return false;
110 if (y >= SIZE) return false;
111 return cells[x][y].isActive();
115 * Evolve matrix for one iteration
117 public void evolve(final boolean preserveHistory) {
123 computeSurvivedCells();
126 private Point3D getCellLocation(final int x, final int z) {
127 final int shift = -((SIZE / 2) * (Cell.SIZE + BORDER));
130 (x * (Cell.SIZE + BORDER)) + shift,
132 (z * (Cell.SIZE + BORDER)) + shift);
136 * Leave trail of active cells as stars above matrix.
138 private void markActiveCells() {
139 // mark survived cells
140 for (int x = 0; x < SIZE; x++)
141 for (int y = 0; y < SIZE; y++)
142 if (cells[x][y].isActive())
143 addShape(new Star(getCellLocation(x, y)));
145 setGroupForUngrouped(GROUP_STARS);
149 * Find all history tracking stars and shift them up.
151 private void shiftStarsUp() {
153 for (final SubShape subShape : getGroup(GROUP_STARS))
154 ((Star) subShape.getShape()).getLocation().translateY(-10);