I have a Game of Life program that has a grid[][]
array which is populated by Cell
objects. If there's a cell in a grid square, that grid square is green. One can add the cells manually by clicking on the grid squares and turning them green.
When a Start Iterations
button is pressed a startIterations()
method starts, which makes use of AnimationTimer
. It all runs in the single thread, until there are no alive cells left or until 10 seconds pass.
However, I still can interfer with that process by clicking on free squares and turning them green. Also I have a Stop Iterations
button that invokes AnimationTimer
's stop()
method when pressed; I can access that button while the simulations are being run at it works OK. How is that possible, if there's only one thread?
Even though it works OK, I have a feeling it's wrong to have everything inside a single thread. What is the better approach? Put animation in a separate second thread?
Main class:
public class Main extends Application {
private static int gameWidth = 800;
private static int gameHeight = 600;
private static int gridSize = 20;
private static Cell[][] grid = new Cell[gridSize][gridSize];
private static Scene scene;
private static Displayer gameDisplayer;
static SimpleIntegerProperty simulationCount = new SimpleIntegerProperty(0);
static int aliveCellsCount = 0;
private static boolean iterationsStatus = false;
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Advanced Game of Life");
createGrid();
gameDisplayer = new Displayer(gameWidth, gameHeight, grid);
scene = gameDisplayer.getGameScene();
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
startIterations()
method:
public static void startIterations() {
System.out.println("Starting iterations");
simulationCount.set(0);
final long startNanoTime = System.nanoTime();
new AnimationTimer() {
private long lastUpdateTime = 0;
public void handle(long currentNanoTime) {
int currentTime = (int) Math.round((currentNanoTime - startNanoTime) / (double) 1000_000_000L);
if (currentNanoTime - lastUpdateTime >= 100_000_000) {
aliveCellsCount=updateGrid();
simulationCount.set(simulationCount.get() + 1);
lastUpdateTime = currentNanoTime;
}
if (aliveCellsCount == 0 || currentTime > 10 || !iterationsStatus) {
stop();
System.out.println("Stopped iterations");
}
}
}.start();
System.out.println("Finished iterations");
}
updateGrid()
method:
public static int updateGrid() {
System.out.println("Updating grid");
int livingCount;
for (int i = 0; i < gridSize; i++) {
for (int j = 0; j < gridSize; j++) {
livingCount = 0;
livingCount += checkGrid(i - 1, j);
livingCount += checkGrid(i, j - 1);
livingCount += checkGrid(i + 1, j);
livingCount += checkGrid(i, j + 1);
livingCount += checkGrid(i - 1, j - 1);
livingCount += checkGrid(i + 1, j + 1);
livingCount += checkGrid(i - 1, j + 1);
livingCount += checkGrid(i + 1, j - 1);
if (livingCount == 3) {
grid[i][j].setNextStatus(true);
} else if (livingCount == 2 && grid[i][j].getStatus()) {
grid[i][j].setNextStatus(true);
} else {
grid[i][j].setNextStatus(false);
}
System.out.print("livingCount for (" + i + ", " + j + "): " + livingCount);
System.out.println(" => " + grid[i][j].getNextStatus());
}
}
int resultLivingCount = 0;
for (int i = 0; i < gridSize; i++) {
for (int j = 0; j < gridSize; j++) {
grid[i][j].setStatus(grid[i][j].getNextStatus());
resultLivingCount += grid[i][j].getStatus() ? 1 : 0;
// System.out.println("grid[" + i + "]["+j + "] is " + grid[i][j].getStatus());
}
}
return resultLivingCount;
}
handle()
method inside Displayer
class, that handles buttons clicks:
public void handle(ActionEvent event) {
if (event.getSource()==createCellButton) {
Main.createCell();
}
else if (event.getSource() == deleteCellsButton) {
Main.deleteCells();
cellsCountLabel.setText("Cells Count: " + (cellId + 1));
System.out.println("Cells deleted");
}
else if (event.getSource()==randomGridButton) {
System.out.println("Calling random grid");
Main.generateRandomGrid();
}
else if (event.getSource() == updateGridButton) {
Main.updateGrid();
}
else if (event.getSource() == startIterationsButton) {
Main.setIterationsStatus(true);
Main.startIterations();
}
else if(event.getSource()==stopIterationsButton) {
Main.setIterationsStatus(false);
}
else {
System.out.println("Unknown button");
}
}