如果它越过框架的边界,则反转运动

Reverse the motion if its crosses the borders of the frame

我正在开发的程序应该使矩形从上到下移动然后从左到右一旦矩形穿过框架的边界它应该从右到左和从下到上反转它的运动。 我设法用一个简单的 if 语句完成了第一部分,但我不知道如何反转它。

import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;

public class RectangleAnimation extends JFrame {

        private static final int FRAME_WIDTH = 800; 
        private static final int FRAME_HEIGHT = 800; 

        public RectangleAnimation() {

        setLayout(new BorderLayout( ));     
        setSize(FRAME_WIDTH, FRAME_HEIGHT); 
        setTitle("Rectangle Animation 2D");
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    
    
        PanelRectangleAnimation panel = new PanelRectangleAnimation();
        add(panel, BorderLayout.CENTER); 
        
        pack();
        setVisible(true);
    }

    public static void main(String[] args) {        
        
        new RectangleAnimation();           
    }

}

class PanelRectangleAnimation extends JPanel implements Runnable {

    private static final int PANEL_WIDTH = 400;
    private static final int PANEL_HEIGHT = 400;
    private static final int RW = 60;
    private static final int RH = 40;
        
    int x, y;
    
    Rectangle2D.Double rec;
    
    Thread mythread;

    public PanelRectangleAnimation() {
        setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
        this.setBackground(Color.white);

        mythread = new Thread(this);
        mythread.start();
    }

    public void run() {
        
        // animation loop
        boolean flag = true;
        while (flag) {
            try{
                Thread.sleep(10);
            }
            catch(InterruptedException e){}
            if(y == 355){
                    x = x + 5;
                }else{
                    y = y + 5;
                }

            if ( x > PANEL_WIDTH || y > PANEL_HEIGHT) {
                x = 0;
                y = 0;
            }                       
            repaint();
        }        
        
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;        
         
        g2.setColor(Color.red);             
        rec = new Rectangle2D.Double(x, y, RW, RH);     
        g2.fill(rec);       
    }
}

因此,您的基本问题可以描述为基本的“碰撞检测”问题。

基本概念是,如果框的一个边缘超出了可视区域,你想反转delta,例如...

box += delta;
if box > viewable_width {
    box = viewable_width
    delta *= -1; // reverse delta
}

现在,您还需要检查 left/top 边缘(即 < 0),但基本思想是相同的。

Swing 也不是线程安全的并且是单线程的。这意味着您不应该从事件调度线程的上下文之外对 UI 或 UI 依赖的任何状态进行更改,并且您不应该执行任何长时间的 running/blocking 事件调度线程上下文中的操作。

请参阅 Concurrency in Swing for more details and How to Use Swing Timers 以获得 possible/common 解决方案

例如...

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private Timer timer;
        private Rectangle box = new Rectangle(0, 0, 64, 40);

        public TestPane() {
            timer = new Timer(5, new ActionListener() {

                private int xDelta = 1;
                private int yDelta = 1;

                @Override
                public void actionPerformed(ActionEvent e) {
                    box.x += xDelta;
                    box.y += yDelta;

                    if (box.x + box.width > getWidth()) {
                        box.x = getWidth() - box.width;
                        xDelta *= -1;
                    } else if (box.x < 0) {
                        box.x = 0;
                        xDelta *= -1;
                    }
                    if (box.y + box.height > getHeight()) {
                        box.y = getHeight() - box.height;
                        yDelta *= -1;
                    } else if (box.y < 0) {
                        box.y = 0;
                        yDelta *= -1;
                    }
                    repaint();
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(800, 400);
        }

        @Override
        public void addNotify() {
            super.addNotify();
            if (timer == null) {
                return;
            }
            timer.start();
        }

        @Override
        public void removeNotify() {
            super.removeNotify();
            if (timer == null) {
                return;
            }
            timer.stop();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.RED);
            g2d.fill(box);
            g2d.dispose();
        }

    }
}