Home > Java > javaTutorial > body text

How Can I Handle Multiple Key Presses Simultaneously in a Java Game Using Key Bindings?

Susan Sarandon
Release: 2024-11-21 02:44:14
Original
404 people have browsed it

How Can I Handle Multiple Key Presses Simultaneously in a Java Game Using Key Bindings?

Threads with Key Bindings

Multi-threading is not necessary unless you want your game to be multi-threaded.

The issue is, can two players press different keys? If so, you can use booleans to indicate whether a key is down and reset the flag when the key is released.

In your game logic, check the states of the booleans and act appropriately. See the following example where both paddles can move independently:

[Image of paddles moving independently]

Here's an example code:

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

public class GameLogic extends JFrame 
{

    public GameLogic() 
    {
        initComponents();
    }

    private void initComponents() 
    {
        JFrame frame = new JFrame("Game Test");
       //create the gamepanel
        final GamePanel gp = new GamePanel(600, 500);
        //create panel to hold buttons to start, pause
        JPanel buttonPanel = new JPanel();
        final JButton startButton = new JButton("Start");
        final JButton pauseButton = new JButton("Pause");
        final JButton resetButton = new JButton("Reset");

        pauseButton.setEnabled(false);
        resetButton.setEnabled(false);
        //add listeners to buttons
        startButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                gp.clearEntities();
                addEntityToPanel(gp);
                
                startButton.setEnabled(false);
                pauseButton.setEnabled(true);
                resetButton.setEnabled(true);

               //start the game loop which will repaint the screen
                runGameLoop(gp);

            }
        });
        //create and add keybindings for game panel 
        GameKeyBindings gameKeyBindings = new GameKeyBindings(gp, player1Entity, player2Entity);

        pauseButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                boolean b = GamePanel.paused.get();

                GamePanel.paused.set(!b);//set it to the opposite of what it was i.e paused to unpaused and vice versa

                if (pauseButton.getText().equals("Pause")) {
                    pauseButton.setText("Un-pause");
                } else {
                    pauseButton.setText("Pause");
                }
            }
        });

        resetButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                resetGame(gp);

            }
        });

        buttonPanel.add(startButton);
        buttonPanel.add(pauseButton);
        buttonPanel.add(resetButton);

        frame.add(gp);
        frame.add(buttonPanel, BorderLayout.SOUTH);

       
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

    }
    

    //Simply used for testing (to simulate sprites) can create different colored images 
    public static BufferedImage createColouredImage(String color, int w, int h, boolean circular) {
        BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = img.createGraphics();
        switch (color.toLowerCase()) {
            case "green":
                g2.setColor(Color.GREEN);
                break;
            case "magenta":
                g2.setColor(Color.MAGENTA);
                break;
            case "red":
                g2.setColor(Color.RED);
                break;
            case "yellow":
                g2.setColor(Color.YELLOW);
                break;
            case "blue":
                g2.setColor(Color.BLUE);
                break;
            case "orange":
                g2.setColor(Color.ORANGE);
                break;
            case "cyan":
                g2.setColor(Color.CYAN);
                break;
            case "gray":
                g2.setColor(Color.GRAY);
                break;
            default:
                g2.setColor(Color.WHITE);
                break;
        }
        if (!circular) {
            g2.fillRect(0, 0, img.getWidth(), img.getHeight());
        } else {
            g2.fillOval(0, 0, img.getWidth(), img.getHeight());
        }
        g2.dispose();
        return img;
    }

    private void runGameLoop(final GamePanel gp) {
        Thread loop = new Thread(new Runnable() {

            @Override
            public void run() {
                gp.gameLoop();
            }
        });
        loop.start();
    }

    private void resetGame(GamePanel gp) {
        gp.reset();
        gp.clearEntities();
        addEntityToPanel(gp);
        gp.repaint();
    }
    void addEntityToPanel(GamePanel gp){
    
                ArrayList<BufferedImage> ballEntityImages = new ArrayList<>();
                ArrayList<Long> ballEntityTimings = new ArrayList<>();
                ballEntityImages.add(createColouredImage("white", 50, 50, true));
                ballEntityTimings.add(500l);

                Entity ballEntity = new Entity(gp.getWidth() / 2, gp.getHeight() / 2, ballEntityImages, ballEntityTimings);
                ballEntity.RIGHT = true;

                //create images  for entities 
                ArrayList<BufferedImage> advEntityImages = new ArrayList<>();
                ArrayList<Long> advEntityTimings = new ArrayList<>();
                advEntityImages.add(createColouredImage("orange", 10, 100, false));
                advEntityTimings.add(500l);
                advEntityImages.add(createColouredImage("blue", 10, 100, false));
                advEntityTimings.add(500l);

                //create entities 
                AdvancedSpritesEntity player1Entity = new AdvancedSpritesEntity(0, 100, advEntityImages, advEntityTimings);


                ArrayList<BufferedImage> entityImages = new ArrayList<>();
                ArrayList<Long> entityTimings = new ArrayList<>();
                entityImages.add(createColouredImage("red", 10, 100, false));
                entityTimings.add(500l);//as its the only image it doesnt really matter what time we put we could use 0l
                //entityImages.add(createColouredImage("magenta", 100, 100));
                //entityTimings.add(500l); 

                Entity player2Entity = new Entity(gp.getWidth() - 10, 200, entityImages, entityTimings);

                gp.addEntity(player1Entity);
                gp.addEntity(player2Entity);//just a standing still Entity for testing
                gp.addEntity(ballEntity);//just a standing still Entity for testing

           
    }
    //Code starts here
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {

                try {//attempt to set look and feel to nimbus Java 7 and up
                    for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                        if ("Nimbus".equals(info.getName())) {
                            UIManager.setLookAndFeel(info.getClassName());
                            break;
                        }
                    }
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }
                GameLogic gameLogic = new GameLogic();
            }
        });
    }
}

class GameKeyBindings {

    public GameKeyBindings(JComponent gp, final Entity entity, final Entity entity2) {

        gp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false), "W pressed");
        gp.getActionMap().put("W pressed", new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent ae) {
               entity.UP=true;
            }
        });
        gp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, false), "S pressed");
        gp.getActionMap().put("S pressed", new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent ae) {
               entity.DOWN=true;
            }
        });

        gp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "up pressed");
        gp.getActionMap().put("up pressed", new AbstractAction() {

            @Override
Copy after login

The above is the detailed content of How Can I Handle Multiple Key Presses Simultaneously in a Java Game Using Key Bindings?. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template