问题
<小时/> 我正在为我的一个班级做最后一个项目的游戏,我正在研究Keybinding。 Keybindings的工作方式并非如此。让我解释一下:
因此,目标是在朝向出口(黑点)移动时,一次将角色移动一个“方形”。每次按指定方向(A,S,D,W)的键绑定时,它应检查“地形”并将其移至“地板”。
侧注:我还没有添加移除地形,因为我需要移动才能正常工作。
回到解释:
所以最大的问题是,当我第一次敲击键绑定时,它会将角色从原始位置移开三个“方块”。那之后的任何动作都是随机的,有时会让玩家超出范围。我已将其设置为每次激活键绑定时打印出播放器的位置(参见下面的代码)。我有一种感觉,我做了一些错误的键绑定过程,因为这是我第一次键入绑定的东西。
这是我的节目为我的角色运动提供的打印输出之一:
E:\StackOverflow\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$1.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.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.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)
正如您所看到的那样,它是完全随机的,并且运动没有连接到随机发生器或类似的东西。此外,我还没有添加代码来检查是否有界限,但我更担心的是首先让这个动作正确。
现在我查看了一个关于键绑定(Can't repaint my JFrame/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);
}
//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);
}
}
}
问题 我是否在键绑定过程中出错了?如果是这样,我该如何解决?如果不是我做错了什么?
如果您想自己搞砸一下,可以使用以下代码:
主要类
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
请尝试让所有解释尽可能“愚蠢”,因为我还在学习,并且还不了解所有的编码术语。
答案 0 :(得分:1)
if(coords[pcX][pcY++] == terrain[floor]){
pcY++;
}
else if(coords[pcX][pcY++] == terrain[dirt]){
pcY++;
}
else if(coords[pcX][pcY++] == terrain[stone]){
pcY++;
}
我第一次击中了一个键绑定,它将角色从原始位置移开了三个“方块”
您多次使用“pcY ++”。每次在if语句中使用该变量时,变量都会递增。
因此,您会得到随机结果,因为每次移动时都会调用随机数量的if语句。
不要在if语句中对变量使用“++”。只有在通过测试时才会增加变量。
此外,您不需要上/下/左/右方法。使用常见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;
}
另外,我不是使用枚举的忠实粉丝。您仅限于上/下/左/右。如果您想要添加对角线移动的能力,会发生什么?查看Motion Using the Keyboard中的KeyboardAnimation
示例。该示例中的Action允许您指定要移动的点。因此,您不需要if / else检查枚举,只需使用Point中指定的值来确定下一个位置。
答案 1 :(得分:0)
您不应该使用addKeyPressedBinding和addKeyReleasedBinding。 这样它将触发动作两次,一次是当用户按下键时,一次是当用户释放它时。
我认为这不是你期望的行为。