Search code examples
javakeylistener

Moving two rectangles at the same time with different keys Java


Trying to moving two rectangles at the same time with different keys. Using KeyListener. I'm doing Pong Game in Java and have some troubles with this. If I try to move the first paddle, the second will not moving while I'm moving the first. Help me please with this problem. Maybe it will be fixed with multithreading?

Main class:

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

Frame class:

import javax.swing.*;
public class Frame extends JFrame{
    private final int WINDOW_WIDTH = 1200;
    private final int WINDOW_HEIGHT = 800;
    private final String TITLE = "Pong";
    Frame() {
        setTitle(TITLE);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
        setTitle(TITLE);
        setLocationRelativeTo(null);
        setResizable(false);
        PaintPanel paintPanel = new PaintPanel();
        paintPanel.setFocusable(true);
        paintPanel.requestFocusInWindow();
        this.add(paintPanel);
        setVisible(true);
    }
}

Paint class:

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

class PaintPanel extends JPanel implements KeyListener {

    // holds the panel's insets
    Insets ins;
    private int RACKET_ONE_Y = 360;
    private final int RACKET_ONE_X = 160;
    private int RACKET_TWO_Y = 360;
    private final int RACKET_TWO_X = 1025;
    private final int SPEED = 50;
    private final int LOWEST_RACKET_POS = 60;
    private final int HIGHEST_RACKET_POS = 600;
    // Construct a panel.
    PaintPanel() {
        setBackground(Color.BLACK);
        addKeyListener(this);
    }
    // Override the paintComponent() method.
    protected void paintComponent(Graphics g) {
        // Always call the superclass method first.
        super.paintComponent(g);
        drawBorders(g);
        drawMiddleLine(g);
        drawRacketOne(g);
        drawRacketTwo(g);

    }
    // drawing rackets
    private void drawRacketOne(Graphics g){
        g.setColor(Color.RED);
        g.fillRect(RACKET_ONE_X, RACKET_ONE_Y, 15, 90);
    }
    private void drawRacketTwo(Graphics g){
        g.setColor(Color.RED);
        g.fillRect(RACKET_TWO_X, RACKET_TWO_Y, 15, 90);
    }
    // game frame borders
    private void drawBorders(Graphics g){
        g.setColor(Color.WHITE);
        g.fillRect(100, 50, 1000, 10);
        g.fillRect(100, 50, 10, 660);
        g.fillRect(100, 700, 1000, 10);
        g.fillRect(1090, 50, 10, 660);
    }
    // middle line
    private void drawMiddleLine(Graphics g){
        g.setColor(Color.WHITE);
        for (int i = 70; i < 672; i += 40) {
            g.fillRect(590, i, 10, 25);
        }
    }
    // moving rackets
    private void racketOneMoveUp(KeyEvent e){
        int key = e.getKeyCode();
        if (key == KeyEvent.VK_W) {
            if (RACKET_ONE_Y > LOWEST_RACKET_POS) {
                RACKET_ONE_Y -= SPEED;
            }
        }
    }
    private void racketOneMoveDown(KeyEvent e){
        int key = e.getKeyCode();
        if (key == KeyEvent.VK_S) {
            if (RACKET_ONE_Y < HIGHEST_RACKET_POS) {
                RACKET_ONE_Y += SPEED;
            }
        }
    }
    private void racketTwoMoveUp(KeyEvent e){
        int key = e.getKeyCode();
        if (key == KeyEvent.VK_O) {
            if (RACKET_TWO_Y > LOWEST_RACKET_POS) {
                RACKET_TWO_Y -= SPEED;
            }
        }
    }
    private void racketTwoMoveDown(KeyEvent e){
        int key = e.getKeyCode();
        if (key == KeyEvent.VK_L) {
            if (RACKET_TWO_Y < HIGHEST_RACKET_POS) {
                RACKET_TWO_Y += SPEED;
            }
        }
    }
    @Override
    public void keyTyped(KeyEvent e) {
    }
    @Override
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        switch (key) {
            case KeyEvent.VK_W:
                racketOneMoveUp(e);
                break;
            case KeyEvent.VK_S:
                racketOneMoveDown(e);
                break;
            case KeyEvent.VK_O:
                racketTwoMoveUp(e);
                break;
            case KeyEvent.VK_L:
                racketTwoMoveDown(e);
                break;
        }
        repaint();
    }
    @Override
    public void keyReleased(KeyEvent e) {

    }
}

