2016-05-09 3 views
0

Problem KeyBindings scheinen unsachgemäß zu arbeiten und wissen nicht warum | Java


Ich mache ein Spiel für ein Abschlussprojekt in einer meiner Klasse und ich arbeite an der Keybinding. Die Keybindings funktionieren einfach nicht wie sie sollen. Lassen Sie mich erklären:

So ist das Ziel, Ihren Charakter ein "Quadrat" auf einmal zu bewegen, während Sie sich in Richtung zum Ausgang bewegen (schwarzer Punkt). Jedes Mal, wenn Sie die Tastenkombination für die angegebene Richtung (A, S, D, W) drücken, sollte das "Terrain" überprüft und Sie zu diesem bewegt werden, wenn es sich um "Floor" handelt.

Seitennotiz: Ich muss noch hinzufügen, Gelände zu entfernen, weil ich die Bewegung zuerst richtig funktionieren muss.

Zurück zur Erklärung: Also das größte Problem ist, dass, wenn ich eine Tastatur zum ersten Mal trifft, es das Zeichen drei "Quadrate" von der ursprünglichen Position entfernt. Dann ist jede Bewegung danach willkürlich und wird den Spieler manchmal außer Reichweite bringen. Ich habe es so eingerichtet, dass es den Standort des Players jedes Mal ausdruckt, wenn eine Tastenkombination aktiviert wird (siehe unten stehenden Code). Ich habe das Gefühl, dass ich etwas falsch gemacht habe, als ich das erste Mal etwas mit der Tastatur verbunden habe.
Hier eines der Ausdrucke, die mein Programm gab mir für die Bewegung meines Charakters:

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) 

Wie Sie es ist völlig zufällig und die Bewegung sehen kann, ist nicht so mit einem Zufallsgenerator oder irgendetwas verbunden. Außerdem muss ich noch hinzufügen, dass der Code außerhalb des zulässigen Bereichs liegt, aber ich mache mir mehr Sorgen darüber, diese Bewegung zuerst zu korrigieren.

Jetzt schaute ich auf einen Beitrag auf Tastenkürzel (Can't repaint my JFrame/JPanel) und versuchte, die Technik auf mein Spiel für die Tastenbindeoperation anzuwenden. Ich weiß nicht, was ich falsch gemacht habe, ist Teil des Problems.

Hier ist der Code, den ich nur für das Keybinding hinzugefügt:

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); 
      } 
     }   
     } 

Frage Bin ich etwas falsch mit dem Keybinding Prozess zu tun? Und wenn ja, wie repariere ich es? Wenn nicht, was habe ich falsch gemacht?

Hier finden Sie einige Arbeitscode, wenn Sie mit ihm herum würden sich gerne:

Hauptklasse

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 
} 

Code, der alles

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 

tut Bitte versuchen Sie und behalten Sie alle Erklärungen a s so "dumbled" wie möglich, da ich noch lerne und den ganzen Programmiersprache noch nicht recht verstehe.

+0

@ Andrew Thompson Oops, sorry lassen Sie mich für Sie ganz schnell – TheMrBaggins

+1

Mögliche Duplikat umformatieren [KeyListener, keyPressed gegen keyTyped] (http://stackoverflow.com/questions/7071757/keylistener-keypressed-versus-keytyped) – bns

+0

@ Ich habe mir diesen Beitrag angesehen und es scheint mein Problem nicht anzugehen. Wieder bin ich neu in der Tastatur, also vermisse ich vielleicht etwas – TheMrBaggins

Antwort

1
if(coords[pcX][pcY++] == terrain[floor]){ 
    pcY++; 
} 

else if(coords[pcX][pcY++] == terrain[dirt]){ 
    pcY++; 
} 

else if(coords[pcX][pcY++] == terrain[stone]){ 
    pcY++; 
}   

traf ich einen Keybinding zum ersten Mal den Charakter drei „Quadrate“ entfernt

Sie verwenden „pcy ++“ mehrfach von der ursprünglichen Position bewegt. Jedes Mal, wenn Sie diese Variable in der if-Anweisung verwenden, wird die Variable inkrementiert.

So erhalten Sie zufällige Ergebnisse, weil Sie bei jeder Bewegung eine zufällige Anzahl von if-Anweisungen aufrufen.

Verwenden Sie nicht "++" für eine Variable in Ihren if-Anweisungen. Sie erhöhen Ihre Variable nur, wenn sie den Test besteht.

Außerdem benötigen Sie keine up/down/left/right-Methoden. Der Sinn einer gemeinsamen Aktion besteht darin, festzulegen, wie sich die Aktion auf den x/y-Ort auswirkt. So könnte die changeCoord() in etwa so aussehen:

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; 
} 

Auch ich bin kein großer Fan von den Aufzählungen verwenden. Sie sind beschränkt auf nur auf/ab/links/rechts. Was passiert, wenn Sie die Fähigkeit, sich diagonal zu bewegen, hinzufügen möchten? Schauen Sie sich das KeyboardAnimation Beispiel in Motion Using the Keyboard an. Mit der Aktion in diesem Beispiel können Sie einen Punkt angeben, zu dem Sie wechseln möchten. Sie brauchen also nicht, wenn/use nach der Enumeration sucht, Sie verwenden einfach die im Point angegebenen Werte, um den nächsten Ort zu bestimmen.

+0

Also, wie überprüfe ich das nächste "Quadrat"? – TheMrBaggins

+0

@TheMrBaggins, verwenden Sie eine separate Variable. Siehe Bearbeiten. – camickr

+0

Alrighty wird es ausprobieren, wenn ich wieder auf meinem PC bin. Vielen Dank für Ihre Hilfe – TheMrBaggins

0

Sie sollten addKeyPressedBinding und addKeyReleasedBinding nicht verwenden. Auf diese Weise wird die Aktion zweimal ausgelöst, einmal wenn der Benutzer die Taste drückt und einmal wenn der Benutzer sie loslässt.

Ich glaube nicht, dass das das Verhalten ist, das Sie erwarten.

+0

es wird nichts für diese Aktion tun. Lesen Sie http://StackOverflow.com/Questions/7071757/keylistener-keypressed-versus-KeyTyped, um über verschiedene Auslöser zu lernen – bns

+0

Ich habe versucht, die addKeyReleasedBinding und wenn ich ein "D" einmal gedrückt und ließ den Charakter in Bewegung – TheMrBaggins

+0

bewegt Bitte lies den Link, den ich vorher gesendet habe. Wenn Sie möchten, dass die Aktion ausgeführt wird, während die Taste gedrückt wird, und mehrfach ausgelöst werden kann (z. B. eine Waffe, die weiter feuert), drücken Sie tastenbetätigt. Wenn Sie möchten, dass die Aktion einmal ausgeführt wird, wenn Sie den Schlüssel loslassen, verwenden Sie den freigegebenen Schlüssel. Wenn Sie möchten, dass die Aktion ausgeführt wird, nachdem ein Zeichen eingegeben wurde (z. B. Umschalt + 7, um das Zeichen & einzugeben), dann verwenden Sie keytyped – bns

Verwandte Themen