【问题标题】:Object fly away after collision物体碰撞后飞走
【发布时间】:2021-05-03 19:51:32
【问题描述】:

明天我在碰撞方面寻求帮助。我有很好的建议,碰撞检测有效,但是在什么物体碰撞之后,他真的飞到了屏幕外的任何地方。我想这是因为我没有打电话给@ Action 中的 987654325@ 方法在动画中执行,但是我为碰撞绘制的矩形与 gif 分割为 Jlabel 我设置为 Icon.T My question about collision

Pac-Man before collision after collision,Pac-Man just fly away

   import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;

public class Hra extends JFrame implements ActionListener   {
     static   ArrayList<Body> bodiky = new ArrayList<Body>(50);
    Rectangle platforma;
    Rectangle packRect;
    Rectangle ghostRect;
    Timer timer;
     
    private JPanel contentPane;
    static  Body body ;
    static JLabel gifLabel = new JLabel(new ImageIcon("C:\\Users\\petrb\\Downloads\\packmanGifRes.gif"));

    JLabel lblNewLabel;
    private  Color bodyCol = Color.white;
    private Color packCol = Color.YELLOW; 
    static PackMan packman; 
    private int xRychlost =1;
    private int yRychlost = 1;
    static int count = 0;
    static Duch duch;
    
  
    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        
                 Hra frame = new Hra();
                    frame.setVisible(true);
                    frame.getContentPane().add(gifLabel);
                    gifLabel.setLocation(packman.getSouradniceX(), packman.getSouradniceY()-38);
                
                    
    }
    

    /**
     * Create the frame.
     */
    public Hra() {
    
        packman = new PackMan(0, 900, 800, packCol);
        packRect = new Rectangle(packman.getSouradniceX(), packman.getSouradniceY(),50, 70);
    
        ghostRect = new Rectangle(800,800,50,70);   
        platforma = new Rectangle(0, 120, 50, 800);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        getContentPane().setBackground(Color.gray);
        timer = new Timer(0,this);
        timer.start();
         lblNewLabel = new JLabel("Score:");
        
        
        
        
        GroupLayout gl_contentPane = new GroupLayout(contentPane);
        gl_contentPane.setHorizontalGroup(
            gl_contentPane.createParallelGroup(Alignment.LEADING)
                .addGroup(gl_contentPane.createSequentialGroup()
                    .addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING)
                        .addGroup(gl_contentPane.createSequentialGroup()
                            .addContainerGap()
                            .addComponent(lblNewLabel, GroupLayout.PREFERRED_SIZE, 107, GroupLayout.PREFERRED_SIZE))
                        .addGroup(gl_contentPane.createSequentialGroup()
                            .addGap(154)
                            .addComponent(gifLabel, GroupLayout.PREFERRED_SIZE, 45, GroupLayout.PREFERRED_SIZE)))
                    .addContainerGap(227, Short.MAX_VALUE))
        );
        gl_contentPane.setVerticalGroup(
            gl_contentPane.createParallelGroup(Alignment.LEADING)
                .addGroup(gl_contentPane.createSequentialGroup()
                    .addComponent(lblNewLabel, GroupLayout.PREFERRED_SIZE, 24, GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(ComponentPlacement.RELATED, 143, Short.MAX_VALUE)
                    .addComponent(gifLabel)
                    .addGap(73))
        );
        contentPane.setLayout(gl_contentPane);
        
        this.addKeyListener(new KeyListener() {
            
            @Override
            public void keyTyped(KeyEvent e) {
                // TODO Auto-generated method stub
                
            }
            
            @Override
            public void keyReleased(KeyEvent e) {
                // TODO Auto-generated method stub
                switch(e.getKeyCode()) {
                case 37: //doleva
            //      packman.setSouradniceX(packman.getSouradniceX()-20);
            //      gifLabel.setLocation(gifLabel.getX()-20, gifLabel.getY());
                    repaint();
                    count = 1;
                   
                    
                    break;
                case 38: //nahorů
            //      packman.setSouradniceY(packman.getSouradniceY()-20);
            //      gifLabel.setLocation(gifLabel.getX(), gifLabel.getY()-20);                  
                    repaint();
                    count = 2;
        //          zkontrolujKolizi();
                    break;
                case 39://doprava
             //         packman.setSouradniceX(packman.getSouradniceX()+20);
               //       gifLabel.setLocation(gifLabel.getX()+20, gifLabel.getY());                      
                    repaint();
                    count = 3;
                //  zkontrolujKolizi();
                    break;
                case 40://dolů
            //      packman.setSouradniceY(packman.getSouradniceY()+20);
            //      gifLabel.setLocation(gifLabel.getX(), gifLabel.getY()+20);
                    count =4;
                            
            //      zkontrolujKolizi();
                    repaint();
                    
                    break;
                }
                
            
            }
            
            @Override
            public void keyPressed(KeyEvent e) {
                // TODO Auto-generated method stub
                System.out.println("hodnota:"+ e.getKeyCode());
                System.out.println("Znak:" + e.getKeyChar());
                
            }
        });
    }
    
    @Override
    public void paint(Graphics g) {
        // TODO Auto-generated method stub
        super.paint(g);
       
        g.drawRect(packRect.x, packRect.y, packRect.height, packRect.width);
        g.setColor(bodyCol);
        
        g.drawRect(ghostRect.x,ghostRect.y,ghostRect.width,ghostRect.height);
        g.setColor(packCol);
        
        g.fillRect(0, 120, 50, 800);
        g.fillRect(40, 858, 200 ,62);
       
        g.drawRect(platforma.x, platforma.y, platforma.width, platforma.height);
        
        
    
        
    }
    
    public boolean zkontrolujKolizi() {     
        return packRect.intersects(ghostRect) || packRect.intersects(platforma) ;
        }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        
        int rollzpetX = packRect.x;
        int rollzpetY = packRect.y;

    switch (count) {
    case 1:
        packman.setSouradniceX(packman.getSouradniceX() - xRychlost);
        gifLabel.setLocation(packman.getSouradniceX(), packman.getSouradniceY()-38);
        
        packRect.x = packRect.x - xRychlost;
    
//      repaint();
        break;

    case 2:
        packman.setSouradniceY(packman.getSouradniceY() - yRychlost);
        gifLabel.setLocation(packman.getSouradniceX(), packman.getSouradniceY()-38);
        packRect.y = packRect.y - yRychlost;
        

        break;
    case 3:
        packman.setSouradniceX(packman.getSouradniceX() + xRychlost);
        gifLabel.setLocation(packman.getSouradniceX(), packman.getSouradniceY()-38);
        packRect.x = packRect.x + xRychlost;
        
        break;
    case 4:
        packman.setSouradniceY(packman.getSouradniceY() + yRychlost);
        gifLabel.setLocation(packman.getSouradniceX(), packman.getSouradniceY()-38);
        packRect.y  = packRect.y+yRychlost; 
        
    
        break;
    }
  
   
    if (zkontrolujKolizi()) {
        packRect.x = rollzpetX;
        packRect.y = rollzpetY;
        
        
    }else {
        repaint();
    }
       
    }
}

