1

I am trying to make a game in Java and this is my first time dealing with multithreading (well, asides from playing music concurrently via the Clip class.) I have a Canvas class which extends JPanel, but within the Canvas class I also have a KeyListener to take input, shown here:

private class myKeyListener implements KeyListener
{
    public void keyPressed(KeyEvent keyEvent)
    {
        if(keyEvent.getKeyCode() == KeyEvent.VK_ESCAPE){System.exit (0);}

        Thread thread3 = new Thread() 
            {
                public void run() {
                    if(keyEvent.getKeyCode() == KeyEvent.VK_RIGHT){moveX(5, player1);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_LEFT){moveX(-5, player1);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_UP){moveY(-5, player1);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_DOWN){moveY (5, player1);}
                }
            };

        Thread thread4 = new Thread() 
            {
                public void run() {
                    if(keyEvent.getKeyCode() == KeyEvent.VK_D){moveX(5, player2);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_A){moveX(-5, player2);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_W){moveY(-5, player2);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_S){ moveY(5, player2);}
                }
            };

        Thread thread5 = new Thread() 
            {
                public void run() {
                    repaint();
                }
            };

        thread3.start();
        thread4.start();
        thread5.start();

        try{
            thread3.join();
            thread4.join();
            thread5.join();
        }
        catch (Exception e){System.out.println(e);}

        repaint();
    }

    public void keyReleased(KeyEvent keyEvent)
    {

    }

    public void keyTyped(KeyEvent keyEvent)
    {
    }
}

My goal is to have it so that one can move both players (which are Rectangles) at the same time on the canvas. Currently, one can only move them one at a time, but never both at the same time. This is my first time dealing with multithreading so I apologize in advance if I am making a rookie mistake.

ADC2000
  • 63
  • 7
  • I didn't understand exactly what you want to do. You won't be able to move both players at the same time with this code because you can't press two keys at the same time. Each time you press a key, the method keyPressed() will be called once. – Daniel Barral May 11 '16 at 01:24
  • Did you mean two people using the same keyboard, each one controlling one player? – Daniel Barral May 11 '16 at 01:26
  • @Daniel Yes, I did. So for example, on the same keyboard one person will be using the arrow keys to control the Rectangle player1, and the other person will be using WASD to control the Rectangle player2 – ADC2000 May 11 '16 at 01:29
  • There is no need to use one thread to move each player. I woul'd recommend you use one thread to do the game loop (update player positions and then update the screen). Can you post the complete code, so I can help? This code don't compile. – Daniel Barral May 11 '16 at 01:44
  • @Daniel I have posted it as an answer below because the code is too long to put into a comment – ADC2000 May 11 '16 at 01:53

2 Answers2

1

Here is the code.

You need just one thread, to do the "game loop".

import java.awt.*;
import java.awt.event.*;
import javax.swing.JPanel;
import java.util.ArrayList;

public class Canvas2 extends JPanel {
    // attributes
    private Rectangle player1;
    private Rectangle player2;
    private ArrayList<KeyEvent> log;

    private boolean player1left = false;
    private boolean player1right = false;
    private boolean player1up = false;
    private boolean player1down = false;
    private boolean player2left = false;
    private boolean player2right = false;
    private boolean player2up = false;
    private boolean player2down = false;

    // constructor
    public Canvas2() {
        // initialize object
        player1 = new Rectangle(50, 50, 50, 50);
        player2 = new Rectangle(50, 50, 50, 50);

        log = new ArrayList<KeyEvent>();

        // set canavs background colour
        setBackground(Color.white);

        // add the key listener in the constructor of your canavas/panel
        addKeyListener(new myKeyListener());

        // ensure focus is on this canavas/panel for key operations.
        setFocusable(true);

        Thread gameLoop = new Thread() {
            public void run() {
                while (true) {
                    updatePlayers();
                    repaint();
                    pause(10);
                }

            }
        };

        gameLoop.start();

    }

    private void updatePlayers() {
        if (player1left) {
            moveX(-5, player1);
        }
        if (player1right) {
            moveX(5, player1);
        }
        if (player1up) {
            moveY(-5, player1);
        }
        if (player1down) {
            moveY(5, player1);
        }
        if (player2left) {
            moveX(-5, player2);
        }
        if (player2right) {
            moveX(5, player2);
        }
        if (player2up) {
            moveY(-5, player2);
        }
        if (player2down) {
            moveY(5, player2);
        }
    }

