Java 图形 - 重新绘制图像而不删除另一个图像

Java graphics - repaint an image without removing another

我正在使用 Graphics g 为我的播放器和地图绘制图像。每当玩家移动时,我想将玩家图像更新到新位置而不更新地图图像。我该怎么做?

提前感谢您的任何回复!

对不起我的乱码。

   Main:
package Main;
import java.awt.Dimension;

import javax.swing.JFrame;

public class Main {
    public static JFrame frame;

    static int size = 32;
    static int width = size*20;
    static int height = size*17;

    static playerObj p = new playerObj(200,200);

    static tileMap grid = new tileMap();

    public static void main(String[] args) {
        frame = new JFrame("Game");
        frame.getContentPane().setPreferredSize(new Dimension(width-9, height-9));
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.add(new drawGraphics());
        frame.setVisible(true);
    }
}

drawGraphics:
package Main;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class drawGraphics extends JPanel implements Runnable {
    private static final long serialVersionUID = 1L;

    boolean running = true;
    boolean renderMap = true;

    playerObj p = Main.p;
    int size = Main.size;
    static int x = 0;
    static int y = 0;

    Thread thread = new Thread(this);

    public drawGraphics() {
        setFocusable(true);
        addKeyListener(new controls());
        start();
    }

    public void start() {
        thread.start();
    }

    public void paint(Graphics g) {
        Graphics2D d = (Graphics2D) g;
        super.paintComponent(g);

        if (renderMap) {
            map(d);
        }

        player(g);

        repaint();
    }

    public void player(Graphics g) {
        try {
            BufferedImage pImg = ImageIO.read(new File("images/player.png"));
            g.drawImage(pImg, p.getX(), p.getY(), null);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void map(Graphics g) {
        System.out.println("2dfsdf");
        Graphics2D d = (Graphics2D) g;
        for (int i = 0; i < tileMap.map.length; i++) {
            for (int j = 0; j < tileMap.map[i].length; j++) {
                d.setColor(tileMap.map[i][j].getC());
                d.fillRect(tileMap.map[i][j].getX(), tileMap.map[i][j].getY(),
                        Main.size, Main.size);
                if (tileMap.map[i][j].solid()) {
                    d.setColor(Color.BLACK);
                    d.drawRect(tileMap.map[i][j].getX(),
                            tileMap.map[i][j].getY(), Main.size, Main.size);
                }
            }
        }
    }

    public void move() {
        if (controls.up) {
            controls.goUp();
            y--;
            repaint();
        }
        if (controls.down) {
            controls.goDown();
            y++;
            repaint();
        }
        if (controls.left) {
            controls.goLeft();
            x--;
            repaint();
        }
        if (controls.right) {
            controls.goRight();
            x++;
            repaint();
        }
        if (controls.place) {
            repaint();
        }
    }

    public void run() {
        while (running == true) {
            move();
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

不要直接在 JFrame 中绘制,而是在 JFrame 中显示的 JPanel 中绘制。

如果您使用 Swing 作为您的 GUI 库,则将背景绘制为 BufferedImage,并首先在您的 paintComponent 方法中绘制它。然后在接下来需要的任何位置绘制您的图像精灵:

@Override  // this is in a JPanel extended class
protected void paintComponent(Graphics g) {
   super.paintComponent(g);
   if (backgroundImg != null) {
      g.drawImage(backgroundImg, 0, 0, null);
   }
   if (spriteImg != null) {
      g.drawImage(spriteImg, spriteX, spriteY, null);
   }
}

您的代码存在一些问题:

  • 不要覆盖 paint 然后在其中调用 super.paintComponent
  • 而是覆盖 paintComponent 并在内部调用相同的超级方法。
  • 切勿在 paint 或 paintComponent 内部调用 repaint()。请改用 Swing 计时器。
  • 在您的 player(...) 方法中,每次调用该方法时您都会重新读取图像,这会减慢您的绘画速度。不要这样做,而是一次性读取图像,并将其保存到变量中。