//吃豆人类

   import java.awt.Color;    
   import java.util.ArrayList;



public class PackMan {

private double skore;
private int souradniceX;
private int souradniceY;
private Color color;

public double getSkore() {
    return skore;
}
public void setSkore(double skore) {
    this.skore = skore;
}

public int getSouradniceX() {
    return souradniceX;
}
public void setSouradniceX(int souradniceX) {
    this.souradniceX = souradniceX;
}
public int getSouradniceY() {
    return souradniceY;
}
public void setSouradniceY(int souradniceY) {
    this.souradniceY = souradniceY;
}
public PackMan(int skore, int souradniceX, int souradniceY,Color color) {
    super();
    this.skore = skore;
    this.souradniceX = souradniceX;
    this.souradniceY = souradniceY;
    this.color = color;


    
}


public Color getColor() {
    return color;
}
public void setColor(Color color) {
    this.color = color;
}



}

//吃豆人类

import java.awt.Color;    
import java.lang.reflect.Array;
import java.util.ArrayList;
public class Body {

private int bodyX;
private int bodyY;
private double hodnotaBodu;
private Color color;
public int getBodyX() {
    return bodyX;
}
public Body(int bodyX, int bodyY, double hodnotaBodu,Color color) {
    super();
    this.bodyX = bodyX;
    this.bodyY = bodyY;
    this.hodnotaBodu = hodnotaBodu;
    this.color = color;

}
public Color getColor() {
    return color;
}
public void setColor(Color color) {
    this.color = color;
}
public void setBodyX(int bodyX) {
    this.bodyX = bodyX;
}
public int getBodyY() {
    return bodyY;
}
public void setBodyY(int bodyY) {
    this.bodyY = bodyY;
}
public double getHodnotaBodu() {
    return hodnotaBodu;
}
public void setHodnotaBodu(double hodnotaBodu) {
    this.hodnotaBodu = hodnotaBodu;
}

}

