KeyBindings 似乎工作不正常,不知道为什么 | Java
KeyBindings seem to work improperly and don't know why | Java
问题
我正在为我的 class 中的最终项目制作游戏,并且我正在处理键绑定。键绑定的工作方式不尽如人意。让我解释一下:
所以 objective 是在向出口(黑点)移动的同时将你的角色一次 "square" 移动一个。每次您按指定方向(A、S、D、W)的键绑定时,它应该检查 "terrain" 并将您移动到 "floor"。
旁注:我还没有添加移除地形,因为我需要先让运动正常工作。
回到说明:
所以最大的问题是,当我第一次按下键绑定时,它会将字符从原始位置移开三个 "squares"。然后之后的任何移动都是随机的,有时会使玩家出界。我设置了它,所以每次激活键绑定时它都会打印出玩家的位置(见下面的代码)。我觉得我在按键绑定过程中做错了,因为这是我第一次进行按键绑定。
这是我的程序为我的角色运动提供的打印输出之一:
E:\Whosebug\KeyBindings>java gamePanelMain
Player Start X: 0
Player Start Y: 0
Direction: Right, New X: 3
Direction: Right, New Y: 0
Direction: Right, New X: 9
Direction: Right, New Y: 0
Direction: Right, New X: 12
Direction: Right, New Y: 0
Direction: Down, New X: 12
Direction: Down, New Y: 3
Direction: Down, New X: 12
Direction: Down, New Y: 6
Direction: Down, New X: 12
Direction: Down, New Y: 8
Direction: Left, New X: 10
Direction: Left, New Y: 8
Direction: Left, New X: 7
Direction: Left, New Y: 8
Direction: Left, New X: 4
Direction: Left, New Y: 8
Direction: Down, New X: 4
Direction: Down, New Y: 11
Direction: Down, New X: 4
Direction: Down, New Y: 13
Direction: Down, New X: 4
Direction: Down, New Y: 17
Direction: Right, New X: 7
Direction: Right, New Y: 17
Direction: Right, New X: 17
Direction: Right, New Y: 17
Direction: Right, New X: 20
Direction: Right, New Y: 17
Direction: Right, New X: 23
Direction: Right, New Y: 17
Direction: Down, New X: 23
Direction: Down, New Y: 20
Direction: Down, New X: 23
Direction: Down, New Y: 23
Direction: Up, New X: 23
Direction: Up, New Y: 21
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 24
at gamePanel.right(gamePanel.java:259)
at gamePanel.changeCoord(gamePanel.java:192)
at gamePanel.actionPerformed(gamePanel.java:46)
at javax.swing.Timer.fireActionPerformed(Unknown Source)
at javax.swing.Timer$DoPostEvent.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access0(Unknown Source)
at java.awt.EventQueue.run(Unknown Source)
at java.awt.EventQueue.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
如您所见,它是完全随机的,并且运动没有连接到随机生成器或类似的东西。此外,我还没有添加检查越界的代码,但我更担心先让这个动作正确。
现在我看了一个关于键绑定的 post () 并尝试将该技术应用到我的游戏中进行键绑定操作。我不知道我做错了什么是问题的一部分。
这是我为键绑定添加的代码:
public enum Direction{
UP,
LEFT,
DOWN,
RIGHT;
}
private Set<Direction>movement;
public gamePanel()
{
setBounds(115,93,480,480);//sets the size and location of gamePanel (x,y,w,h)
setFocusable(true);
movement = new HashSet<>(4);
addKeyPressedBinding(KeyEvent.VK_A, "left.pressed", new MoveAction(movement, Direction.LEFT, true));
addKeyReleasedBinding(KeyEvent.VK_A, "left.released", new MoveAction(movement, Direction.LEFT, false));
addKeyPressedBinding(KeyEvent.VK_D, "right.pressed", new MoveAction(movement, Direction.RIGHT, true));
addKeyReleasedBinding(KeyEvent.VK_D, "right.released", new MoveAction(movement, Direction.RIGHT, false));
addKeyPressedBinding(KeyEvent.VK_W, "up.pressed", new MoveAction(movement, Direction.UP, true));
addKeyReleasedBinding(KeyEvent.VK_W, "up.released", new MoveAction(movement, Direction.UP, false));
addKeyPressedBinding(KeyEvent.VK_S, "down.pressed", new MoveAction(movement, Direction.DOWN, true));
addKeyReleasedBinding(KeyEvent.VK_S, "down.released", new MoveAction(movement, Direction.DOWN, false));
Timer timer = new Timer(100, new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
changeCoord();
}
});
timer.start();
System.out.println("Player Start X: " + pcX);
System.out.println("Player Start Y: " + pcY + "\n");
}
protected void addKeyBinding(int keyCode, String name, Action action){
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0), name, action);
}
protected void addKeyPressedBinding(int keyCode, String name, Action action) {
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0, false), name, action);
}
protected void addKeyReleasedBinding(int keyCode, String name, Action action) {
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0, true), name, action);
}
protected void addKeyBinding(KeyStroke keyStroke, String name, Action action) {
InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = getActionMap();
inputMap.put(keyStroke, name);
actionMap.put(name, action);
}
//Later in the code after the generation and painting of the map...............
public void changeCoord() {
if (movement.contains(Direction.UP)) {
up();//checks position and moves player if it is "safe"
System.out.println("Direction: Up, New X: " + pcX);
System.out.println("Direction: Up, New Y: " + pcY + "\n");
} else if (movement.contains(Direction.DOWN)) {
down();//checks position and moves player if it is "safe"
System.out.println("Direction: Down, New X: " + pcX);
System.out.println("Direction: Down, New Y: " + pcY + "\n");
}
if (movement.contains(Direction.LEFT)) {
left();//checks position and moves player if it is "safe"
System.out.println("Direction: Left, New X: " + pcX);
System.out.println("Direction: Left, New Y: " + pcY + "\n");
} else if (movement.contains(Direction.RIGHT)) {
right();//checks position and moves player if it is "safe"
System.out.println("Direction: Right, New X: " + pcX);
System.out.println("Direction: Right, New Y: " + pcY + "\n");
}
repaint();
}
public class MoveAction extends AbstractAction{
private Set<Direction> movement;
private Direction direction;
private boolean pressed;
public MoveAction(Set<Direction> movement, Direction direction, boolean pressed) {
this.movement = movement;
this.direction = direction;
this.pressed = pressed;
}
@Override
public void actionPerformed(ActionEvent e) {
if (pressed) {
movement.add(direction);
} else {
movement.remove(direction);
}
}
}
问题
我在键绑定过程中做错了什么吗?如果是这样,我该如何解决?如果不是我做错了什么?
如果您想自己动手,这里有一些工作代码:
主要Class
import javax.swing.JFrame;
public class gamePanelMain{
public static void main(String[] args){
JFrame frame = new JFrame();
gamePanel panel = new gamePanel();
frame.add(panel);
frame.setSize(520,540);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
panel.mapGen();
}//end main
}
无所不能的代码
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.image.*;
import javax.swing.Timer;
public class gamePanel extends JPanel
{
public enum Direction{
UP,
LEFT,
DOWN,
RIGHT;
}
private Set<Direction>movement;
public gamePanel()
{
setBounds(115,93,480,480);//sets the size and location of gamePanel (x,y,w,h)
setFocusable(true);
movement = new HashSet<>(4);
addKeyPressedBinding(KeyEvent.VK_A, "left.pressed", new MoveAction(movement, Direction.LEFT, true));
addKeyReleasedBinding(KeyEvent.VK_A, "left.released", new MoveAction(movement, Direction.LEFT, false));
addKeyPressedBinding(KeyEvent.VK_D, "right.pressed", new MoveAction(movement, Direction.RIGHT, true));
addKeyReleasedBinding(KeyEvent.VK_D, "right.released", new MoveAction(movement, Direction.RIGHT, false));
addKeyPressedBinding(KeyEvent.VK_W, "up.pressed", new MoveAction(movement, Direction.UP, true));
addKeyReleasedBinding(KeyEvent.VK_W, "up.released", new MoveAction(movement, Direction.UP, false));
addKeyPressedBinding(KeyEvent.VK_S, "down.pressed", new MoveAction(movement, Direction.DOWN, true));
addKeyReleasedBinding(KeyEvent.VK_S, "down.released", new MoveAction(movement, Direction.DOWN, false));
Timer timer = new Timer(100, new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
changeCoord();
}
});
timer.start();
System.out.println("Player Start X: " + pcX);
System.out.println("Player Start Y: " + pcY + "\n");
}
protected void addKeyBinding(int keyCode, String name, Action action){
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0), name, action);
}
protected void addKeyPressedBinding(int keyCode, String name, Action action) {
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0, false), name, action);
}
protected void addKeyReleasedBinding(int keyCode, String name, Action action) {
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0, true), name, action);
}
protected void addKeyBinding(KeyStroke keyStroke, String name, Action action) {
InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = getActionMap();
inputMap.put(keyStroke, name);
actionMap.put(name, action);
}
private Random tGenerator = new Random();//initialize a random number generator
int tmin = 1;
int tmax = 20;
int floor = 0; //initializes the variable floor to zero for later use
int dirt = 1; //initializes the variable dirt to one for later use
int stone = 2; //initializes the variable stone to two for later use
int width = 24; // width of playing area
int height = 24; //height of playing area
int x, y; // my x & y variables for coordinates
int[][] coords = new int[width][height]; //my array that I want to store the coordinates for later use in painting
int[] terrain = {floor, dirt, stone}; //my terrain that will determine the color of the paint
public void mapGen() //what should mark/generate the JPanel
{
for(x = 0; x < width; x++)
{
for(y = 0; y < height; y++)
{
int t = tGenerator.nextInt(tmax - tmin + 1) + tmin; // random generator for terrain
if(t <= 10)
{
coords[x][y] = terrain[floor]; //should mark the coordinates as floor
}
if(t >= 12 && t <=16)
{
coords[x][y] = terrain[stone]; //should mark the coordinates as stone
}
if(t >=17 && t <= 19)
{
coords[x][y] = terrain[dirt]; //should mark the coordinates as dirt
}
}
}
coords[0][0] = terrain[0]; // sets coordinate 0,0 to floor
coords[23][23] = terrain[0]; // sets coordinate 24,24 to floor
}//end mapGen
public int pcY = 0;
public int pcX = 0;
@Override
public void paintComponent(Graphics g)//what will paint each 20x20 square on the grid what it is assigned
{
super.paintComponent(g);
for(int x = 0; x < width; x++)
{
for(int y = 0; y < height; y++)
{
if(coords[x][y] == terrain[floor])// paints floor color at marked coordinates
{
g.setColor(new Color(249,249,249));
g.fillRect((x*20), (y*20), 20, 20);
}
if(coords[x][y] == terrain[dirt])// paints dirt color at marked coordinates
{
g.setColor(new Color(121,85,58));
g.fillRect((x*20), (y*20), 20, 20);
}
if(coords[x][y] == terrain[stone])// paints stone color at marked coordinates
{
g.setColor(new Color(143,143,143));
g.fillRect((x*20),(y*20),20,20);
}
}
}
g.setColor(Color.red);//creates the player "model"
g.fillOval((pcX*20),(pcY*20),20,20);
g.setColor(Color.black);
g.fillOval((23*20),(23*20),20,20);
}//end paintComponent
public void changeCoord() {
if (movement.contains(Direction.UP)) {
up();
System.out.println("Direction: Up, New X: " + pcX);
System.out.println("Direction: Up, New Y: " + pcY + "\n");
} else if (movement.contains(Direction.DOWN)) {
down();
System.out.println("Direction: Down, New X: " + pcX);
System.out.println("Direction: Down, New Y: " + pcY + "\n");
}
if (movement.contains(Direction.LEFT)) {
left();
System.out.println("Direction: Left, New X: " + pcX);
System.out.println("Direction: Left, New Y: " + pcY + "\n");
} else if (movement.contains(Direction.RIGHT)) {
right();
System.out.println("Direction: Right, New X: " + pcX);
System.out.println("Direction: Right, New Y: " + pcY + "\n");
}
repaint();
}
public class MoveAction extends AbstractAction{
private Set<Direction> movement;
private Direction direction;
private boolean pressed;
public MoveAction(Set<Direction> movement, Direction direction, boolean pressed) {
this.movement = movement;
this.direction = direction;
this.pressed = pressed;
}
@Override
public void actionPerformed(ActionEvent e) {
if (pressed) {
movement.add(direction);
} else {
movement.remove(direction);
}
}
}
public void up(){
if(coords[pcX][pcY--] == terrain[floor]){
coords[pcX][pcY] = coords[pcX][pcY--];
}
else if(coords[pcX][pcY--] == terrain[dirt]){
coords[pcX][pcY] = coords[pcX][pcY--];
}
else if(coords[pcX][pcY--] == terrain[stone]){
coords[pcX][pcY] = coords[pcX][pcY--];
}
}
public void down(){
if(coords[pcX][pcY++] == terrain[floor]){
pcY++;
}
else if(coords[pcX][pcY++] == terrain[dirt]){
pcY++;
}
else if(coords[pcX][pcY++] == terrain[stone]){
pcY++;
}
}
public void right(){
if(coords[pcX++][pcY] == terrain[floor]){
pcX += pcX+1;
}
else if(coords[pcX++][pcY] == terrain[dirt]){
pcX++;
}
else if(coords[pcX++][pcY] == terrain[stone]){
pcX++;
}
}
public void left(){
if(coords[pcX--][pcY] == terrain[floor]){
pcX--;
}
else if(coords[pcX--][pcY] == terrain[dirt]){
pcX--;
}
else if(coords[pcX--][pcY] == terrain[stone]){
pcX--;
}
}
}// end gamePanel
请 尝试将所有解释保持 "dumbed" 尽可能低,因为我仍在学习并且还不完全理解所有编码行话。
您不应该使用 addKeyPressedBinding 和 addKeyReleasedBinding。
这样它会触发两次操作,一次是在用户按下键时,一次是在用户释放键时。
我认为这不是您所期望的行为。
if(coords[pcX][pcY++] == terrain[floor]){
pcY++;
}
else if(coords[pcX][pcY++] == terrain[dirt]){
pcY++;
}
else if(coords[pcX][pcY++] == terrain[stone]){
pcY++;
}
I hit a keybinding for the first time it moves the character three "squares" away from the original position
您多次使用 "pcY++"。每次在 if 语句中使用该变量时,该变量都会递增。
所以你会得到随机结果,因为你每次移动时都会调用随机数量的 if 语句。
不要在 if 语句中对变量使用“++”。只有在通过测试时才增加变量。
此外,您不需要 up/down/left/right 方法。使用通用 Action 的要点是指定 Action 如何影响 x/y 位置。所以 changeCoord()
可能看起来像:
public void changeCoord()
{
int potentialX = pcX;
int potentialY = pcY;
if (movement.contains(Direction.LEFT)) potentialX--;
if (movement.contains(Direction.RIGHT)) potentialX++;
if (movement.contains(Direction.UP)) potentialY--;
if (movement.contains(Direction.DOWN)) potentialY++;
if (isValidMove(potentialX, potentially)
{
pcX = potentialX;
pcY = potentialY;
}
repaint();
}
private boolean isValidMove(int potentialX, int potentialY)
{
if (cords[potentialX][potentialY] == terrain[floor])
return true;
...
return false;
}
此外,我不太喜欢使用枚举。您仅限 up/down/lef/right。如果你想添加对角线移动的能力会怎样?查看 Motion Using the Keyboard 中的 KeyboardAnimation
示例。该示例中的 Action 允许您指定要移动到的点。因此,您不需要 if/else 检查枚举,您只需使用 Point 中指定的值来确定下一个位置。
问题
我正在为我的 class 中的最终项目制作游戏,并且我正在处理键绑定。键绑定的工作方式不尽如人意。让我解释一下:
所以 objective 是在向出口(黑点)移动的同时将你的角色一次 "square" 移动一个。每次您按指定方向(A、S、D、W)的键绑定时,它应该检查 "terrain" 并将您移动到 "floor"。
旁注:我还没有添加移除地形,因为我需要先让运动正常工作。
回到说明:
所以最大的问题是,当我第一次按下键绑定时,它会将字符从原始位置移开三个 "squares"。然后之后的任何移动都是随机的,有时会使玩家出界。我设置了它,所以每次激活键绑定时它都会打印出玩家的位置(见下面的代码)。我觉得我在按键绑定过程中做错了,因为这是我第一次进行按键绑定。
这是我的程序为我的角色运动提供的打印输出之一:
E:\Whosebug\KeyBindings>java gamePanelMain
Player Start X: 0
Player Start Y: 0
Direction: Right, New X: 3
Direction: Right, New Y: 0
Direction: Right, New X: 9
Direction: Right, New Y: 0
Direction: Right, New X: 12
Direction: Right, New Y: 0
Direction: Down, New X: 12
Direction: Down, New Y: 3
Direction: Down, New X: 12
Direction: Down, New Y: 6
Direction: Down, New X: 12
Direction: Down, New Y: 8
Direction: Left, New X: 10
Direction: Left, New Y: 8
Direction: Left, New X: 7
Direction: Left, New Y: 8
Direction: Left, New X: 4
Direction: Left, New Y: 8
Direction: Down, New X: 4
Direction: Down, New Y: 11
Direction: Down, New X: 4
Direction: Down, New Y: 13
Direction: Down, New X: 4
Direction: Down, New Y: 17
Direction: Right, New X: 7
Direction: Right, New Y: 17
Direction: Right, New X: 17
Direction: Right, New Y: 17
Direction: Right, New X: 20
Direction: Right, New Y: 17
Direction: Right, New X: 23
Direction: Right, New Y: 17
Direction: Down, New X: 23
Direction: Down, New Y: 20
Direction: Down, New X: 23
Direction: Down, New Y: 23
Direction: Up, New X: 23
Direction: Up, New Y: 21
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 24
at gamePanel.right(gamePanel.java:259)
at gamePanel.changeCoord(gamePanel.java:192)
at gamePanel.actionPerformed(gamePanel.java:46)
at javax.swing.Timer.fireActionPerformed(Unknown Source)
at javax.swing.Timer$DoPostEvent.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access0(Unknown Source)
at java.awt.EventQueue.run(Unknown Source)
at java.awt.EventQueue.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
如您所见,它是完全随机的,并且运动没有连接到随机生成器或类似的东西。此外,我还没有添加检查越界的代码,但我更担心先让这个动作正确。
现在我看了一个关于键绑定的 post (
这是我为键绑定添加的代码:
public enum Direction{
UP,
LEFT,
DOWN,
RIGHT;
}
private Set<Direction>movement;
public gamePanel()
{
setBounds(115,93,480,480);//sets the size and location of gamePanel (x,y,w,h)
setFocusable(true);
movement = new HashSet<>(4);
addKeyPressedBinding(KeyEvent.VK_A, "left.pressed", new MoveAction(movement, Direction.LEFT, true));
addKeyReleasedBinding(KeyEvent.VK_A, "left.released", new MoveAction(movement, Direction.LEFT, false));
addKeyPressedBinding(KeyEvent.VK_D, "right.pressed", new MoveAction(movement, Direction.RIGHT, true));
addKeyReleasedBinding(KeyEvent.VK_D, "right.released", new MoveAction(movement, Direction.RIGHT, false));
addKeyPressedBinding(KeyEvent.VK_W, "up.pressed", new MoveAction(movement, Direction.UP, true));
addKeyReleasedBinding(KeyEvent.VK_W, "up.released", new MoveAction(movement, Direction.UP, false));
addKeyPressedBinding(KeyEvent.VK_S, "down.pressed", new MoveAction(movement, Direction.DOWN, true));
addKeyReleasedBinding(KeyEvent.VK_S, "down.released", new MoveAction(movement, Direction.DOWN, false));
Timer timer = new Timer(100, new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
changeCoord();
}
});
timer.start();
System.out.println("Player Start X: " + pcX);
System.out.println("Player Start Y: " + pcY + "\n");
}
protected void addKeyBinding(int keyCode, String name, Action action){
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0), name, action);
}
protected void addKeyPressedBinding(int keyCode, String name, Action action) {
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0, false), name, action);
}
protected void addKeyReleasedBinding(int keyCode, String name, Action action) {
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0, true), name, action);
}
protected void addKeyBinding(KeyStroke keyStroke, String name, Action action) {
InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = getActionMap();
inputMap.put(keyStroke, name);
actionMap.put(name, action);
}
//Later in the code after the generation and painting of the map...............
public void changeCoord() {
if (movement.contains(Direction.UP)) {
up();//checks position and moves player if it is "safe"
System.out.println("Direction: Up, New X: " + pcX);
System.out.println("Direction: Up, New Y: " + pcY + "\n");
} else if (movement.contains(Direction.DOWN)) {
down();//checks position and moves player if it is "safe"
System.out.println("Direction: Down, New X: " + pcX);
System.out.println("Direction: Down, New Y: " + pcY + "\n");
}
if (movement.contains(Direction.LEFT)) {
left();//checks position and moves player if it is "safe"
System.out.println("Direction: Left, New X: " + pcX);
System.out.println("Direction: Left, New Y: " + pcY + "\n");
} else if (movement.contains(Direction.RIGHT)) {
right();//checks position and moves player if it is "safe"
System.out.println("Direction: Right, New X: " + pcX);
System.out.println("Direction: Right, New Y: " + pcY + "\n");
}
repaint();
}
public class MoveAction extends AbstractAction{
private Set<Direction> movement;
private Direction direction;
private boolean pressed;
public MoveAction(Set<Direction> movement, Direction direction, boolean pressed) {
this.movement = movement;
this.direction = direction;
this.pressed = pressed;
}
@Override
public void actionPerformed(ActionEvent e) {
if (pressed) {
movement.add(direction);
} else {
movement.remove(direction);
}
}
}
问题 我在键绑定过程中做错了什么吗?如果是这样,我该如何解决?如果不是我做错了什么?
如果您想自己动手,这里有一些工作代码:
主要Class
import javax.swing.JFrame;
public class gamePanelMain{
public static void main(String[] args){
JFrame frame = new JFrame();
gamePanel panel = new gamePanel();
frame.add(panel);
frame.setSize(520,540);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
panel.mapGen();
}//end main
}
无所不能的代码
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.image.*;
import javax.swing.Timer;
public class gamePanel extends JPanel
{
public enum Direction{
UP,
LEFT,
DOWN,
RIGHT;
}
private Set<Direction>movement;
public gamePanel()
{
setBounds(115,93,480,480);//sets the size and location of gamePanel (x,y,w,h)
setFocusable(true);
movement = new HashSet<>(4);
addKeyPressedBinding(KeyEvent.VK_A, "left.pressed", new MoveAction(movement, Direction.LEFT, true));
addKeyReleasedBinding(KeyEvent.VK_A, "left.released", new MoveAction(movement, Direction.LEFT, false));
addKeyPressedBinding(KeyEvent.VK_D, "right.pressed", new MoveAction(movement, Direction.RIGHT, true));
addKeyReleasedBinding(KeyEvent.VK_D, "right.released", new MoveAction(movement, Direction.RIGHT, false));
addKeyPressedBinding(KeyEvent.VK_W, "up.pressed", new MoveAction(movement, Direction.UP, true));
addKeyReleasedBinding(KeyEvent.VK_W, "up.released", new MoveAction(movement, Direction.UP, false));
addKeyPressedBinding(KeyEvent.VK_S, "down.pressed", new MoveAction(movement, Direction.DOWN, true));
addKeyReleasedBinding(KeyEvent.VK_S, "down.released", new MoveAction(movement, Direction.DOWN, false));
Timer timer = new Timer(100, new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
changeCoord();
}
});
timer.start();
System.out.println("Player Start X: " + pcX);
System.out.println("Player Start Y: " + pcY + "\n");
}
protected void addKeyBinding(int keyCode, String name, Action action){
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0), name, action);
}
protected void addKeyPressedBinding(int keyCode, String name, Action action) {
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0, false), name, action);
}
protected void addKeyReleasedBinding(int keyCode, String name, Action action) {
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0, true), name, action);
}
protected void addKeyBinding(KeyStroke keyStroke, String name, Action action) {
InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = getActionMap();
inputMap.put(keyStroke, name);
actionMap.put(name, action);
}
private Random tGenerator = new Random();//initialize a random number generator
int tmin = 1;
int tmax = 20;
int floor = 0; //initializes the variable floor to zero for later use
int dirt = 1; //initializes the variable dirt to one for later use
int stone = 2; //initializes the variable stone to two for later use
int width = 24; // width of playing area
int height = 24; //height of playing area
int x, y; // my x & y variables for coordinates
int[][] coords = new int[width][height]; //my array that I want to store the coordinates for later use in painting
int[] terrain = {floor, dirt, stone}; //my terrain that will determine the color of the paint
public void mapGen() //what should mark/generate the JPanel
{
for(x = 0; x < width; x++)
{
for(y = 0; y < height; y++)
{
int t = tGenerator.nextInt(tmax - tmin + 1) + tmin; // random generator for terrain
if(t <= 10)
{
coords[x][y] = terrain[floor]; //should mark the coordinates as floor
}
if(t >= 12 && t <=16)
{
coords[x][y] = terrain[stone]; //should mark the coordinates as stone
}
if(t >=17 && t <= 19)
{
coords[x][y] = terrain[dirt]; //should mark the coordinates as dirt
}
}
}
coords[0][0] = terrain[0]; // sets coordinate 0,0 to floor
coords[23][23] = terrain[0]; // sets coordinate 24,24 to floor
}//end mapGen
public int pcY = 0;
public int pcX = 0;
@Override
public void paintComponent(Graphics g)//what will paint each 20x20 square on the grid what it is assigned
{
super.paintComponent(g);
for(int x = 0; x < width; x++)
{
for(int y = 0; y < height; y++)
{
if(coords[x][y] == terrain[floor])// paints floor color at marked coordinates
{
g.setColor(new Color(249,249,249));
g.fillRect((x*20), (y*20), 20, 20);
}
if(coords[x][y] == terrain[dirt])// paints dirt color at marked coordinates
{
g.setColor(new Color(121,85,58));
g.fillRect((x*20), (y*20), 20, 20);
}
if(coords[x][y] == terrain[stone])// paints stone color at marked coordinates
{
g.setColor(new Color(143,143,143));
g.fillRect((x*20),(y*20),20,20);
}
}
}
g.setColor(Color.red);//creates the player "model"
g.fillOval((pcX*20),(pcY*20),20,20);
g.setColor(Color.black);
g.fillOval((23*20),(23*20),20,20);
}//end paintComponent
public void changeCoord() {
if (movement.contains(Direction.UP)) {
up();
System.out.println("Direction: Up, New X: " + pcX);
System.out.println("Direction: Up, New Y: " + pcY + "\n");
} else if (movement.contains(Direction.DOWN)) {
down();
System.out.println("Direction: Down, New X: " + pcX);
System.out.println("Direction: Down, New Y: " + pcY + "\n");
}
if (movement.contains(Direction.LEFT)) {
left();
System.out.println("Direction: Left, New X: " + pcX);
System.out.println("Direction: Left, New Y: " + pcY + "\n");
} else if (movement.contains(Direction.RIGHT)) {
right();
System.out.println("Direction: Right, New X: " + pcX);
System.out.println("Direction: Right, New Y: " + pcY + "\n");
}
repaint();
}
public class MoveAction extends AbstractAction{
private Set<Direction> movement;
private Direction direction;
private boolean pressed;
public MoveAction(Set<Direction> movement, Direction direction, boolean pressed) {
this.movement = movement;
this.direction = direction;
this.pressed = pressed;
}
@Override
public void actionPerformed(ActionEvent e) {
if (pressed) {
movement.add(direction);
} else {
movement.remove(direction);
}
}
}
public void up(){
if(coords[pcX][pcY--] == terrain[floor]){
coords[pcX][pcY] = coords[pcX][pcY--];
}
else if(coords[pcX][pcY--] == terrain[dirt]){
coords[pcX][pcY] = coords[pcX][pcY--];
}
else if(coords[pcX][pcY--] == terrain[stone]){
coords[pcX][pcY] = coords[pcX][pcY--];
}
}
public void down(){
if(coords[pcX][pcY++] == terrain[floor]){
pcY++;
}
else if(coords[pcX][pcY++] == terrain[dirt]){
pcY++;
}
else if(coords[pcX][pcY++] == terrain[stone]){
pcY++;
}
}
public void right(){
if(coords[pcX++][pcY] == terrain[floor]){
pcX += pcX+1;
}
else if(coords[pcX++][pcY] == terrain[dirt]){
pcX++;
}
else if(coords[pcX++][pcY] == terrain[stone]){
pcX++;
}
}
public void left(){
if(coords[pcX--][pcY] == terrain[floor]){
pcX--;
}
else if(coords[pcX--][pcY] == terrain[dirt]){
pcX--;
}
else if(coords[pcX--][pcY] == terrain[stone]){
pcX--;
}
}
}// end gamePanel
请 尝试将所有解释保持 "dumbed" 尽可能低,因为我仍在学习并且还不完全理解所有编码行话。
您不应该使用 addKeyPressedBinding 和 addKeyReleasedBinding。 这样它会触发两次操作,一次是在用户按下键时,一次是在用户释放键时。
我认为这不是您所期望的行为。
if(coords[pcX][pcY++] == terrain[floor]){
pcY++;
}
else if(coords[pcX][pcY++] == terrain[dirt]){
pcY++;
}
else if(coords[pcX][pcY++] == terrain[stone]){
pcY++;
}
I hit a keybinding for the first time it moves the character three "squares" away from the original position
您多次使用 "pcY++"。每次在 if 语句中使用该变量时,该变量都会递增。
所以你会得到随机结果,因为你每次移动时都会调用随机数量的 if 语句。
不要在 if 语句中对变量使用“++”。只有在通过测试时才增加变量。
此外,您不需要 up/down/left/right 方法。使用通用 Action 的要点是指定 Action 如何影响 x/y 位置。所以 changeCoord()
可能看起来像:
public void changeCoord()
{
int potentialX = pcX;
int potentialY = pcY;
if (movement.contains(Direction.LEFT)) potentialX--;
if (movement.contains(Direction.RIGHT)) potentialX++;
if (movement.contains(Direction.UP)) potentialY--;
if (movement.contains(Direction.DOWN)) potentialY++;
if (isValidMove(potentialX, potentially)
{
pcX = potentialX;
pcY = potentialY;
}
repaint();
}
private boolean isValidMove(int potentialX, int potentialY)
{
if (cords[potentialX][potentialY] == terrain[floor])
return true;
...
return false;
}
此外,我不太喜欢使用枚举。您仅限 up/down/lef/right。如果你想添加对角线移动的能力会怎样?查看 Motion Using the Keyboard 中的 KeyboardAnimation
示例。该示例中的 Action 允许您指定要移动到的点。因此,您不需要 if/else 检查枚举,您只需使用 Point 中指定的值来确定下一个位置。