Why is JavaFX canvas sometimes failing to draw and breaking my program?

349 views Asked by At

This is my first question here so take it easy ;)
Ok so, I am trying to make a game in Java completely from scratch. The problem I am having at the moment is drawing on a canvas. So essentially the game takes place in a hexagonal grid, so I am trying to draw a hexagonal grid over the screen. The problem is that sometimes (Maybe half the time) the grid doesn't fully render and everything breaks. Upon clicking play game from the main menu, the user should be greeted with a game screen, which is for now just a canvas. A hexagon grid is immediately drawn. When testing with a 10 x 10 hexagonal grid, some hexagons on the right side (that are rendering last) flicker for a few seconds and then either stop flickering and everything works (I can zoom) or they disappear completely and I can no longer zoom. With a 90 x 90 grid, I can't see any flickering as it is likely off-screen, but zooming in/out never works.

Game.java

public class Game {
private static Game ourInstance = new Game();

public static Game getInstance() {
    return ourInstance;
}

public final float MIN_SIZE = 64.0f;
public final float MAX_SIZE = 512.0f;
public final float SCROLL_MULTIPLIER = 0.2f;

private float size;

private Point gridPosition;

private HexGrid hexGrid;

public GraphicsContext gc;

private Timer timer = new Timer();

private Game() {

}

public void startGame(GraphicsContext gc) {
    hexGrid = new HexGrid(HexHelper.GRID_ORIENTATION.POINTY, HexHelper.GRID_SIZE.OPEN_SPACE);
    size = 128.0f;
    gridPosition = new Point(0.0f, 0.0f);
    runGame(gc);
}

public void runGame(GraphicsContext gc) {
    timer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            updateGame(gc);
        }
    }, 0, 1000L / 60L);
}

public void updateGame(GraphicsContext gc) {

    repaintGame(gc);
}

public void repaintGame(GraphicsContext gc) {
    gc.clearRect(0, 0, 1920, 1080);
    gc.setStroke(Color.BLACK);
    //TODO change with zoom
    gc.setLineWidth(5.0);
    hexGrid.drawGrid(gc, size);
}

public void zoomCamera(double delta) {
    if(size >= MIN_SIZE && size <= MAX_SIZE) {
        size += delta * SCROLL_MULTIPLIER;
        size = Math.max(MIN_SIZE, Math.min(MAX_SIZE, size));

    }
    System.out.println(size);
}
}

HexGrid.java

package hexlib;

import javafx.scene.canvas.GraphicsContext;

public class HexGrid {
private HexHelper.GRID_ORIENTATION orientation;
private Hexagon[][] grid;

public HexGrid(HexHelper.GRID_ORIENTATION o, HexHelper.GRID_SIZE s) {
    orientation = o;
    generateGrid(s);
}

public void generateGrid(HexHelper.GRID_SIZE s) {
    int tiles;

    switch (s) {
        case OPEN_SPACE:
            tiles = 90;
            break;
        case PLANETARY_ORBIT:
            tiles = 10;
            break;
        default:
            tiles = 1;
    }

    grid = new Hexagon[tiles][tiles];

    for (int i = 0; i < tiles; i++) {
        for (int j = 0; j < tiles; j++) {
            grid[j][i] = new Hexagon(new OffsetCoord(j, i));
        }
    }
}

public void drawGrid(GraphicsContext gc, float size) {
    Point[] points;

    for (Hexagon[] row: grid) {
        for (Hexagon h : row) {

            //Gets the coordinates of vertices of the hexagon located at the given coordinate
            points = HexHelper.evenRToPixelHexagonVertices(h.getOffsetCoord(), size);
            double[] xPoints = new double[]{points[0].x, points[1].x, points[2].x, points[3].x, points[4].x, points[5].x};
            double[] yPoints = new double[]{points[0].y, points[1].y, points[2].y, points[3].y, points[4].y, points[5].y};
            gc.strokePolygon(xPoints, yPoints, 6);
        }
    }
}

public Hexagon[][] getGrid() {
    return grid;
}
}

HexHelper.java

package hexlib;

import utils.ExtendedMath;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class HexHelper {

public enum GRID_ORIENTATION {
    POINTY,
    FLAT;
}

public enum GRID_SIZE {
    OPEN_SPACE,
    PLANETARY_ORBIT,
    LARGE_PLANET,
    SMALL_PLANET,
    ONE;
}

public static Point evenRToPixelHexagonCenter(OffsetCoord o, float size) {
    float x, y;

    //If row is odd, x = column + 1 (times size)
    //Else x = column + 1/2 (times size)
    if (o.getCoords()[1] % 2 == 0) {
        x = (o.getCoords()[0] + 1.0f) * size;
    }
    else {
        x = (o.getCoords()[0] + 0.5f) * size;
    }

    //0.75 is 3/4 height between each hexagon
    //0.5  is 1/2 height that inherently exists between the top of the first row and their centers
    y = (o.getCoords()[1] * 0.75f * size) + (0.5f * size);

    return new Point(x, y);
}

public static Point[] evenRToPixelHexagonVertices(OffsetCoord o, float size) {
    float x, y;
    Point[] points = new Point[6];
    Point centerPoint = evenRToPixelHexagonCenter(o, size);

    points[0] = new Point(centerPoint.x + (0.00f * size), centerPoint.y + (0.50f * size));
    points[1] = new Point(centerPoint.x + (0.50f * size), centerPoint.y + (0.25f * size));
    points[2] = new Point(centerPoint.x + (0.50f * size), centerPoint.y - (0.25f * size));
    points[3] = new Point(centerPoint.x + (0.00f * size), centerPoint.y - (0.50f * size));
    points[4] = new Point(centerPoint.x - (0.50f * size), centerPoint.y - (0.25f * size));
    points[5] = new Point(centerPoint.x - (0.50f * size), centerPoint.y + (0.25f * size));
    return points;
}
}

gc is a GraphicsContext created in the JavaFX application and passed into Game.getInstance().startGame()

Any help is appreciated, and thank you in advance for your help

0

There are 0 answers