【问题标题】:How to create a JavaFX Scene for multiple Key Listeners?如何为多个关键侦听器创建 JavaFX 场景?
【发布时间】:2023-03-20 16:20:01
【问题描述】:

所以我正在尝试创建一个有点像蛇的 Tron 多人游戏。 无论如何,多人应该能够使用一个键盘玩该游戏,但不同的组合键可以在屏幕上引导他们的角色。一位玩家目前使用 WASD 键,另一位玩家应使用箭头键。

我的问题是我使用 FXML 使用 Javafx Scene Builder 创建了一个场景。在创建游戏之后我才注意到场景构建器显然只支持一个按键监听器,所以目前只有一个玩家可以控制他们的游戏人物。 有没有办法解决这个问题?请帮助一位玩家可以使用 WASD 键,而另一位玩家可以使用箭头键进行导航。 我的问题与现有解决方案不同,因为蛇需要属于不同的玩家。仅检查是否按下了一个键输入或同时按下了两个键是不够的,但它需要检查是否正确的玩家按下了输入,即使当时另一个玩家也按下了他们的输入。 希望这能消除一些混乱。

关键监听器

 import java.util.ArrayList;

import javafx.scene.Scene;

public class Human extends Player implements Runnable{


int keyboardControlsLayout;
Scene scene;

public Human(int stepSize, String colour, int playerNum, Scene scene, 
           int keyboardControlsLayout) {
    super(stepSize, colour, playerNum);
    // keyboardControlsLayout(0) = WASD
    // keyboardControlsLayout(1) = ARROWS
    this.keyboardControlsLayout = keyboardControlsLayout;
    this.scene = scene;

}

@Override
public void run() {
    // TODO Auto-generated method stub

    while(this.getSnake().getAlive()) {

        if (keyboardControlsLayout == 1) {
            // use WASD
            System.out.println("wasd");

            scene.setOnKeyPressed(event -> {
                switch (event.getCode()) {
                    case W:
                        snake.setDirection(0);
                        break;
                    case S:
                        snake.setDirection(1);
                        break;
                    case A:
                        snake.setDirection(3);
                        break;
                    case D:
                        snake.setDirection(2);
                        break;
                    default:
                        break;
                }
                //System.out.println(event.getCode().toString());
            });


        } else if (keyboardControlsLayout == 0) {
            System.out.println("arrows");
            // use arrow keys
            scene.setOnKeyPressed(event -> {
                switch (event.getCode()) {
                    case UP:
                        snake.setDirection(0);
                        break;
                    case DOWN:
                        snake.setDirection(1);
                        break;
                    case LEFT:
                        snake.setDirection(3);
                        break;
                    case RIGHT:
                        snake.setDirection(2);
                        break;
                    default:
                        break;
                }
            });
        }


    }

}
 }

我在哪里创建场景:

public void newGame() {
    System.out.println("<----- NEW GAME ----->");
    game = new Game(10, scene, numHumans);
    displayController.setUpDisplay(game);

    timer = new Timeline((new KeyFrame(
            Duration.millis(80),
            event -> {
                try {
                    timerTick();
                } catch (Exception e) {
                    // TODO Auto-generated catch 
                                         block
                    e.printStackTrace();
                }
            })));
    timer.setCycleCount(Animation.INDEFINITE);

    start();
}

private void start() {
// starts game and logic
}


private void loadDisplayFXMLLoader() {
    FXMLLoader displayFXMLLoader = new 
    FXMLLoader(getClass().getResource("DisplayView.fxml"));

    try {
        scene = new Scene(displayFXMLLoader.load(), 500, 525);
    } catch (IOException e) {
        Main.outputError(e);
    }

    displayController = displayFXMLLoader.getController();

}

private void loadScene() {
    this.setScene(scene);
    this.show();

    //error Handling and closing



}

任何帮助将不胜感激!

谢谢

【问题讨论】:

  • 我喜欢使用here 找到的想法。他使用ArrayList 进行输入。我喜欢使用Set。当按下映射按钮时,将其添加到输入中。发布时,将其从输入中删除。
  • 它与您指出的问题类似。但不完全相同,因为我不想同时按下多个键。但是听众可能会对两个玩家做出反应
  • 我会看看那个。谢谢塞德里克!
  • 我没有在副本中使用@James_D 答案,但考虑到他的历史,我敢打赌它有效。我在共享的链接上使用了第一个想法。它工作正常。

标签: java javafx keylistener


【解决方案1】:

