Search code examples
javajavafxgame-enginerectanglespane

Remove spacing between rectangles JavaFX


I'm working on an ASCII graphics engine in Java, to emulate terminal graphics without some of the headaches of dealing with actual terminals.

One key element is coloring the background of characters. So at every position, I put a rectangle, which serves as the background color, and a Text object, which represents a character (using monospace fonts).

I've tried using FlowPanes, TilePanes, GridPanes, but regular Panes seem to work best (least spacing achieved). Here is an image that shows the issue at hand: Screenshot

I'm trying to make all the rectangles align in a way that there is no visible space to see through to the background. In the image linked above, there should be no black ridges between the colored rectangles.

Here is the code I have that adds the Rectangle and Text for each "pixel" (which is simply a class called Char that holds a Rectangle and a Text object).

for (int x = 0; x < COLUMNS; x++)
    for (int y = 0; y < ROWS; y++)
        pixels[x][y] = new Char(pane, paddingX + x * width, paddingY + y * height, width, height);

The height and width are calculated before this block, and are determined based on the font used. They represent the width and height of any character, since the font used is monospace. The padding is just a number used to center the "pixels", and is also determined before the nested loop.

Char class:

private Text ch;
private Rectangle background;

Char(Pane pane, double x, double y, double w, double h) {
    ch = new Text();
    ch.relocate(x, y);
    ch.setFont(View.font);
    ch.setFill(Color.WHITE);

    background = new Rectangle(w, h, Color.BLACK);
    background.relocate(x, y);

    ch.setBoundsType(TextBoundsType.VISUAL);

    pane.getChildren().addAll(background, ch);
}

Solution

  • This is a rounding issue. It can be fixed by making sure you're using integral locations and sizes.

    In the following code you replacing the assignments for x, y, nx and ny to the ones in the comments results in visible gaps but changing w and h to integral values, e.g. 10, also prevents visible gaps:

    @Override
    public void start(Stage primaryStage) {
        double w = 10.5;
        double h = 10.5;
    
        Pane pane = new Pane();
    
        for (int i = 0; i < 57; i++) {
            for (int j = 0; j < 57; j++) {
                double x = Math.floor(i * w);
                double y = Math.floor(j * h);
                double nx = Math.floor((i + 1) * w);
                double ny = Math.floor((j + 1) * h);
    //            double x = i * w;
    //            double y = j * h;
    //            double nx = (i + 1) * w;
    //            double ny = (j + 1) * h;
                Rectangle rect = new Rectangle(x, y, nx - x, ny - y);
                rect.setFill(Color.BLACK);
                pane.getChildren().add(rect);
            }
        }
    
        primaryStage.setScene(new Scene(pane, 600, 600));
        primaryStage.show();
    }