我有一个适用于player1 keyEvents的线程,但是当我为player2 keyevents添加另一个线程时,只注册了player2按键。这是线程问题还是keyEvents()方法的问题?我不知道接下来要去哪里。
//keyEvents thread for player 1
AnimationTimer player1_timer = new AnimationTimer(){
@Override
public void handle(long now){
keyEvents(player1, 1);
}
};
player1_timer.start();
if(true){ //if I set this to false, player1 keyEvents are registered again.
//keyEvents thread for player 2
AnimationTimer player2_timer = new AnimationTimer(){
@Override
public void handle(long now){
keyEvents(player2, 2);
}
};
player2_timer.start();
}
private void keyEvents(Unit player, int playerNumber){
map.setOnKeyPressed((KeyEvent e) -> {
if(playerNumber == 1){
if(null != e.getCode())switch (e.getCode()) {
case LEFT:
player1.rotateLeft();
break;
default:
break;
}
}
if(playerNumber == 2){
if(null != e.getCode())switch (e.getCode()) {
case A:
player2.rotateLeft();
break;
default:
break;
}
}
});
}
更新代码:
//keyEvents thread for players
AnimationTimer playerTimer = new AnimationTimer(){
@Override
public void handle(long now){
keyEvents();
}
};
playerTimer.start();
private void keyEvents(){
Bullet bullet = new Bullet();
map.setOnKeyPressed((KeyEvent e) -> {
if(null != e.getCode())switch (e.getCode()) {
case A:
player2.rotateLeft();
break;
case LEFT:
player1.rotateLeft();
break;
default:
break;
}
});
}
答案 0 :(得分:1)
首先,这就像我的第二个JavaFX程序,所以我确信可以做出一些改进。
你必须认识到你仍然只处理单个线程,JavaFX的事件调度线程。
AnimationTimer
和EventHandler
都在此线程的上下文中被调用,因此添加更多这些内容并不会为您提供任何额外的好处,并且实际上可能是部门的。< / p>
相反,您想为keyPressed
和keyReleased
添加一个处理程序。在这些处理程序中,您希望为给定的玩家设置给定方向的状态。
执行此操作的最简单方法之一是Set
,您可以add
和remove
一个“关键”对象,它代表给定玩家的方向。< / p>
然后,您将使用单个AnimationTimer
作为“主循环”,并根据Set
的状态确定播放器对象应移动的方向
这是游戏开发中非常常见的概念,它很简单,但它也将逻辑与状态分离,因此可以通过任何方式(鼠标/操纵杆/ AI /网络)设置状态,逻辑不会在意。
import java.util.Set;
import java.util.TreeSet;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import static javafx.scene.input.KeyCode.DOWN;
import static javafx.scene.input.KeyCode.SHIFT;
import static javafx.scene.input.KeyCode.UP;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class Test extends Application {
enum Direction {
UP, DOWN, LEFT, RIGHT;
}
private static final double W = 600, H = 400;
private Image playerOneImage;
private Node playerOneNode;
private Image playerTwoImage;
private Node playerTwoNode;
private Set<Direction> playerOneDirection = new TreeSet<>();
private Set<Direction> playerTwoDirection = new TreeSet<>();
boolean running;
@Override
public void start(Stage stage) throws Exception {
playerOneImage = makePlayerOne();
playerOneNode = new ImageView(playerOneImage);
playerTwoImage = makePlayerTwo();
playerTwoNode = new ImageView(playerTwoImage);
Group dungeon = new Group(playerOneNode, playerTwoNode);
movePlayerTo(playerOneNode, 0, 0);
movePlayerTo(playerTwoNode, W - 12.5, H - 12.5);
Scene scene = new Scene(dungeon, W, H, Color.FORESTGREEN);
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
switch (event.getCode()) {
case UP:
playerOneDirection.add(Direction.UP);
break;
case DOWN:
playerOneDirection.add(Direction.DOWN);
break;
case LEFT:
playerOneDirection.add(Direction.LEFT);
break;
case RIGHT:
playerOneDirection.add(Direction.RIGHT);
break;
case W:
playerTwoDirection.add(Direction.UP);
break;
case S:
playerTwoDirection.add(Direction.DOWN);
break;
case A:
playerTwoDirection.add(Direction.LEFT);
break;
case D:
playerTwoDirection.add(Direction.RIGHT);
break;
}
}
});
scene.setOnKeyReleased(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
switch (event.getCode()) {
case UP:
playerOneDirection.remove(Direction.UP);
break;
case DOWN:
playerOneDirection.remove(Direction.DOWN);
break;
case LEFT:
playerOneDirection.remove(Direction.LEFT);
break;
case RIGHT:
playerOneDirection.remove(Direction.RIGHT);
break;
case W:
playerTwoDirection.remove(Direction.UP);
break;
case S:
playerTwoDirection.remove(Direction.DOWN);
break;
case A:
playerTwoDirection.remove(Direction.LEFT);
break;
case D:
playerTwoDirection.remove(Direction.RIGHT);
break;
}
}
});
stage.setScene(scene);
stage.show();
AnimationTimer timer = new AnimationTimer() {
@Override
public void handle(long now) {
movePlayer(playerOneNode, playerOneDirection);
movePlayer(playerTwoNode, playerTwoDirection);
}
};
timer.start();
}
private void movePlayer(Node playerNode, Set<Direction> direction) {
int dx = 0;
int dy = 0;
if (direction.contains(Direction.UP)) {
dy -= 1;
}
if (direction.contains(Direction.DOWN)) {
dy += 1;
}
if (direction.contains(Direction.RIGHT)) {
dx += 1;
}
if (direction.contains(Direction.LEFT)) {
dx -= 1;
}
if (running) {
dx *= 3;
dy *= 3;
}
if (dx == 0 && dy == 0) {
return;
}
final double cx = playerNode.getBoundsInLocal().getWidth() / 2;
final double cy = playerNode.getBoundsInLocal().getHeight() / 2;
double x = cx + playerNode.getLayoutX() + dx;
double y = cy + playerNode.getLayoutY() + dy;
movePlayerTo(playerNode, x, y);
}
private void movePlayerTo(Node playerNode, double x, double y) {
final double cx = playerNode.getBoundsInLocal().getWidth() / 2;
final double cy = playerNode.getBoundsInLocal().getHeight() / 2;
if (x - cx >= 0
&& x + cx <= W
&& y - cy >= 0
&& y + cy <= H) {
playerNode.relocate(x - cx, y - cy);
}
}
protected Image makePlayerOne() {
return makePlayer(Color.RED);
}
protected Image makePlayerTwo() {
return makePlayer(Color.BLUE);
}
protected Image makePlayer(Color color) {
WritableImage image = new WritableImage(25, 25);
PixelWriter writer = image.getPixelWriter();
for (int y = 0; y < 25; y++) {
for (int x = 0; x < 25; x++) {
writer.setColor(x, y, color);
}
}
return image;
}
public static void main(String[] args) {
launch(args);
}
}