    // painting
    public void paintComponent(Graphics graphics) {
        super.paintComponent(graphics);
        Graphics2D graphics2d = (Graphics2D) graphics;

        graphics.setColor(Color.blue);
        graphics2d.fill(player1);
        graphics2d.fill(player2);
    }

    // function which essentially re-creates rectangle with varying x
    // orientations. (x-movement)
    public void moveX(int mutationDistance, Rectangle sampleObject) {
        sampleObject.setBounds(sampleObject.x + mutationDistance,
                sampleObject.y, sampleObject.width, sampleObject.height);
    }

    // function which essentially re-creates rectangle with varying y
    // orientations. (y-movement)
    public void moveY(int mutationDistance, Rectangle sampleObject) {
        sampleObject.setBounds(sampleObject.x, sampleObject.y
                + mutationDistance, sampleObject.width, sampleObject.height);
    }

    // listener
    private class myKeyListener implements KeyListener {
        // implement all the possible actions on keys
        public void keyPressed(final KeyEvent keyEvent) {
            if (keyEvent.getKeyCode() == KeyEvent.VK_ESCAPE) {
                System.exit(0);
            }

            if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) {
                player1right = true;
            }
            if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT) {
                player1left = true;
            }
            if (keyEvent.getKeyCode() == KeyEvent.VK_UP) {
                player1up = true;
            }
            if (keyEvent.getKeyCode() == KeyEvent.VK_DOWN) {
                player1down = true;
            }

