javaswingjframejpanelpaintcomponent

Java - Multiple Panels in JFrame


I'm developing a hide and seek game for a school project, where two players move using the keyboard and if the hunter touches the survivor, the game is over. My initial approach is for each player to be a panel that moves in a frame. The code is working for a single player moving, and I would like to know how it would be possible to adapt the GameManager for two players. I tried changing the layout of the frame and just adding the players but didn't worked at all. I don't have much experience with GUI in Java, so I don't have many ideas of what to do here.

Here is the code of the project:

class GameManager extends JFrame {

    private Player player;
    public GameManager() {

        setTitle("Hide and Seek");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setExtendedState(JFrame.MAXIMIZED_BOTH);
        setResizable(true);
        player = new Player(0, 0, 50, 50, 'H');

        add(player);
        setVisible(true);

        addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                int keyCode = e.getKeyCode();
                player.move(keyCode);
            }
            public void keyReleased(KeyEvent e) {
                int keyCode = e.getKeyCode();
                player.stop(keyCode);
            }
        });

    }
}

abstract class GameObject extends JPanel {

    protected int x;
    protected int y;

    protected int width;
    protected int height;

    protected Image image;

    public GameObject(int x, int y, int width, int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(image, x, y, width, height, null);
    }

}
class Player extends GameObject {

    // Attributes
        ...
    //

    public Player ( int x, int y, int width, int height, char type) {

        super(x, y, width, height);
        
        String spritesSurvivor[] = {"src/char1.gif", "src/char2.gif", "src/charRun1.gif", "src/charRun2.gif", "src/dead.gif"};
        String spritesHunter[] = {"src/hunter1.gif", "src/hunter2.gif", "src/hunterRun1.gif", "src/hunterRun2.gif", "src/dead.gif"};
        
        if(type=='S'){
            sprites = spritesSurvivor;
            speed = 10;
        }
        else if(type=='H'){
            sprites = spritesHunter;
            speed = 15;
        }

        directionX = 'R';
        changeSprite();

    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(image, x, y, width, height, null);
    }

    public void move(int keyCode) {

        // switch for keycode to update which direction to move  
        ...

        checkBounds();
        changeSprite();
        repaint();
        
    }

    public void stop(int keyCode){

        // switch for keycode to update which key was released
        ...

        changeSprite();
        repaint();

    }

    private void changeSprite(){
            
        // basically just changes the sprite based on the direction and if the player is walking or not
        ...
    
    }

    private void checkBounds() {

        // checks if the player is inside the screen to prevent it from going out of bounds
        ...

    }
    
}

I tried to change the layout to null to define the position of the panels manually, but both panels ended up disappearing from the frame.


Solution

  • Ok, so basically, I changed the class GameObject so it extends JLabel instead of JPanel, and updated its methods and attributes to handle ImageIcon instead of Image. At the end GameManager looks like this:

    class GameManager extends JFrame {
    
         private Player player;
         private Player player2;
    
         public GameManager() {
    
             setTitle("Hide and Seek");
             setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
             setExtendedState(JFrame.MAXIMIZED_BOTH);
             setLocationRelativeTo(null);
             setResizable(true);
             setFocusable(true);
             setLayout(null);
    
             player = new Player(0, 0, 50, 50, 'S');
             player2 = new Player(100, 100, 60, 60, 'H');
    
             add(player);
             add(player2);
    
             setVisible(true);
    
             addKeyListener(new KeyAdapter() {
                 public void keyPressed(KeyEvent e) {
                     int keyCode = e.getKeyCode();
                     player.move(keyCode);
                     player2.move(keyCode);
                 }
                 public void keyReleased(KeyEvent e) {
                     int keyCode = e.getKeyCode();
                     player.stop(keyCode);
                     player2.stop(keyCode);
                 }
             });
    
         }
    }
    

    Now I'll be working with the collision handler, game timer and scores!