我想写一个小游戏,我可以用W,a,S,D键在JavaFX面板上移动一个球
我有一个getPosX()
和setPosX()
但是我不知道如何编写一个KeyListener
,如果我按D,它将计算setPosX(getPosX()1)
。
我必须做什么?
使用JNativeHook:https://github.com/kwhat/jnativehook
<!-- https://mvnrepository.com/artifact/com.1stleg/jnativehook -->
<dependency>
<groupId>com.1stleg</groupId>
<artifactId>jnativehook</artifactId>
<version>2.1.0</version>
</dependency>
private void initKeyListener(Stage primaryStage){
/* Note: JNativeHook does *NOT* operate on the event dispatching thread.
* Because Swing components must be accessed on the event dispatching
* thread, you *MUST* wrap access to Swing components using the
* SwingUtilities.invokeLater() or EventQueue.invokeLater() methods.
*/
try {
GlobalScreen.registerNativeHook();
} catch (NativeHookException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
GlobalScreen.addNativeKeyListener(new NativeKeyListener() {
public void nativeKeyPressed(NativeKeyEvent e) {
if ( (e.getModifiers() & NativeKeyEvent.CTRL_MASK) != 0
&& (e.getModifiers() & NativeKeyEvent.ALT_MASK) != 0
&& (e.getKeyCode() == NativeKeyEvent.VC_B)){
logger.debug("key :Hide");
primaryStage.hide();
}
if ( (e.getModifiers() & NativeKeyEvent.CTRL_MASK) != 0
&& (e.getModifiers() & NativeKeyEvent.SHIFT_MASK) != 0
&& (e.getModifiers() & NativeKeyEvent.ALT_MASK) != 0
&& (e.getKeyCode() == NativeKeyEvent.VC_B)){
logger.debug("key :Show");
primaryStage.show();
}
//System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
}
public void nativeKeyReleased(NativeKeyEvent e) {
//System.out.println("Key Released: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
}
public void nativeKeyTyped(NativeKeyEvent e) {
//System.out.println("Key Typed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
}
});
/*
GlobalScreen.addNativeMouseListener(new NativeMouseListener() {
@Override
public void nativeMouseReleased(NativeMouseEvent arg0) {
// TODO Auto-generated method stub
System.out.println("MouseReleased()");
}
@Override
public void nativeMousePressed(NativeMouseEvent arg0) {
// TODO Auto-generated method stub
System.out.println("MousePressed()");
}
@Override
public void nativeMouseClicked(NativeMouseEvent arg0) {
// TODO Auto-generated method stub
System.out.println("MouseClicked()");
}
});
*/
}
Scene myScene = new Scene();
KeyCombination cntrlZ = new KeyCodeCombination(KeyCode.Z, KeyCodeCombination.CONTROL_DOWN);
myScene.setOnKeyPressed(new EventHandler<KeyEvent>(){
@Override
public void handle(KeyEvent event) {
if(contrlZ.match(event)){
//Do something
}
}
});
来自JavaRanch论坛的帖子。
按键和释放处理程序添加到场景中,并更新应用程序中记录的移动状态变量。动画计时器与JavaFX pulse机制挂钩(默认情况下,该机制将限制每秒触发60次事件),因此这是一种游戏“循环”。在计时器中,将检查移动状态变量,并将其增量动作应用于角色位置——这实际上是响应按键在屏幕上移动角色。
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.*;
import javafx.scene.image.*;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
/**
* Hold down an arrow key to have your hero move around the screen.
* Hold down the shift key to have the hero run.
*/
public class Runner extends Application {
private static final double W = 600, H = 400;
private static final String HERO_IMAGE_LOC =
"http://icons.iconarchive.com/icons/raindropmemory/legendora/64/Hero-icon.png";
private Image heroImage;
private Node hero;
boolean running, goNorth, goSouth, goEast, goWest;
@Override
public void start(Stage stage) throws Exception {
heroImage = new Image(HERO_IMAGE_LOC);
hero = new ImageView(heroImage);
Group dungeon = new Group(hero);
moveHeroTo(W / 2, H / 2);
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: goNorth = true; break;
case DOWN: goSouth = true; break;
case LEFT: goWest = true; break;
case RIGHT: goEast = true; break;
case SHIFT: running = true; break;
}
}
});
scene.setOnKeyReleased(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
switch (event.getCode()) {
case UP: goNorth = false; break;
case DOWN: goSouth = false; break;
case LEFT: goWest = false; break;
case RIGHT: goEast = false; break;
case SHIFT: running = false; break;
}
}
});
stage.setScene(scene);
stage.show();
AnimationTimer timer = new AnimationTimer() {
@Override
public void handle(long now) {
int dx = 0, dy = 0;
if (goNorth) dy -= 1;
if (goSouth) dy += 1;
if (goEast) dx += 1;
if (goWest) dx -= 1;
if (running) { dx *= 3; dy *= 3; }
moveHeroBy(dx, dy);
}
};
timer.start();
}
private void moveHeroBy(int dx, int dy) {
if (dx == 0 && dy == 0) return;
final double cx = hero.getBoundsInLocal().getWidth() / 2;
final double cy = hero.getBoundsInLocal().getHeight() / 2;
double x = cx + hero.getLayoutX() + dx;
double y = cy + hero.getLayoutY() + dy;
moveHeroTo(x, y);
}
private void moveHeroTo(double x, double y) {
final double cx = hero.getBoundsInLocal().getWidth() / 2;
final double cy = hero.getBoundsInLocal().getHeight() / 2;
if (x - cx >= 0 &&
x + cx <= W &&
y - cy >= 0 &&
y + cy <= H) {
hero.relocate(x - cx, y - cy);
}
}
public static void main(String[] args) { launch(args); }
}
如果已经提供的信息足以满足您的需要,请忽略本答案的其余部分。
虽然上述解决方案足以回答这个问题,但如果有兴趣,可以在这个演示突破游戏中找到更复杂的输入处理程序(具有更通用、更独立的输入和更新处理逻辑):
示例突破游戏中的通用输入处理程序:
class InputHandler implements EventHandler<KeyEvent> {
final private Set<KeyCode> activeKeys = new HashSet<>();
@Override
public void handle(KeyEvent event) {
if (KeyEvent.KEY_PRESSED.equals(event.getEventType())) {
activeKeys.add(event.getCode());
} else if (KeyEvent.KEY_RELEASED.equals(event.getEventType())) {
activeKeys.remove(event.getCode());
}
}
public Set<KeyCode> getActiveKeys() {
return Collections.unmodifiableSet(activeKeys);
}
}
虽然带有适当设置更改侦听器的observateSet
可以用于活动密钥集,但我使用了一个访问器,它会及时返回一组不可修改的密钥,这些密钥在快照中处于活动状态,因为这正是我感兴趣的,而不是实时观察活动密钥集的更改。
通用输入处理程序用法示例:
Scene gameScene = createGameScene();
// register the input handler to the game scene.
InputHandler inputHandler = new InputHandler();
gameScene.setOnKeyPressed(inputHandler);
gameScene.setOnKeyReleased(inputHandler);
gameLoop = createGameLoop();
// . . .
private AnimationTimer createGameLoop() {
return new AnimationTimer() {
public void handle(long now) {
update(now, inputHandler.getActiveKeys());
if (gameState.isGameOver()) {
this.stop();
}
}
};
}
public void update(long now, Set<KeyCode> activeKeys) {
applyInputToPaddle(activeKeys);
// . . . rest of logic to update game state and view.
}
// The paddle is sprite implementation with
// an in-built velocity setting that is used to
// update its position for each frame.
//
// on user input, The paddle velocity changes
// to point in the correct predefined direction.
private void applyInputToPaddle(Set<KeyCode> activeKeys) {
Point2D paddleVelocity = Point2D.ZERO;
if (activeKeys.contains(KeyCode.LEFT)) {
paddleVelocity = paddleVelocity.add(paddleLeftVelocity);
}
if (activeKeys.contains(KeyCode.RIGHT)) {
paddleVelocity = paddleVelocity.add(paddleRightVelocity);
}
gameState.getPaddle().setVelocity(paddleVelocity);
}
问题内容: 我正在手动为postgres构造DELETE CASCADE语句。 我有一个“交易”和一个“切片”表,如下所示: 假设我要删除名称为“ my_slice”的切片所引用的所有事务和category_item。我需要写些什么? 问题答案: 万一您不能做别人建议的事情:
问题内容: 如何编写Android Studio插件? 我一直在寻找文档,但是很遗憾,文档很少或很差,所以可以推荐哪些文章? Eclipse或IntelliJ IDEA插件可以在Android Studio中使用吗? 问题答案: 由于Android Studio基于IntelliJIDEA,因此IntelliJ文档是一个很好的起点: Jetbrains插件开发
问题内容: 如何仅为IE 11破解或编写CSS?我有一个在IE 11中看起来很糟糕的网站。我只是在这里和那里搜索,但尚未找到任何解决方案。 是否有任何CSS选择器? 问题答案: 结合使用Microsoft特定的CSS规则来过滤IE11: 之所以这样的过滤器,是因为以下原因: 当用户代理无法解析选择器时(即,它不是有效的CSS 2.1),它必须忽略选择器以及随后的声明块(如果有)。
一些背景知识,以防我为实际想要实现的目标解决了错误的问题:我的目标是编写一个函数: 它检查和是否具有相同的类型并相等,然后返回提供的(我们当时知道它与相同--T可能不是内射的,但它是一个函数!)或,否则。 我已经找到了一个解决办法,将违规的包装在中,使用,然后再次打开包装: 这种解决方法是完全可以接受的,但我希望去掉虚假的类型。
下面是我的员工课。如果我在第1行、第2行或第3行编写@bean注释,它会抛出一个错误。 它只允许对方法名使用@bean注释。为什么?
问题内容: 类似于,是否有写方法? 我正在通过重写一些旧代码来练习Java 8。而且,我想知道如何使用Stream API编写以下函数。 我希望它将转化为以下内容: 问题答案: