Home >Java >javaTutorial >How Can Threads Improve Key Binding Handling in a Two-Player Game?

How Can Threads Improve Key Binding Handling in a Two-Player Game?

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-11-25 05:49:10584browse

How Can Threads Improve Key Binding Handling in a Two-Player Game?

Threads with Key Bindings

In the given context, you can use separate threads to handle key bindings and update the game state. This allows players to control their paddles independently using different keys and ensures that both players can move their paddles simultaneously.

Here's an example that demonstrates how to use key bindings with threads:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class Main {
    private static final int WIDTH = 600;
    private static final int HEIGHT = 500;

    public static void main(String[] args) {
        // Create a new game instance
        Game game = new Game(WIDTH, HEIGHT);

        // Create a thread pool to handle key bindings
        ExecutorService keyBindingPool = Executors.newCachedThreadPool();

        // Create key bindings for the two players
        KeyBindings player1Bindings = new KeyBindings(game, "W", "S");
        KeyBindings player2Bindings = new KeyBindings(game, "UP", "DOWN");

        // Install the key bindings using SwingUtilities to ensure they work on the EDT
        SwingUtilities.invokeLater(() -> {
            game.getComponent().getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false), "player1Up");
            game.getComponent().getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, false), "player1Down");
            game.getComponent().getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "player2Up");
            game.getComponent().getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "player2Down");
            game.getComponent().getActionMap().put("player1Up", new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) { player1Bindings.up = true; }
            });
            game.getComponent().getActionMap().put("player1Down", new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) { player1Bindings.down = true; }
            });
            game.getComponent().getActionMap().put("player2Up", new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) { player2Bindings.up = true; }
            });
            game.getComponent().getActionMap().put("player2Down", new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) { player2Bindings.down = true; }
            });
        });

        // Add the key bindings to the thread pool
        keyBindingPool.submit(player1Bindings);
        keyBindingPool.submit(player2Bindings);

        // Start the game loop
        game.start();
    }

    private static class Game {
        private final int width;
        private final int height;
        private final Paddle paddle1;
        private final Paddle paddle2;
        private final Thread gameLoopThread;
        private final AtomicBoolean running;

        public Game(int width, int height) {
            this.width = width;
            this.height = height;
            this.paddle1 = new Paddle(0, 100, 10, 100);
            this.paddle2 = new Paddle(width - 10, 200, 10, 100);
            this.running = new AtomicBoolean(false);
            this.gameLoopThread = new Thread(this::gameLoop);
        }

        public void start() {
            running.set(true);
            gameLoopThread.start();
        }

        private void gameLoop() {
            while (running.get()) {
                // Update the game state based on the key bindings
                if (player1Bindings.up) { paddle1.moveUp(); } else if (player1Bindings.down) { paddle1.moveDown(); }
                if (player2Bindings.up) { paddle2.moveUp(); } else if (player2Bindings.down) { paddle2.moveDown(); }

                // Render the game on the screen
                paint();
            }
        }

        public void paint() {
            // Clear the screen
            // Draw the paddles
            // Draw the ball
            // Update the display
        }

        public JComponent getComponent() { return null; }
    }

    private static class KeyBindings implements Runnable {
        private final Game game;
        private final String upKey;
        private final String downKey;
        private final HashSet<String> keysPressed;
        public boolean up;
        public boolean down;
        private AtomicBoolean running;

        public KeyBindings(Game game, String upKey, String downKey) {
            this.game = game;
            this.upKey = upKey;
            this.downKey = downKey;
            this.keysPressed = new HashSet<>();
            this.running = new AtomicBoolean(false);
        }

        public void start() {
            running.set(true);
        }

        @Override
        public void run() {
            while (running.get()) {
                // Check for key presses
                if (keysPressed.contains(upKey)) { up = true; } else { up = false; }
                if (keysPressed.contains(downKey)) { down = true; } else { down = false; }

                // Sleep for a bit
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {}
            }
        }
    }

    private static class Paddle {
        private int x;
        private int y;
        private int width;
        private int height;

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

        public void moveUp() { if (y > 0) { y -= 5; } }
        public void moveDown() { if (y < game.getHeight() - height) { y += 5; } }
    }
}

In this example:

  • The Game class manages the game state and initializes the paddles. It also starts the game loop thread.
  • The KeyBindings class is used to handle key bindings. It listens for key presses and updates the game state accordingly.
  • The Paddle class represents the paddles that are controlled by the players.
  • The main method creates a new game instance and installs the key bindings using SwingUtilities. It also starts the game loop.

This example ensures that both players can move their paddles independently using different keys, and the game state is updated smoothly and responsively.

The above is the detailed content of How Can Threads Improve Key Binding Handling in a Two-Player Game?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
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