Solution

  • I reorganized your code to fit in a single file (easier to debug that way). I do not see the problem you are talking about as I am able to move both paddles at the same time.

    Changes made.

    • invoke via SwingUtilties.
    • override getPreferredSize() in PaintPanel class
    • set the size via getPreferredSize in the panel gives you a true size less the frame border thicknesses.
    • pack the frame before setting to center
    • made a MyKeyListener class that extends KeyAdapter - adapter classes have default empty methods so you don't have to explicitly add them.
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Insets;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.WindowConstants;
    
    public class Pong {
        
        private final String TITLE = "Pong";
        
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> new Pong().start());
        }
        
        public void start() {
            JFrame frame = new JFrame(TITLE);
            PaintPanel paintPanel = new PaintPanel();
            frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            
            frame.setTitle(TITLE);
            frame.setResizable(false);
            paintPanel.setFocusable(true);
            paintPanel.requestFocusInWindow();
            frame.add(paintPanel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
        
    }
    
    class PaintPanel extends JPanel {
        
        // holds the panel's insets
        Insets ins;
        private int RACKET_ONE_Y = 360;
        private final int RACKET_ONE_X = 160;
        private int RACKET_TWO_Y = 360;
        private final int RACKET_TWO_X = 1025;
        private final int SPEED = 2;
        private final int LOWEST_RACKET_POS = 60;
        private final int HIGHEST_RACKET_POS = 600;
        private final int WINDOW_WIDTH = 1200;
        private final int WINDOW_HEIGHT = 800;
        private Map<String, Runnable> moves = new HashMap<>();
        
        // Construct a panel.
        PaintPanel() {
            setBackground(Color.BLACK);
            addKeyListener(new MyKeyListener());
        }
        
        // Override the paintComponent() method.
        protected void paintComponent(Graphics g) {
            // Always call the superclass method first.
            super.paintComponent(g);
            drawBorders(g);
            drawMiddleLine(g);
            drawRacketOne(g);
            drawRacketTwo(g);
            for (Runnable moveit : moves.values()) {
                moveit.run();
            }
        }
        
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(WINDOW_WIDTH, WINDOW_HEIGHT);
        }
        
        // drawing rackets
        private void drawRacketOne(Graphics g) {
            g.setColor(Color.RED);
            g.fillRect(RACKET_ONE_X, RACKET_ONE_Y, 15, 90);
        }
        
        private void drawRacketTwo(Graphics g) {
            g.setColor(Color.RED);
            g.fillRect(RACKET_TWO_X, RACKET_TWO_Y, 15, 90);
        }
        
        // game frame borders
        private void drawBorders(Graphics g) {
            g.setColor(Color.WHITE);
            g.fillRect(100, 50, 1000, 10);
            g.fillRect(100, 50, 10, 660);
            g.fillRect(100, 700, 1000, 10);
            g.fillRect(1090, 50, 10, 660);
        }
        
        // middle line
        private void drawMiddleLine(Graphics g) {
            g.setColor(Color.WHITE);
            for (int i = 70; i < 672; i += 40) {
                g.fillRect(590, i, 10, 25);
            }
        }
        
        // moving rackets
        private void racketOneMoveUp(KeyEvent e) {
            int key = e.getKeyCode();
            if (key == KeyEvent.VK_W) {
                if (RACKET_ONE_Y > LOWEST_RACKET_POS) {
                    RACKET_ONE_Y -= SPEED;
                }
            }
        }
        
        private void racketOneMoveDown(KeyEvent e) {
            int key = e.getKeyCode();
            if (key == KeyEvent.VK_S) {
                if (RACKET_ONE_Y < HIGHEST_RACKET_POS) {
                    RACKET_ONE_Y += SPEED;
                }
            }
        }
        
        private void racketTwoMoveUp(KeyEvent e) {
            int key = e.getKeyCode();
            if (key == KeyEvent.VK_O) {
                if (RACKET_TWO_Y > LOWEST_RACKET_POS) {
                    RACKET_TWO_Y -= SPEED;
                }
            }
        }
        
        private void racketTwoMoveDown(KeyEvent e) {
            int key = e.getKeyCode();
            if (key == KeyEvent.VK_L) {
                if (RACKET_TWO_Y < HIGHEST_RACKET_POS) {
                    RACKET_TWO_Y += SPEED;
                }
            }
        }
        
        private class MyKeyListener extends KeyAdapter {
            
            public void keyPressed(KeyEvent e) {
                String ch =
                        Character.toString(e.getKeyChar()).toUpperCase();
                if (!moves.containsKey(ch)) {
                
                    int key = e.getKeyCode();
                    switch (key) {
                        case KeyEvent.VK_W:
                            moves.put("W",
                                    () -> racketOneMoveUp(e));
                            moves.remove("S");
    //                  racketOneMoveUp(e);
                            break;
                        case KeyEvent.VK_S:
                            moves.put("S",
                                    () -> racketOneMoveDown(e));
                            moves.remove("W");
    //                  racketOneMoveDown(e);
                            break;
                        case KeyEvent.VK_O:
                            moves.put("O",
                                    () -> racketTwoMoveUp(e));
                            moves.remove("L");
    //                  racketTwoMoveUp(e);
                            break;
                        case KeyEvent.VK_L:
                            moves.put("L",
                                    () -> racketTwoMoveDown(e));
                            moves.remove("O");
    //                  racketTwoMoveDown(e);
                            break;
                    }
                }
                repaint();
            }
        }
        
    }