我正在进行2D游戏,我需要在另一个上面绘制图像。在我绘制第一个图像(较大的一个,jpg)之后,第二个图像(较小的一个,png)从第二个图像到右下角的位置擦除。像这样:
我已经对此进行了一些研究,并且有人建议我使用缓冲图像,所以我用两个图像做了这个,问题仍然存在。这是我看过的一篇文章:How to draw an image over another image?。我也看到有人建议使用graphics2d,虽然我不太明白使用它们的原因或如何使用它们。我是java图形和图像的新手,所以这可能是一个愚蠢的错误。 这是我的代码。谢谢。
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import javax.swing.*;
import java.util.ArrayList;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.IOException;
public class DisplayExample extends JComponent
{
private BufferedImage backgroundImage;
private String backgroundName;
private BufferedImage image; //image to draw
private int imageX; //position of left edge of image
private int imageY; //position of top edge of image
private JFrame frame;
public static void main(String[] args)
{
DisplayExample example = new DisplayExample();
example.run();
}
public DisplayExample()
{
imageX = 200;
imageY = 200;
backgroundName = "backgroundShip.jpg";
URL backgroundURL = getClass().getResource(backgroundName);
if (backgroundURL == null)
throw new RuntimeException("Unable to load: " + backgroundName);
try{backgroundImage = ImageIO.read(backgroundURL);}catch(IOException ioe){}
//load image
String fileName = "explosion.png";
URL url = getClass().getResource(fileName);
if (url == null)
throw new RuntimeException("Unable to load: " + fileName);
//image = new ImageIcon(url).getImage();
try{image = ImageIO.read(url);}catch(IOException ioe){}
System.out.println(image instanceof BufferedImage);
setPreferredSize(new Dimension(1040,500)); //set size of drawing region
//need for keyboard input
setFocusable(true); //indicates that WorldDisp can process key presses
frame = new JFrame();
frame.getContentPane().add(this);
frame.pack();
frame.setVisible(true);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if(backgroundImage != null)
g.drawImage(backgroundImage,0,0,getWidth(), getHeight(), null);
g.drawImage(image, imageX, imageY, this);
}
public void run()
{
while(true)
{
imageY+=1;
repaint();
try{Thread.sleep(100);}catch(Exception e){}
}
}
}
答案 0 :(得分:1)
所以我拿了你的代码,添加了我自己的图片,它运行正常。
话虽如此,有些方面可以改进:
run
方法将线程竞争条件引入代码的风险。您应该考虑使用Swing Timer
。有关详细信息,请参阅How to use Swing Timers。这允许您安排在EDT上下文中调用的常规回调,使更新UI的上下文更安全paint
方法中这样做,而是缩放图像并保留对结果的引用,并在需要绘制时使用它。KeyListener
上的密钥绑定API,它将解决与使用KeyListener
相关的许多问题。有关详细信息,请参阅How to Use Key Bindings。例如......
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DisplayExample extends JComponent {
private BufferedImage backgroundImage;
private String backgroundName;
private BufferedImage image; //image to draw
private int imageX; //position of left edge of image
private int imageY; //position of top edge of image
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
DisplayExample example = new DisplayExample();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(example);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public DisplayExample() {
imageX = 200;
imageY = 200;
try {
backgroundImage = ImageIO.read(new File("..."));
} catch (IOException ioe) {
ioe.printStackTrace();
}
//load image
try {
image = ImageIO.read(new File("..."));
} catch (IOException ioe) {
ioe.printStackTrace();
}
//need for keyboard input
//setFocusable(true); //indicates that WorldDisp can process key presses
// Use the key bindings API instead, causes less issues
Timer timer = new Timer(100, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
imageY += 1;
repaint();
}
});
timer.start();
}
@Override
public Dimension getPreferredSize() {
return backgroundImage == null ? new Dimension(200, 200) : new Dimension(backgroundImage.getWidth(), backgroundImage.getHeight());
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (backgroundImage != null) {
// Scaling is expensive, don't do it here
int x = (getWidth() - backgroundImage.getWidth()) / 2;
int y = (getHeight() - backgroundImage.getHeight()) / 2;
g2d.drawImage(backgroundImage, x, y, this);
}
g2d.drawImage(image, imageX, imageY, this);
g2d.dispose();
}
}