【问题讨论】:

  • 考虑提供minimal reproducible example 以吸引更好的回复
  • 我已经粘贴了我知道有问题的部分。我已经在碰撞之前和之后设置了坐标。但是 pacman 仍然能够穿墙
  • “我已经粘贴了我知道有问题的部分。” 但是您还没有粘贴让我可以轻松编译和运行代码的部分,并且查看我可能尝试的任何更改的结果,以使其正常工作。嗯,NVM。对我来说,这纯粹是学术性的..
  • 如果它是更大的项目怎么办?我已经阅读了最小的可重现示例。所以我希望我做对了。好吧,我会发布我所有的代码,但是代码不是英文有关系吗?
  • "如果它是更大的项目怎么办?" 不要将更大的项目和手头的问题混淆,即"物体在碰撞后飞走" 。我们不需要也不想要“项目”。我们确实鼓励人们发布我们在屏幕上实际看到问题所需的最小/短代码(包括导入、类结构、main 方法等)。就我而言,我通常无法仔细查看代码,直到它在我的 IDE 中编译并格式化,因为我习惯于看到格式化的代码。 提示: 添加@MadProgrammer(或@ 很重要的任何人)以通知此人有新评论。

标签: java swing 2d collision-detection collision


【解决方案1】:

好的,你的代码是不可编译的,所以很难理解它或看到它们是如何联系在一起的。

我将尝试回答一些间接问题,而不是尝试回答您的直接问题。

您的基本代码存在许多问题,从长远来看这些问题会再次困扰您。

绘画

一般来说,您应该避免覆盖paint,尤其是像JFrame 这样的顶级组件。顶级组件不是双缓冲的,因此在快速绘制时最终会出现闪烁。 JFrame 是一个复合组件,也就是说,它实际上是由许多其他组件组成的。如果您覆盖 paintJFrame,则您将面临子组件在您正在绘制的内容之上绘制的风险。

JFrame 还包括窗饰。也就是说,可用空间的大小是框架的大小,减去它的装饰。计算装饰插图并不容易,有更好的方法可以避免这个问题。

详情请见How to get the EXACT middle of a screen, even when re-sized

输入

KeyListener 通常也是监控键盘输入的不好选择,主要是因为它存在焦点相关问题并且可能有点抽搐。更好的解决方案是使用key bindings API,它可以让您更好地控制决定在什么条件下激活密钥。

博弈论

在大多数游戏中,您都希望有一个“主”或“游戏”循环。这是一组重复的指令,以(大部分)定期间隔运行。

它负责获取输入、更新状态(碰撞/分数/等)、调度重绘,并且在更高级的场景中,根据所需的帧速率算法调度循环的下一次运行。

在您的情况下,您使用的是 Swing Timer,但根据之前的一些实验,我发现大约 5 毫秒是您可以可靠获得的最小间隔。

但问题是,您正在更新状态,安排重绘并在整个地方做很多其他事情。

相反,您需要将所有更新都集中在“主”循环中,这是键绑定之类的真正有用的地方。

您无需在输入事件发生时立即更新状态,您只需更新输入的状态标志(开/关),然后让主循环在其下一个周期更新状态。

可运行示例

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class Test {

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

    public Test() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setVisible(true);
            }
        });
    }

    public static class TestPane extends JPanel {

        protected static int MOVEMENT_DELTA = 1;

        private Set<Input> inputManager = new TreeSet<>();

        private Timer timer;

        private Rectangle player = new Rectangle(245, 245, 10, 10);

        private List<Rectangle> mapComponents = new ArrayList<>(25);

        public TestPane() {
            ActionMap actionMap = getActionMap();
            actionMap.put("Up.pressed", new InputAction(Input.UP, true, inputManager));
            actionMap.put("Up.released", new InputAction(Input.UP, false, inputManager));
            actionMap.put("Down.pressed", new InputAction(Input.DOWN, true, inputManager));
            actionMap.put("Down.released", new InputAction(Input.DOWN, false, inputManager));
            actionMap.put("Left.pressed", new InputAction(Input.LEFT, true, inputManager));
            actionMap.put("Left.released", new InputAction(Input.LEFT, false, inputManager));
            actionMap.put("Right.pressed", new InputAction(Input.RIGHT, true, inputManager));
            actionMap.put("Right.released", new InputAction(Input.RIGHT, false, inputManager));

            InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "Up.pressed");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "Up.released");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "Down.pressed");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "Down.released");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "Left.pressed");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "Left.released");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "Right.pressed");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "Right.released");

            timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent evt) {
                    int x = player.x;
                    int y = player.y;
                    if (inputManager.contains(Input.UP)) {
                        y -= MOVEMENT_DELTA;
                    }
                    if (inputManager.contains(Input.DOWN)) {
                        y += MOVEMENT_DELTA;
                    }
                    if (inputManager.contains(Input.LEFT)) {
                        x -= MOVEMENT_DELTA;
                    }
                    if (inputManager.contains(Input.RIGHT)) {
                        x += MOVEMENT_DELTA;
                    }

                    // Screen bounds check
                    if (x < 0) {
                        x = 0;
                    } else if (x + player.width > getWidth()) {
                        x = getWidth() - player.width;
                    }

                    if (y < 0) {
                        y = 0;
                    } else if (y + player.height > getHeight()) {
                        y = getHeight() - player.height;
                    }

                    int originX = player.x;
                    int originY = player.y;

                    player.setLocation(x, y);

                    for (Rectangle component : mapComponents) {
                        if (player.intersects(component)) {
                            x = originX;
                            y = originY;
                            break;
                        }
                    }

                    player.setLocation(x, y);

                    repaint();
                }
            });

            mapComponents.add(new Rectangle(250 - (150 / 2), 150, 150, 1));
            mapComponents.add(new Rectangle(250 - (150 / 2), 350, 150, 1));

            mapComponents.add(new Rectangle(150, 250 - (150 / 2), 1, 150));
            mapComponents.add(new Rectangle(350, 250 - (150 / 2), 1, 150));
        }

        @Override
        public void addNotify() {
            super.addNotify();
            timer.start();
        }

        @Override
        public void removeNotify() {
            super.removeNotify();
            timer.stop();
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            g2d.setColor(Color.DARK_GRAY);
            for (Rectangle map : mapComponents) {
                g2d.fill(map);
            }

            g2d.setColor(Color.RED);
            g2d.fill(player);
            g2d.dispose();
        }

    }

    public enum Input {
        UP, DOWN, LEFT, RIGHT
    }

    public static class InputAction extends AbstractAction {

        private Input input;
        private boolean activated;
        private Set<Input> manager;

        public InputAction(Input input, boolean activated, Set<Input> manager) {
            this.input = input;
            this.activated = activated;
            this.manager = manager;
        }

        @Override
        public void actionPerformed(ActionEvent evt) {
            if (activated) {
                manager.add(input);
            } else {
                manager.remove(input);
            }
        }

    }
}

【讨论】:

  • 你的代码看起来很专业。谢谢你的提示
  • 我已经编辑了我的问题,现在你应该可以编译我的代码了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
  • 2013-12-24
  • 1970-01-01
  • 2023-03-15
相关资源
最近更新 更多