如何移动图像(动画)?

我正试图在X轴上移动船(没有键盘)。 如何将运动/动画与boat.png联系起来,而不是与任何其他图像联系起来?

 public class Mama extends Applet implements Runnable { int width, height; int x = 200; int y = 200; int dx = 1; Image img1, img2, img3, img4; @Override public void init(){ setSize(627, 373); Thread t = new Thread(this); img1 = getImage(getCodeBase(),"Background.png"); img2 = getImage(getCodeBase(), "boat.png"); img3 = getImage(getCodeBase(), "LeftPalm.png"); img4 = getImage(getCodeBase(), "RightPalm.png"); } @Override public void paint(Graphics g){ g.drawImage(img1, 0, 0, this); g.drawImage(img2, 200, 200, this); g.drawImage(img3, 40, 100, this); g.drawImage(img4, 450, 130, this); } @Override public void run() { while(true){ x += dx; repaint(); try { Thread.sleep(17); } catch (InterruptedException e) { System.out.println("Thread generates an error."); } } } } 

有一些东西突出……

问题”

如前所述,您需要为图像绘制过程提供变量参数。 g.drawImage(img2, x, y, this); ,这将允许您定义应该绘制图像的位置。

虽然您已经实现了Runnable ,但实际上您还没有启动任何线程来调用它。 这意味着,实际上没有任何东西改变变量。

在你的start方法中,你应该调用类似new Thread(this).start()

建议

虽然您已将问题标记为Swing,但您使用的是AWT组件。 这是不推荐的(实际上小程序通常不鼓励,因为它们很麻烦 – 恕我直言)。 另一个问题,就像你很快就会发现的那样,它们不是双缓冲的,这通常会在执行动画时导致闪烁,这是不可取的。

另外,我们也不鼓励覆盖像Applet这样的顶级容器的paint方法。 顶级容器往往包含许多其他组件,通过覆盖这样的paint方法,您可以销毁此设置。 此外,顶级容器也不倾向于双缓冲。

下面的示例使用了一个JFrame ,但将它转换为使用JApplet并不需要太多(只需将AnimationPanel放到它上面。这是为什么不鼓励从顶级容器扩展的另一个原因;)

在此处输入图像描述

 public class AnimatedBoat { public static void main(String[] args) { new AnimatedBoat(); } public AnimatedBoat() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame("Test"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new AnimationPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class AnimationPane extends JPanel { private BufferedImage boat; private int xPos = 0; private int direction = 1; public AnimationPane() { try { boat = ImageIO.read(new File("boat.png")); Timer timer = new Timer(40, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { xPos += direction; if (xPos + boat.getWidth() > getWidth()) { xPos = getWidth() - boat.getWidth(); direction *= -1; } else if (xPos < 0) { xPos = 0; direction *= -1; } repaint(); } }); timer.setRepeats(true); timer.setCoalesce(true); timer.start(); } catch (IOException ex) { ex.printStackTrace(); } } @Override public Dimension getPreferredSize() { return boat == null ? super.getPreferredSize() : new Dimension(boat.getWidth() * 4, boat.getHeight()); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); int y = getHeight() - boat.getHeight(); g.drawImage(boat, xPos, y, this); } } } 

你需要替换g.drawImage(img2, 200, 200, this);g.drawImage(img2, x, y, this);