            if (keyEvent.getKeyCode() == KeyEvent.VK_D) {
                player2right = true;
            }
            if (keyEvent.getKeyCode() == KeyEvent.VK_A) {
                player2left = true;
            }
            if (keyEvent.getKeyCode() == KeyEvent.VK_W) {
                player2up = true;
            }
            if (keyEvent.getKeyCode() == KeyEvent.VK_S) {
                player2down = true;
            }


        }

        public void keyReleased(KeyEvent keyEvent) {
            if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) {
                player1right = false;
            }
            if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT) {
                player1left = false;
            }
            if (keyEvent.getKeyCode() == KeyEvent.VK_UP) {
                player1up = false;
            }
            if (keyEvent.getKeyCode() == KeyEvent.VK_DOWN) {
                player1down = false;
            }

            if (keyEvent.getKeyCode() == KeyEvent.VK_D) {
                player2right = false;
            }
            if (keyEvent.getKeyCode() == KeyEvent.VK_A) {
                player2left = false;
            }
            if (keyEvent.getKeyCode() == KeyEvent.VK_W) {
                player2up = false;
            }
            if (keyEvent.getKeyCode() == KeyEvent.VK_S) {
                player2down = false;
            }
        }

        public void keyTyped(KeyEvent keyEvent) {
        }
    }

    public static void pause(int secs) {
        try {
            Thread.sleep(secs);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Daniel Barral
  • 3,896
  • 2
  • 35
  • 47
  • Thank you @Daniel . I am experimenting around with KeyBindings now, but this fits my purposes exactly. Thank you. – ADC2000 May 11 '16 at 02:44
0
import java.awt.*;
import java.awt.event.*;
import javax.swing.JPanel;
import java.util.ArrayList;

/**
 * This code was originally by the user "UniBrain" from the website:
 * http://forum.codecall.net/topic/74377-moving-graphics-across-up-and-down-a-jpanel/?p=652384
 * 
 * but has been modified by me for my own purposes
 */

public class Canvas2 extends JPanel
{
//attributes
private Rectangle player1;
private Rectangle player2;
private ArrayList<KeyEvent> log;

//constructor
public Canvas2()
{
    //initialize object
    player1 = new Rectangle (50, 50, 50, 50);
    player2 = new Rectangle (50, 50, 50, 50);

    log = new ArrayList<KeyEvent>();

    //set canavs background colour
    setBackground (Color.white);

    //add the key listener in the constructor of your canavas/panel
    addKeyListener(new myKeyListener());

    //ensure focus is on this canavas/panel for key operations.
    setFocusable(true);
}

//painting
public void paintComponent(Graphics graphics)
{
    super.paintComponent(graphics);
    Graphics2D graphics2d =(Graphics2D)graphics;

    graphics.setColor(Color.blue);
    graphics2d.fill(player1);
    graphics2d.fill(player2);
}

//function which essentially re-creates rectangle with varying x orientations. (x-movement)
public void moveX(int mutationDistance, Rectangle sampleObject)
{
    sampleObject.setBounds(sampleObject.x + mutationDistance, sampleObject.y, sampleObject.width, sampleObject.height);
}

//function which essentially re-creates rectangle with varying y orientations. (y-movement)
public void moveY(int mutationDistance, Rectangle sampleObject)
{
    sampleObject.setBounds(sampleObject.x, sampleObject.y + mutationDistance, sampleObject.width, sampleObject.height);
}

public void move(){
    /*
     * This method of keeping track of key events and using a loop is taken from the user Michael Meyers at
     * http://stackoverflow.com/questions/752999/how-do-i-handle-multiple-key-presses-in-java
     */
    Thread thread1 = new Thread() 
        {
            public void run() {
                for(KeyEvent keyEvent: log){
                    if(keyEvent.getKeyCode() == KeyEvent.VK_RIGHT){moveX(5, player1);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_LEFT){moveX (-5, player1);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_UP){moveY (-5, player1);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_DOWN){moveY (5, player1);}
                }
            }
        };
    Thread thread2 = new Thread() 
        {
            public void run() {
                for(KeyEvent keyEvent: log){
                    if(keyEvent.getKeyCode() == KeyEvent.VK_D){moveX(5, player2);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_A){moveX(-5, player2);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_W){moveY(-5, player2);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_S){moveY(5, player2);}
                }
            }
        };

    //Starts the threads
    thread1.start();
    thread2.start();

    //Waits for them to finish
    try{
        thread1.join();
        thread2.join();
        log = new ArrayList<KeyEvent>();
    }
    catch (Exception e){System.out.println(e);}
}
//listener
private class myKeyListener implements KeyListener
{
    //implement all the possible actions on keys
    public void keyPressed(KeyEvent keyEvent)
    {
        if(keyEvent.getKeyCode() == KeyEvent.VK_ESCAPE){System.exit (0);}

        Thread thread3 = new Thread() 
            {
                public void run() {
                    if(keyEvent.getKeyCode() == KeyEvent.VK_RIGHT){moveX(5, player1);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_LEFT){moveX(-5, player1);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_UP){moveY(-5, player1);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_DOWN){moveY (5, player1);}
                }
            };

        Thread thread4 = new Thread() 
            {
                public void run() {
                    if(keyEvent.getKeyCode() == KeyEvent.VK_D){moveX(5, player2);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_A){moveX(-5, player2);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_W){moveY(-5, player2);}
                    if(keyEvent.getKeyCode() == KeyEvent.VK_S){ moveY(5, player2);}
                }
            };

        Thread thread5 = new Thread() 
            {
                public void run() {
                    repaint();
                }
            };

        thread3.start();
        thread4.start();
        thread5.start();

        try{
            thread3.join();
            thread4.join();
            thread5.join();
        }
        catch (Exception e){System.out.println(e);}

        repaint();
    }

    public void keyReleased(KeyEvent keyEvent)
    {
    }

    public void keyTyped(KeyEvent keyEvent)
    {
    }
}

public static void pause(int secs){
    try{Thread.sleep(secs*0);} catch(Exception e){}
}
}

which is then executed by this class

import javax.swing.JFrame;
import java.awt.Dimension;

/**
 * This code was taken from the user "UniBrain" from the website:
 * http://forum.codecall.net/topic/74377-moving-graphics-across-up-and-down-a-jpanel/?p=652384
 */

public class Display
{   

public static void main ( String [ ] arguments )
{
    JFrame frame = new JFrame("key listener demo");
    Canvas2 panel = new Canvas2();

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(panel);
    frame.setContentPane(panel);

    frame.setPreferredSize(new Dimension(800, 600));
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    frame.pack();
}
}
ADC2000
  • 63
  • 7