简体   繁体   中英

Java AWT drawing tiles laves gap

I am trying to make a tile based game in Java and I have noticed a problem with the drawing. There is about a one pixel gap between some of the tiles and I am not sure what is causing it.

Here is a screenshot of it:

https://i.stack.imgur.com/UbJ2B.png

Here is my code so far:

Main class:

package Game.main;

import javax.swing.JFrame;

public class Main {
    public static JFrame window;
    public static void main(String[] args) {
        window = new JFrame();
        window.setVisible(true);
        window.setSize(1280, 720);
        window.setTitle("Game");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Game game = new Game();
        window.add(game);
    }
}

Game class:

package Game.main;

import javax.swing.JPanel;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;

import java.util.ArrayList;

import Game.tile.Tile;

public class Game extends JPanel implements Runnable {

    public Game() {
        start();
    }

    boolean running = false;

    int width,height;

    ArrayList<Tile> tiles = new ArrayList<>();

    public void paint(Graphics g1) {
        //cast to graphics2d
        Graphics2D g = (Graphics2D)g1;
        //fill background
        g.setColor(Color.CYAN);
        g.fillRect(0, 0, width, height);
        //draw tiles
        for(int i = 0; i < tiles.size(); i++) {
            tiles.get(i).render(g, width, height);
        }
    }

    private void start() {
        Thread gameThread = new Thread(this);
        gameThread.start();
        //create start tiles
        for(int x = 0; x < 1000; x+=10) {
            for(int y = 700; y < 1000; y+=20) {
                Tile tile = new Tile(x, y);
                tiles.add(tile);
            }
        }
    }

    @Override
    public void run() {
        running = true;
        while(running) {
            //get window width and height
            requestFocus();
            width = Main.window.getWidth();
            height = Main.window.getHeight();
            //redraw current frame
            repaint();
        }
    }
}

Tile class:

package Game.tile;

import java.awt.Graphics2D;
import java.awt.Color;

public class Tile {
    public int x,y;
    public int w,h;
    public Tile(int x, int y) {
        this.x = x;
        this.y = y;
        this.w = 10;
        this.h = this.w*2;
    }
    public void render(Graphics2D g, int width, int height) {
        g.setColor(Color.GRAY);
        g.fillRect(this.x*width/1000, this.y*height/1000, this.w*width/1000, this.h*height/1000);
    }
}

You have magic numbers in your "Game" class:

    for(int x = 0; x < 1000; x+=10) {
        for(int y = 700; y < 1000; y+=20) {
            Tile tile = new Tile(x, y);
            tiles.add(tile);
        }

And you have more magic numbers in your Tile class:

    this.w = 10;
    this.h = this.w*2;
}
public void render(Graphics2D g, int width, int height) {
    g.setColor(Color.GRAY);
    g.fillRect(this.x*width/1000, this.y*height/1000, this.w*width/1000, this.h*height/1000);
}

You are also going to get rounding when you use:

  x * width / 1000

So the "x" value you get when painting will not always be a multiple of 10 like you expect. This is probably why you get the gaps between tiles.

You need to remove the magic numbers from multiple classes. For example the Tile class should be self contained. It should be able to paint itself without any magic numbers. All the information should be passed to the class in the constructor.

For example:

//public Tile(int x, int y) {
public Tile(int x, int y, int width, int height) {

Then in the painting logic you can use:

//public void render(Graphics2D g, int width, int height) {
public void render(Graphics2D g) {
    g.setColor(Color.GRAY);
    //g.fillRect(this.x*width/1000, this.y*height/1000, this.w*width/1000, this.h*height/1000);
    g.drawRect(x, y, width, height);
}

And in you Game class when you create the Tile you would use:

//Tile tile = new Tile(x, y);
Tile tile = new Tile(x, y, 10, 20);

Now the Game class fully controls the size and number of tiles. The Tile class just paints itself and doesn't worry about the size of the Game panel.

Of course you have to make sure you use reasonable values when creating the tiles:

    for(int x = 0; x < 1000; x+=10) {
        for(int y = 700; y < 1000; y+=20) {

Why would the "y" variable start at 700 when the height of the frame is only 720?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM