0

Tommorow I've asked for help with collision.I've got good advice,collision detection works,but after what object collide he literally fly to nowhere-off the screen.I thought It was because I didn't call repaint() method in ActionPerformed in animation,but Rectangle I've draw for collision split up with gif as Jlabel I setted as 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();
    }
       
    }
}

//Pacman class

   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;
}



}

//Pacman class

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;
}

}
PeteJerk
  • 14
  • 2
  • 1
    Consider providing a [mcve] in order to attract better responses – MadProgrammer May 03 '21 at 21:16
  • I've pasted part where I know that there is problem.I've setted coordinates before collision and after.But pacman is still able to going through the wall – PeteJerk May 04 '21 at 09:55
  • *"I've pasted part where I know that there is problem."* But you haven't pasted the parts that allow me to easily compile & run the code, and see the result of any changes I might try, to make it work. Well, NVM. For me it is purely academic.. – Andrew Thompson May 04 '21 at 10:11
  • What if is it larger project?I've read minimal reproducible example.So I hoped I did right.Ok,I will post all my code,but does it matter that the code is not in English? – PeteJerk May 04 '21 at 10:16
  • *"What if is it larger project?"* Don't get confused between the larger project and the problem at hand, namely *"Object fly away after collision"*. We don't need or want 'the project'. We **do** encourage people to post the minimal / short code (including imports, class structure, `main` method etc.) needed for us to actually see the problem on-screen. For my part, I usually cannot look at code carefully until it is compiled in my IDE and formatted as I am used to seeing code formatted. **Tip:** Add @MadProgrammer (or whoever, the `@` is important) to *notify* the person of a new comment. – Andrew Thompson May 04 '21 at 10:26
  • @AndrewThompson Ok,I posted it as answer.I hope I helped you,but I think problem will be with images – PeteJerk May 04 '21 at 10:39
  • *"Ok,I posted it as answer."* It is not an answer. I was going to suggest to make an [edit] to the question to add it, but it is also not a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). There are missing classes, it has over 338 lines of code - which is pushing it for minimal / short, even if all the code is actually necessary. Which leads me to. It's not. There are a number of images referenced that don't need to be in a problem about colliding shapes. See [Collision detection with complex shapes](http://stackoverflow.com/a/14575043/418556) for tips. .. – Andrew Thompson May 04 '21 at 10:47
  • On both collisions of shapes ***and*** code that is an MRE / SSCCE. The code seen there is less than 140 lines of code, animated, using best coding practices - and it can be copy/pasted, compiled and run, **easily.** That example is about all the help I can offer until there is an MRE/SSCCE edited into the question. – Andrew Thompson May 04 '21 at 10:50
  • @AndrewThompson Is it better now? – PeteJerk May 04 '21 at 11:01
  • *"Is it better now?"* Before I do anything with that code, I'd like you to create a new project in your IDE to test it yourself. Copy/paste the code as seen above into classes in the project, compile it, run it and check you can see the problem. **Can you?** If not, it's not an MRE / SSCCE. Note that 'better / worse' is not important to me. The thing that *is* important, is: Is it code we can easily work with, like the answer by @MadProgrammer, below? You've tried that code, right? – Andrew Thompson May 04 '21 at 11:09
  • @AndrewThompson I know what you mean by compiling cody from MadProgrammer.I edited and I if I made four different classe(PacMan,Body,Duch and Hra),the problem should be seen – PeteJerk May 04 '21 at 11:32

1 Answers1

1

Okay, you code isn't compilable so it's difficult to make any sense of it or see how it all hangs together.

Instead of trying to answer your direct question, I'm going to try and answer some of the indirect questions.

Your base code has a number of issues which are going to come back to haunt you in the long run.

Painting

In general, you should avoid override paint and especially of top level components like JFrame. Top level components aren't double buffered, so you'll end up with flickering when painting fast. JFrame is a composite component, that is, it's actually made up of a number of other components. If your override paint of the JFrame you run the risk of the child components painting over the top of what you're painting.

JFrame also includes the window decorations. That is, the size of the available space is the size of the frame, minus it's decorations. Calculating the decorations insets is not easy and there are better ways to avoid the issue.

See How to get the EXACT middle of a screen, even when re-sized for more details

Input

KeyListener is also, generally, a bad choice for monitoring key board input, mostly because it suffers from focus related issues and can be a little twitchy. A better solution would be to make use of the key bindings API which gives you more control over deciding under what conditions the key would activate.

Game theory

In most games, you want to have a "main" or "game" loop. This is a repeating set of instructions which run at a (mostly) regular interval.

It's responsible for taking the input, updating the state (collision/score/etc), scheduling the repaint and, in more advanced scenarios, scheduling the next run of the loop based a desired frame rate algorithm.

In your case, you are using a Swing Timer, but, based on some previous experimentation, I find that about 5 milliseconds is about the smallest interval you can reliably get.

The problem is though, you're updating the state, scheduling repaints and doing a bunch of other things all over the place.

Instead, you need to focus all your updates into the "main" loop, this is where things like key bindings can really help.

Instead of relying on updating the state immediately when a input event occurs, you simply update a state flag for the input (on/off) and let the main loop update the state on it's next cycle.

Runnable example

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);
            }
        }

    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366