0

so I'm programming Conway's game of life with JavaFX, and I have a problem.

The grid is represented with a Canvas. I made a method that update the canvas after a value changed in the grid, and a method that compute the next generation according to the rules of the cellular automaton.

The next step is to make the loop :

  1. compute the next generation
  2. refresh the canvas
  3. wait for 0.5 sec.

That's where it goes wrong. It's seems that instead of refreshing the canvas and then wait for 0.5 sec, the program wait for the end of the loop to repaint the canvas.

There are my methods :

public void repaintCanvas() {
    Double canvasWidth = gridCanvas.getWidth();
    Double canvasHeight = gridCanvas.getHeight();
    GraphicsContext gc = gridCanvas.getGraphicsContext2D();
    gc.clearRect(0, 0, canvasWidth, canvasHeight);
    gc.setFill(Color.RED);
    gc.strokeRect(0, 0, canvasWidth, canvasHeight);
    gc.setFill(Color.BLACK);
    Double x, y;
    for (int i = 0; i < this.grid.length; i++) {
        for (int j = 0; j < grid[0].length; j++) {
            if (grid[i][j].isAlive()) {
                x = j * cellWidth;
                y = i * cellHeight;
                Cell.display(gc, x.intValue(), y.intValue(), cellWidth.intValue(), cellHeight.intValue());
            }
        }
    }
}

public void computeNextGeneration() {
    Cell[][] newGrid = new Cell[grid.length][grid[0].length];
    for (int i = 0; i < newGrid.length; i++) {
        for (int j = 0; j < newGrid[0].length; j++) {
            newGrid[i][j] = opperationOnCell(i, j);
        }
    }
    grid = newGrid;
    repaintCanvas();
}

I tried several things, like the TimeLine class, but the way I change the canvas makes it impossible since the TimeLine seems only to change the shapes in time, when repaintCanvas() replace them (black square = living cell, white square = dead cell).

How can I fix this ?

Thanks in advance for any help.

Nono
  • 1
  • 3
    You must not sleep on the FX Application thread. Using a `Timeline` is a good approach. Your explanation of why you can’t use it is not at all clear. See https://stackoverflow.com/a/60685975/2189127 (if you haven’t already) – James_D May 14 '23 at 15:55
  • 1
    A small, complete example is examined [here](https://stackoverflow.com/q/21396055/230513). – trashgod May 14 '23 at 17:46
  • 1
    *"I tried several things, like the TimeLine class, but the way I change the canvas makes it impossible since the TimeLine seems only to change the shapes in time, when repaintCanvas() replace them (black square = living cell, white square = dead cell)."* -> I don't understand what this means, so it is hard to know, what is "wrong" and to advise how to "fix" it. – jewelsea May 15 '23 at 04:55
  • 3
    If you follow the method trashgod linked, what you do is separate the code for the simulator from the UI completely. On a timeline you update the simulation model periodically (e.g. twice a second), no UI work at all. In an AnimationTimer, you refresh the view, reading the simulation model (the grid array) and drawing it to the canvas, no simulation logic at all. You don't have to program this way, though your current code is close to this. I like this approach because simulation logic can be unit tested and the UI can be changed without rewriting the simulation. – jewelsea May 15 '23 at 05:44

0 Answers0