在激光与矩形对象相交后,尝试让爆炸消失

编程语言 2026-07-12

我在用Java做一个小型游戏:飞船向一个矩形射出激光,矩形会被移除,同时出现一个爆炸PNG图片。我的问题是在于想让爆炸的动画在几秒后也被移除,但一直没搞定……爆炸动画不会消失。

下面是一些代码,真的非常感谢任何帮助……

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

public class MovingObject extends JPanel implements KeyListener {

    private ArrayList<Rectangle> rects = new ArrayList<>();
    private final int MAX_X = 400;
    private final int SPEED = 7;
    private BufferedImage image, image2, image3;
    private boolean visible = false;

    public MovingObject() {

        rects.add(new Rectangle(20, 50, 128, 128));
        rects.add(new Rectangle(80, 75, 32, 32));
        rects.add(new Rectangle(130, 25, 128, 128));
        rects.add(new Rectangle(200, 50, 50, 50));
        rects.add(new Rectangle(300, 50, 50, 50));
        try {
            image = ImageIO.read(new File("C:/Users/hm_08/OneDrive/Desktop/ship3.png"));
            image2 = ImageIO.read(new File("C:/Users/hm_08/OneDrive/Desktop/shot.png"));
            image3 = ImageIO.read(new File("C:/Users/hm_08/OneDrive/Desktop/expl.png"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        bgColor();

        this.setFocusable(true);
        addKeyListener(this);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (visible) {
            g.drawImage(image3, rects.get(2).x, 25, 128, 128, this);
        }
        g.fillRect(rects.get(3).x, 50, 50, 50);
        if (!visible) {
            g.drawImage(image2, rects.get(1).x, 75, 32, 32, this);
        }
        g.drawImage(image, rects.get(0).x, 20, 128, 128, this);
        g.fillRect(300, 50, 50, 50);

    }

    private void bgColor() {
        setBackground(Color.BLACK);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Moving Object");

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 500);
        frame.add(new MovingObject());
        frame.setVisible(true);
    }

    @Override
    public void keyPressed(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.VK_SPACE) {
            Thread animationThread = new Thread(() -> {

                while (rects.get(1).x < MAX_X) {
                    if (!rects.isEmpty()) {
                        rects.get(1).x += SPEED;
                        repaint();
                        if (rects.get(1).intersects(rects.get(3))) {
                            visible = !visible;
                            rects.remove(3);
                            repaint();
                            break;
                        }
                        removeKeyListener(this);
                    }

                    try {
                        Thread.sleep(50); // Delay for smooth movement
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            });
            animationThread.start();
        }

    }

    @Override
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub

    }

}

更新:增加了一个定时器来发射激光,但这次的表现仍然和之前一样,出现了长度为3 的下标3 越界错误(更新后的代码如下:)

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

public class MovingObject extends JPanel implements KeyListener {

    private ArrayList<Rectangle> rects = new ArrayList<>();
    private final int SPEED = 7;
    private BufferedImage image, image2, image3;
    private boolean visible = false;

    public MovingObject() {

        rects.add(new Rectangle(20, 50, 128, 128));
        rects.add(new Rectangle(80, 75, 32, 32));
        rects.add(new Rectangle(130, 25, 128, 128));
        rects.add(new Rectangle(200, 50, 50, 50));
        rects.add(new Rectangle(300, 50, 50, 50));
        try {
            image = ImageIO.read(new File("C:/Users/hm_08/OneDrive/Desktop/ship3.png"));
            image2 = ImageIO.read(new File("C:/Users/hm_08/OneDrive/Desktop/shot.png"));
            image3 = ImageIO.read(new File("C:/Users/hm_08/OneDrive/Desktop/expl.png"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        bgColor();

        this.setFocusable(true);
        addKeyListener(this);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (visible) {
            g.drawImage(image3, rects.get(2).x, 25, 128, 128, this);
        }
        g.fillRect(rects.get(3).x, 50, 50, 50);
        if (!visible) {
            g.drawImage(image2, rects.get(1).x, 75, 32, 32, this);
        }
        g.drawImage(image, rects.get(0).x, 20, 128, 128, this);
        g.fillRect(300, 50, 50, 50);

    }

    private void bgColor() {
        setBackground(Color.BLACK);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Moving Object");

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 500);
        frame.add(new MovingObject());
        frame.setVisible(true);
    }

    @Override
    public void keyPressed(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.VK_SPACE) {
            Timer timer = new Timer(25, e -> {

                if (!rects.isEmpty()) {
                    rects.get(1).x += SPEED;
                    repaint();
                    System.out.println(rects.size());
                    if (rects.get(1).intersects(rects.get(3))) {
                        visible = !visible;
                        rects.remove(3);
                        repaint();

                    }
                    removeKeyListener(this);
                }

            });
            timer.start();

        }

    }

    @Override
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub

    }

}

解决方案

你应用程序最严重的问题在于混用不同的“矩形”。在名为 recs 的列表里,既有与飞船对应的矩形,也有“目标”矩形。删除元素时,随着你使用固定的索引,索引就开始出问题。然后你提到动画不会停止,但没有相应的机制来让它停止。你只检查与位置“3”处的“对象”的碰撞。至于激光呢?无论如何,我做了一个小应用,给你一个关于“事情可能会如何发展”的思路。希望对你有帮助。

public class Demo extends JFrame {

   MyContentPane contentPane;
   Timer timerLaser;
   int SPEED = 1;
   String type;
   boolean firstIteration = true;
   Rectangle removed = null;

   public Demo( String name ) {
      super( name );
   }

   void ini() {
      setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
      setSize( 800, 500 );
      contentPane = new MyContentPane();
      setContentPane( contentPane );
      contentPane.addRect( 200, 250, 50, 50 );
      contentPane.addRect( 470, 25, 128, 128 );
      contentPane.setShip( 20, 50, 128, 128 );
      setVisible( true );
      addKeyListener( new KeyAdapter() {
         @Override
         public void keyPressed( KeyEvent event ) {
            if( event.getKeyCode() == KeyEvent.VK_SPACE ) {
               type = "laser";
               execute();
            }
         }
      } );
   }

   void execute() {
      contentPane.setThereIsNow( true );
      Rectangle aux = contentPane.getAux();
      Rectangle ship = contentPane.getShip();

      timerLaser = new Timer( 25, e -> {
         if( type.equals( "laser" ) ) {
            if( firstIteration ) {
               contentPane.setAux( ship.x + ship.width, ship.y + 62, 1, 4 );
               firstIteration = false;
            }
            if( aux.width < 20 ) {
               aux.width += SPEED;
            }
            else {
               aux.x += SPEED;
            }
            for( Rectangle rec : contentPane.getRectangles() ) {
               if( rec.intersects( aux ) ) {
                  removed = rec;
                  contentPane.deleteRect( rec );
                  firstIteration = true;
                  type = "";
                  break;
               }
            }
            repaint();
         }
         else {
            if( firstIteration ) {
               contentPane.setAux( removed.x, removed.y, removed.width, removed.height );
               firstIteration = false;
            }
            aux.x -= 1;
            aux.width += 2;
            aux.y -= 1;
            aux.height += 2;
            repaint();
            if( removed.x - aux.x > 40 ) {
               timerLaser.stop();
               contentPane.setThereIsNow( false );
               firstIteration = true;
               type = "laser";
            }
         }
      });
      timerLaser.start();
   }

   public static void main( String[] args ) {
      Demo frame = new Demo( "Moving Object" );
      frame.ini();
   }
}
public class MyContentPane extends JComponent {

   private ArrayList<Rectangle> rects;
   private Rectangle ship;
   private Rectangle aux;
   boolean isLaser = true, thereIsNow = false;
   int auxX, auxY, auxWidth, auxHeigth;
   Timer timerLaser, timerExplosion;

   public MyContentPane() {
      rects = new ArrayList<>();
      aux = new Rectangle();
   }

   void addRect( int x, int y, int w, int h ) {
      rects.add( new Rectangle( x, y, w, h ) );
   }

   void setShip( int x, int y, int w, int h ) {
      ship = new Rectangle( x, y, w, h );
   }

   void setAux( int x, int y, int w, int h ) {
      aux.x = x;
      aux.y = y;
      aux.width = w;
      aux.height = h;
   }

   @Override
   public void paintComponent( Graphics g ) {
      super.paintComponent( g );
      Graphics2D gr = (Graphics2D) g;
      gr.clearRect( 0, 0, getWidth(), getHeight());
      gr.fillRect( ship.x, ship.y, ship.width, ship.height );
      for( Rectangle rect : rects ) {
         gr.fillRect( rect.x, rect.y, rect.width, rect.height );
      }
      if( thereIsNow ) {
         if( isLaser ) {
            gr.setColor( Color.yellow );
         }
         else {
            gr.setColor( Color.red );
         }
         gr.fillRect( aux.x, aux.y, aux.width, aux.height );
      }
   }

   void deleteRect( Rectangle rec ) {
      rects.remove( rec );
   }

   ArrayList<Rectangle> getRectangles() {
      return rects;
   }

   Rectangle getShip() {
      return ship;
   }

   Rectangle getAux() {
      return aux;
   }

   void setThereIsNow( boolean bool ) {
      thereIsNow = bool;
   }
}

PS:附言:把图片替换成矩形,因为这会影响动画代码,你需要对它进行调整,以使它能够与 gif 一起工作吗?

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章