Java 图形 - 绘制多个彼此相邻的图像会创建空行 |解决了

问题描述 投票:0回答:1

我正在尝试绘制游戏地图,它具有带有 x 和 y 位置的图块对象。 瓷砖的图像由 1 类保存,我在完成缩放后调整它们的大小。 我想以双精度绘制图像,事实上我正在使用 AffineTransform 来翻译它们,并且还以双精度缩放。

Camera 类中,我将缩放变量设置为双倍。 当zoom为0时,似乎一切都好,但是当我移动鼠标时,这个错误仍然发生。 (因为相机根据鼠标距中心的距离移动)

我正在一个名为 GameScreen 的面板上绘制所有内容,我有多个 ScreenPainter 类,我可以在其中绘制不同的内容,然后在该面板上绘制所有内容。

游戏屏幕类:

public class GameScreen extends JPanel {

    private static GameScreen INSTANCE;
    private static Graphics2D graphics2D;

    private List<ScreenPainter> painters = new ArrayList<>();

    public GameScreen() {
        INSTANCE = this;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        graphics2D = (Graphics2D) g;
        graphics2D.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);

        for (ScreenPainter painter : painters) painter.paint();
        for (BAText text : new ArrayList<>(TextRegistry.getTexts().values())) {
            if (text != null) text.drawText(graphics2D);
        }

        //if (BlueArchangels.STATE == GameState.PAUSE) MenuRegistry.getExitMenu().paint(graphics);

        graphics2D.dispose();
    }

    public void updatePainters() {
        painters = new ArrayList<>(ScreenPainterManager.getPainters());
    }

    public static GameScreen INSTANCE() {
        return INSTANCE;
    }

    public static Graphics2D getGraphics2D() {
        return graphics2D;
    }
}

MapPainter类中的方法

    @Override
    public void paint() {
        if (grids == null) {
            assignValue();
            return;
        }

        double cellWidth = getCellWidth(), cellHeight = getCellHeight();
        boolean zooming = Camera.zooming();

        for (Map.TileGrid tileGrid : grids) {
            int offsetX = tileGrid.getOffsetX(), offsetY = tileGrid.getOffsetY();

            for (Map.Tile tile : tileGrid.getAllTiles()) {
                BufferedImage image = tile.getTileImage();
                if (image == null) continue;

                double width = cellWidth, height = cellHeight;
                double x = width * (tile.x + offsetX), y = height * (-tile.y - offsetY);

                AffineTransform transform = new AffineTransform();

                // Ground tiles are already at the same size as the cell.
                if (!tile.isGround()) {
                    double w = image.getWidth(), h = image.getHeight();
                    // Check how many times the cell stays inside the image, to scale it later.
                    double timesX = w / width, timesY = h / height;

                    // Calculate the target size of the tile.
                    width = width * timesX;
                    height = height * timesY;

                    // Scale the size to the target size.
                    transform.scale(width / w, height / h);

                    // Now with the target size, we calculate the exact location to place it in its cell at (x; y).
                    // Otherwise, when scaled it will be placed on another cell and not its original.

                    // Now we correct the position by placing the x coordinate and
                    // the bottom part of the tile in the middle of the cell.
                    x += -(width / 2D) + (cellWidth / 2D);
                    y += -height + (cellHeight / 2D);
                }

                if (Camera.isOutCamera(x, y, width, height)) continue;

                if (zooming) {
                    // If zooming and the tile is ground, scale it to the correct size while waiting for resizing.
                    if (tile.isGround()) {
                        //transform.scale(width / image.getWidth(), height / image.getHeight());
                        x += -(width / 2) + (cellWidth / 2);
                        y += -(height / 2) + (cellHeight / 2);
                    }
                    wasZooming = true;
                } else {
                    // Once the game is no more zooming, update the ground tile sizes and draw them without scaling.
                    if (wasZooming) resizeMapTiles();
                    wasZooming = false;
                }
                transform.translate(Camera.toX(x), Camera.toY(y));

                if (zooming) {
                    // If zooming and the tile is ground, scale it to the correct size while waiting for resizing.
                    if (tile.isGround()) transform.scale(width / image.getWidth(), height / image.getHeight());

                }

                int degrees = tile.getRotation();
                if (degrees != 0) transform.rotate(Math.toRadians(degrees), width / 2D, height / 2D);

                ScreenPainter.drawImage(image, transform);
            }
        }
    }

知道为什么会发生这种情况吗? 问题视频

编辑1

我找到了这些线路的主要问题。 (据我测试)

问题是以双精度绘制的,我将缩放变量编辑为整数,问题大大减少了,现在当我尝试移动时会出现问题,因为当我绘制时位置也是双精度的使用整数位置,问题不会出现。

现在另一个问题是,如何解决双精度问题?是渲染问题吗?舍入问题?有人有过这样的经历吗?

java java-2d
1个回答
0
投票

我终于发现问题了,三周后...

您在视频中看到的问题是由 JPanel 不透明引起的(我不知道为什么会导致该问题)。

要修复这个恼人的错误,只需将 JPanel 设置为 not opaque

解决此问题的最佳方法

重写 isOpaque 方法以确保它始终为 false:

@Override
public boolean isOpaque() {
    return false;
}
© www.soinside.com 2019 - 2024. All rights reserved.