我不熟悉 FXML,但我个人自己使用 javafx,它运行良好。如果您想尝试测试一下,我调整了一个旧程序以满足您的需求

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class yeet {

    private static JFrame frame;
    private static JPanel panel;

    private static int x = 300;
    private static int y = 300;
    private static int x1 = 500;
    private static int y1 = 500;

    private static boolean running = true;
    private static boolean moving = false;
    private static boolean moving1 = false;
    private static boolean up;
    private static boolean down;
    private static boolean right;
    private static boolean left;
    private static boolean up1;
    private static boolean down1;
    private static boolean right1;
    private static boolean left1;

    private static Timer refresh;
    private static Timer speed;

    private static Graphics g;

    public static void main(String[] args) {

        UI();



        ActionListener al = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                if(moving && up) y--;
                if (moving && down) y++;
                if (moving && right) x++;
                if (moving && left) x--;

                if (moving1 && up1) y1--;
                if (moving1 && down1) y1++;
                if (moving1 && right1) x1++;
                if (moving1 && left1) x1--;

                panel.repaint();

            }

        };

        ActionListener al1 = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                guy(g);
                laser(g);

            }

        };

        refresh = new Timer(0, al1);
        refresh.start();
        speed = new Timer (4, al);
        speed.start();



        while (running) {
            guy(g);
            laser(g);

        }

    }

    public static void guy(Graphics g) {
        g = panel.getGraphics();
        g.setColor(Color.green);
        g.drawRect(x, y, 25, 25);
        g.fillRect(x, y, 25, 25);

    }

    public static void laser (Graphics g) {
        g = panel.getGraphics();
        g.setColor(Color.red);
        g.drawRect(x1, y1, 30, 30);
        g.fillRect(x1, y1, 30, 30);
    }

    public static void UI () {

        frame = new JFrame("Multiple movement test");
        panel = new JPanel();

        panel.setBackground(Color.black);
        panel.setLayout(null);

        frame.setSize(600,600);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        frame.setVisible(true);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.addKeyListener(new KeyListener() {

            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_UP) {
                    moving = true;
                    up = true;

                    down = false;
                    right = false;
                    left = false;

                    refresh.start();
                    speed.start();
                }

                if (e.getKeyCode() == KeyEvent.VK_DOWN) {
                    moving = true;
                    down = true;

                    up = false;
                    right = false;
                    left = false;

                    refresh.start();
                    speed.start();
                }

                if (e.getKeyCode() == KeyEvent.VK_LEFT) {
                    moving = true;
                    left = true;

                    up = false;
                    down = false;
                    right = false;

                    refresh.start();
                    speed.start();
                }

                if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
                    moving = true;
                    right = true;

                    left = false;
                    up = false;
                    down = false;

                    refresh.start();
                    speed.start();
                }

                if (e.getKeyCode() == KeyEvent.VK_W) {
                    moving1 = true;
                    up1 = true;

                    down1 = false;
                    right1 = false;
                    left1 = false;

                    refresh.start();
                    speed.start();
                }

                if (e.getKeyCode() == KeyEvent.VK_A) {
                    moving1 = true;
                    left1 = true;

                    up1 = false;
                    down1 = false;
                    right1 = false;


                    refresh.start();
                    speed.start();
                }

                if (e.getKeyCode() == KeyEvent.VK_S) {
                    moving1 = true;
                    down1 = true;

                    up1 = false;
                    right1 = false;
                    left1 = false;

                    refresh.start();
                    speed.start();
                }

                if (e.getKeyCode() == KeyEvent.VK_D) {
                    moving1 = true;
                    right1 = true;

                    up1 = false;
                    down1 = false;
                    left1 = false;

                    refresh.start();
                    speed.start();
                }

            }

            @Override
            public void keyReleased(KeyEvent arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void keyTyped(KeyEvent arg0) {
                // TODO Auto-generated method stub

            }

        });

        frame.add(panel);

    }
}   

希望这会有所帮助!

【讨论】:

  • 谢谢亚历克斯。我的问题是我需要为键分配某种“所有权”,所以蛇 1 被 WASD 键移动,蛇 2 被箭头移动。我不知道如何将它应用到你写的东西上,但我会考虑的。
  • 不,问题是关于 FX,而不是 Swing/awt
猜你喜欢
  • 1970-01-01
  • 2020-05-17
  • 1970-01-01
  • 2016-09-19
  • 1970-01-01
  • 2021-09-12
  • 2016-12-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多