2016-01-26 1 views
1

Je suis en train de coder un jeu pour mon projet final en Java, notre professeur nous a fourni une classe Board qui est un composant qui permet de placer et de retirer des pinces sur un jeu virtuel au lieu d'avoir à en coder un nous-mêmes. J'essaye d'ajouter la liaison de clé au composant de conseil mais l'action que je veux exécuter sur la presse de clé se produit quand j'exécute le programme mais il ne fonctionnera pas quand je tape une clé.L'action Keybind s'exécute au démarrage mais pas à partir de la touche

La classe de la carte a déjà une méthode pour obtenir la position cliquée sur le composant et je pense que cela pourrait interférer avec mon code mais je ne suis pas sûr.

C'est ma classe de jeu où j'ai essayé d'ajouter raccourci clavier

package rpgGame; 

import java.awt.Color; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import java.util.ArrayList; 
import java.util.List; 
import javax.swing.AbstractAction; 
import javax.swing.Action; 
import javax.swing.JComponent; 
import javax.swing.KeyStroke; 

public class RPGGame 
{ 
    public static final GameWorld WORLD_MAP = new GameWorld(); 
    public static Board LOCAL_MAP = new Board(20,50); 

    public static List<Mobile> allMobs = new ArrayList<Mobile>(); 
    public static final Player PLAYER = new Player(); 

    public static int xIndex = ((GameWorld.WORLD_SIZE-1)/2) - (50/2); 
    public static int yIndex = ((GameWorld.WORLD_SIZE-1)/2) - (20/2); 

    public static boolean boardUpdate = true; 

    public enum Direction {RIGHT,LEFT,UP,DOWN} 

    private static final String MOVE_PLAYER_UP = "move up"; 
    private static final String MOVE_PLAYER_LEFT = "move left"; 
    private static final String MOVE_PLAYER_RIGHT = "move right"; 
    private static final String MOVE_PLAYER_DOWN = "move down"; 

    public static final Thread SYNC_BOARD = new Thread() 
    { 
     public synchronized void run() 
     { 
      while (boardUpdate) 
      { 
       for (int i = 0; i < 50; i++) 
       { 
        for (int j = 0; j < 20; j++) 
        { 
         if (WORLD_MAP.isOccupied(i+xIndex, j+yIndex)) 
         { 
          LOCAL_MAP.putPeg(Color.RED, j, i); 
          System.out.println("Successfully Updated"); 
         } 
         else 
         { 
          LOCAL_MAP.putPeg(Color.GRAY, j,i); 

         } 
        } 
       } 
       boardUpdate = false; 
      } 
     } 
    }; 

    public RPGGame() 
    { 
     generateMobs(200); 
     placeMobs(); 
     placePlayer(); 
     SYNC_BOARD.run(); 

     LOCAL_MAP.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), MOVE_PLAYER_UP); 
     LOCAL_MAP.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), MOVE_PLAYER_UP); 
     LOCAL_MAP.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), MOVE_PLAYER_LEFT); 
     LOCAL_MAP.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), MOVE_PLAYER_LEFT); 
     LOCAL_MAP.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), MOVE_PLAYER_RIGHT); 
     LOCAL_MAP.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), MOVE_PLAYER_RIGHT); 
     LOCAL_MAP.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), MOVE_PLAYER_DOWN); 
     LOCAL_MAP.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), MOVE_PLAYER_DOWN); 

     LOCAL_MAP.getActionMap().put(MOVE_PLAYER_UP, new MoveAction(Direction.UP)); 
     LOCAL_MAP.getActionMap().put(MOVE_PLAYER_LEFT, new MoveAction(Direction.LEFT)); 
     LOCAL_MAP.getActionMap().put(MOVE_PLAYER_RIGHT, new MoveAction(Direction.RIGHT)); 
     LOCAL_MAP.getActionMap().put(MOVE_PLAYER_DOWN, new MoveAction(Direction.DOWN)); 
    } 

    public static void main(String[] args) 
    { 
     new RPGGame(); 
    } 

    public static void generateMobs(int numOfMobs) 
    { 
     for (int i=0; i<numOfMobs; i++) 
     { 
      allMobs.add(new Mobile()); 
     } 
    } 

    public static void generateMobs() 
    { 
     int numOfMobs = (int)(Math.random()*500); 
     for (int i=0;i<numOfMobs; i++) 
     { 
      allMobs.add(new Mobile()); 
     } 
    } 

    public static void placeMobs() 
    { 
     for (int i=0; i<allMobs.size(); i++) 
     { 
      //i is used as a placeholder value for points until I create a random number generator. 
      WORLD_MAP.placeCharacter(i, i,allMobs.get(i)); 
      allMobs.get(i).setLocation(i, i); 
     } 
    } 

    public static void placePlayer() 
    { 
     WORLD_MAP.placeCharacter(249, 249, PLAYER); 
     PLAYER.setLocation(249, 249); 
    } 

    @SuppressWarnings("serial") 
    public class MoveAction extends AbstractAction 
    { 
     Direction direction; 

     public MoveAction(Direction direction) 
     { 
      if (direction.equals(Direction.RIGHT)) 
      { 
       int x = PLAYER.getX(); 
       int y = PLAYER.getY(); 
       WORLD_MAP.moveCharacter(x+1, y, x, y); 
       PLAYER.move(1, 0); 
       boardUpdate = true; 
       System.out.println("MOVE RIGHT"); 
      } 
      if (direction.equals(Direction.LEFT)) 
      { 
       int x = PLAYER.getX(); 
       int y = PLAYER.getY(); 
       WORLD_MAP.moveCharacter(x, y, x-1, y); 
       PLAYER.move(-1, 0); 
       boardUpdate = true; 
       System.out.println("MOVE LEFT"); 
      } 
      if (direction.equals(Direction.UP)) 
      { 
       int x = PLAYER.getX(); 
       int y = PLAYER.getY(); 
       WORLD_MAP.moveCharacter(x, y, x, y+1); 
       PLAYER.move(0, 1); 
       boardUpdate = true; 
       System.out.println("MOVE UP"); 
      } 
      if (direction.equals(Direction.DOWN)) 
      { 
       int x = PLAYER.getX(); 
       int y = PLAYER.getY(); 
       WORLD_MAP.moveCharacter(x, y, x, y-1); 
       PLAYER.move(0, -1); 
       boardUpdate = true; 
       System.out.println("MOVE DOWN"); 
      } 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) 
     { 

     } 

    } 
} 

C'est la classe

package rpgGame; 
import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.event.*; 

/** Board GUI for implementation with various games 
* Author: Kirill Levin, Troy Vasiga, Chris Ingram 
*/ 

@SuppressWarnings("serial") 
public class Board extends JPanel 
{ 
    private static final int X_DIM = 60; 
    private static final int Y_DIM = 60; 
    private static final int X_OFFSET = 30; 
    private static final int Y_OFFSET = 30; 
    private static final double MIN_SCALE = 0.25; 
    private static final int GAP = 10; 
    private static final int FONT_SIZE = 16; 

    // Grid colours 
    private static final Color GRID_COLOR_A = new Color(153,255,102); 
    private static final Color GRID_COLOR_B = new Color(136,255,77); 

    private Color[][] grid; 
    private Point lastClick; // How the mouse handling thread communicates 
    // to the board where the last click occurred 
    private String message = ""; 
    private int numLines = 0; 
    private double[][] line = new double[4][100]; // maximum number of lines is 100 
    private int columns, rows; 

    private int originalWidth; 
    private int originalHeight; 
    private double scale; 

    /** A constructor to build a 2D board. 
    */ 
    public Board (int rows, int columns) 
    { 
     super(true); 
     JFrame boardFrame = new JFrame("Board game"); 

     this.columns = columns; 
     this.rows = rows; 
     originalWidth = 2*X_OFFSET+X_DIM*columns; 
     originalHeight = 2*Y_OFFSET+Y_DIM*rows+GAP+FONT_SIZE; 

     this.setPreferredSize(new Dimension(originalWidth, originalHeight)); 

     boardFrame.setResizable(true); 

     this.grid = new Color[columns][rows]; 

     this.addMouseListener(
       new MouseInputAdapter() 
       { 
        /** A method that is called when the mouse is clicked 
        */ 
        public void mouseClicked(MouseEvent e) 
        { 
         int x = (int)e.getPoint().getX(); 
         int y = (int)e.getPoint().getY(); 

         // We need to by synchronized to the parent class so we can wake 
         // up any threads that might be waiting for us 
         synchronized(Board.this) 
         { 
          int curX = (int)Math.round(X_OFFSET*scale); 
          int curY = (int)Math.round(Y_OFFSET*scale); 
          int nextX = (int)Math.round((X_OFFSET+X_DIM*grid.length)*scale); 
          int nextY = (int)Math.round((Y_OFFSET+Y_DIM*grid[0].length)*scale); 

          // Subtract one from high end so clicks on the black edge 
          // don't yield a row or column outside of board because of 
          // the way the coordinate is calculated. 
          if (x >= curX && y >= curY && x < nextX && y < nextY) 
          { 
           lastClick = new Point(y,x); 
           // Notify any threads that would be waiting for a mouse click 
           Board.this.notifyAll() ; 
          } /* if */ 
         } /* synchronized */ 
        } /* mouseClicked */ 
       } /* anonymous MouseInputAdapater */ 
       ); 

     boardFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     boardFrame.setContentPane(this); 
     boardFrame.pack(); 
     boardFrame.setVisible(true); 
    } 

    /** A constructor to build a 1D board. 
    */ 
    public Board (int cols) 
    { 
     this(1, cols); 
    } 

    private void paintText(Graphics g) 
    { 
     g.setColor(this.getBackground()); 
     g.setFont(new Font(g.getFont().getFontName(), Font.ITALIC+Font.BOLD, (int)(Math.round(FONT_SIZE*scale)))); 

     int x = (int)Math.round(X_OFFSET*scale); 
     int y = (int)Math.round((Y_OFFSET+Y_DIM*grid[0].length)*scale + GAP ) ; 

     g.fillRect(x,y, this.getSize().width, (int)Math.round(GAP+FONT_SIZE*scale)); 
     g.setColor(Color.black); 
     g.drawString(message, x, y + (int)Math.round(FONT_SIZE*scale)); 
    } 

    private void paintGrid(Graphics g) 
    { 
     for (int i = 0; i < this.grid.length; i++) 
     { 
      for (int j = 0; j < this.grid[i].length; j++) 
      {  
       if ((i%2 == 0 && j%2 != 0) || (i%2 != 0 && j%2 == 0)) 
        g.setColor(GRID_COLOR_A); 
       else 
        g.setColor(GRID_COLOR_B); 
       int curX = (int)Math.round((X_OFFSET+X_DIM*i)*scale); 
       int curY = (int)Math.round((Y_OFFSET+Y_DIM*j)*scale); 
       int nextX = (int)Math.round((X_OFFSET+X_DIM*(i+1))*scale); 
       int nextY = (int)Math.round((Y_OFFSET+Y_DIM*(j+1))*scale); 
       int deltaX = nextX-curX; 
       int deltaY = nextY-curY; 

       g.fillRect(curX, curY, deltaX, deltaY); 
       Color curColour = this.grid[i][j]; 
       if (curColour != null) // Draw pegs if they exist 
       { 
        g.setColor(curColour); 
        g.fillOval(curX+deltaX/4, curY+deltaY/4, deltaX/2, deltaY/2); 
       } 
      } 
     } 
     ((Graphics2D) g).setStroke(new BasicStroke(0.5f)); 
     g.setColor(Color.BLACK); 
     int curX = (int)Math.round(X_OFFSET*scale); 
     int curY = (int)Math.round(Y_OFFSET*scale); 
     int nextX = (int)Math.round((X_OFFSET+X_DIM*grid.length)*scale); 
     int nextY = (int)Math.round((Y_OFFSET+Y_DIM*grid[0].length)*scale); 
     g.drawRect(curX, curY, nextX-curX, nextY-curY); 
    } 

    private void drawLine(Graphics g) 
    { 
     for (int i =0; i < numLines; i++) 
     { 
      ((Graphics2D) g).setStroke(new BasicStroke(5.0f*(float)scale)); 
      g.drawLine((int)Math.round((X_OFFSET+X_DIM/2.0+line[0][i]*X_DIM)*scale), 
        (int)Math.round((Y_OFFSET+Y_DIM/2.0+line[1][i]*Y_DIM)*scale), 
        (int)Math.round((X_OFFSET+X_DIM/2.0+line[2][i]*X_DIM)*scale), 
        (int)Math.round((Y_OFFSET+Y_DIM/2.0+line[3][i]*Y_DIM)*scale)); 
     } 
    } 

    /** 
    * Convert a String to the corresponding Color defaulting to Black 
    * with an invald input 
    */ 
    /*private Color convertColour(String theColour) 
    { 
     for(int i=0; i<COLOUR_NAMES.length; i++) 
     { 
      if(COLOUR_NAMES[i].equalsIgnoreCase(theColour)) 
       return COLOURS[i]; 
     } 

     return DEFAULT_COLOUR; 
    }*/ 


    /** The method that draws everything 
    */ 
    public void paintComponent(Graphics g) 
    { 
     this.setScale(); 
     this.paintGrid(g); 
     this.drawLine(g); 
     this.paintText(g); 
    } 

    public void setScale() 
    { 
     double width = (0.0+this.getSize().width)/this.originalWidth; 
     double height = (0.0+this.getSize().height)/this.originalHeight; 
     this.scale = Math.max(Math.min(width,height), MIN_SCALE); 
    } 

    /** Sets the message to be displayed under the board 
    */ 
    public void displayMessage(String theMessage) 
    { 
     message = theMessage; 
     this.repaint(); 
    } 


    /** This method will save the value of the colour of the peg in a specific 
    * spot. theColour is restricted to 
    * "yellow", "blue", "cyan", "green", "pink", "white", "red", "orange" 
    * Otherwise the colour black will be used. 
    */ 
    public void putPeg(Color colour, int row, int col) 
    { 
     this.grid[col][row] = colour; 
     this.repaint(); 
    } 

    /** Same as putPeg above but for 1D boards 
    */ 
    public void putPeg(Color colour, int col) 
    { 
     this.putPeg(colour, 0, col); 
    } 

    /** Remove a peg from the gameboard. 
    */ 
    public void removePeg(int row, int col) 
    { 
     this.grid[col][row] = null; 
     repaint(); 
    } 

    /** Same as removePeg above but for 1D boards 
    */ 
    public void removePeg(int col) 
    { 
     this.grid[col][0] = null; 
     repaint(); 
    } 

    /** Draws a line on the board using the given co-ordinates as endpoints 
    */ 
    public void drawLine(double row1, double col1, double row2, double col2) 
    { 
     this.line[0][numLines]=col1; 
     this.line[1][numLines]=row1; 
     this.line[2][numLines]=col2; 
     this.line[3][numLines]=row2; 
     this.numLines++; 
     repaint(); 
    } 

    /** Removes one line from a board given the co-ordinates as endpoints 
    * If there is no such line, nothing happens 
    * If multiple lines, all copies are removed 
    */ 

    public void removeLine(int row1, int col1, int row2, int col2) 
    { 
     int curLine = 0; 
     while (curLine < this.numLines) 
     { 
      // Check for either endpoint being specified first in our line table 
      if ((line[0][curLine] == col1 && line[1][curLine] == row1 && 
        line[2][curLine] == col2 && line[3][curLine] == row2) || 
        (line[2][curLine] == col1 && line[3][curLine] == row1 && 
        line[0][curLine] == col2 && line[1][curLine] == row2)) 
      { 
       // found a matching line: overwrite with the last one 
       numLines--; 
       line[0][curLine] = line[0][numLines]; 
       line[1][curLine] = line[1][numLines]; 
       line[2][curLine] = line[2][numLines]; 
       line[3][curLine] = line[3][numLines]; 
       curLine--; // perhaps the one we copied is also a match 
      } 
      curLine++; 

     } 
     repaint(); 
    } 

    /** Waits for user to click somewhere and then returns the click. 
    */ 
    public Point getClick() 
    { 
     Point returnedClick = null; 
     synchronized(this) { 
      lastClick = null; 
      while (lastClick == null) 
      { 
       try { 
        this.wait(); 
       } catch(Exception e) { 
        // We'll never call Thread.interrupt(), so just consider 
        // this an error. 
        e.printStackTrace(); 
        System.exit(-1) ; 
       } /* try */ 
      } 

      int x = (int)Math.floor((lastClick.getY()-X_OFFSET*scale)/X_DIM/scale); 
      int y = (int)Math.floor((lastClick.getX()-Y_OFFSET*scale)/Y_DIM/scale); 

      // Put this into a new object to avoid a possible race. 
      returnedClick = new Point(x,y); 
     } 
     return returnedClick; 
    } 

    /** Same as getClick above but for 1D boards 
    */ 
    public double getPosition() 
    { 
     return this.getClick().getY(); 
    } 

    public int getColumns() 
    { 
     return this.columns; 
    } 

    public int getRows() 
    { 
     return this.rows; 
    } 
} 
+0

Vous devriez demander aux TA qui ont écrit ceci comment ils vous ont demandé d'ajouter des raccourcis clavier à 'Board'. Si c'est pour une classe, en espérant que le code est correct et que vous ne l'utilisez pas correctement (pas de faute de votre part, tous les professeurs/classes ne fournissent pas une bonne documentation sur l'utilisation de leur code, comme dans la vraie vie!). – Riaz

+0

Notez qu'en plus du problème que je mentionne dans ma réponse, le remplacement de la classe paintComponent de votre classe Board n'appelle pas la méthode du super, ce qui peut causer des problèmes importants car cela casse la chaîne de peinture. –

+0

Malheureusement, le 'conseil' vient de [ici] (https://cs.uwaterloo.ca/~tmjvasig/ibmtalk/), ce qui n'est pas l'école où je vais. Je suis au lycée et je ne suis pas sûr que notre professeur sache comment les raccourcis clavier fonctionneraient avec cette classe non plus. –

Répondre

2

Conseil Vous vous tirer une balle dans le pied avec ce code de fil - vous » re appeler run() pas start() sur elle

SYNC_BOARD.run(); 

Ceci sera exécuté sur le thread d'événement Swing et risque de geler complètement votre interface graphique. En règle générale, vous ne devriez presque jamais étendre Thread mais plutôt implémenter Runnable, mais quoi qu'il en soit, n'utilisez pas ce Thread code - Utilisez plutôt un Swing Timer puisque votre code n'a pas de ruptures dedans, pas Thread.sleeps et cela rendra votre processeur terriblement occupé, et la minuterie d'oscillation vous aidera à vous assurer que votre code obéit aux règles d'enfilage de Swing.

Votre MoveAction est également incorrect. La plupart de ce code devrait aller dans la méthode actionPerformed. Le constructeur devrait simplement définir le champ de direction et c'est tout.

Quelque chose comme:

@SuppressWarnings("serial") 
public class MoveAction extends AbstractAction { 
    Direction direction; 

    public MoveAction(Direction direction) { 
     // this is the only code the constructor should have! 
     this.direction = direction; 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     // use direction to help make move in here 
    } 
} 

comprendre que ce qui a probablement causé des problèmes majeurs, puisque le constructeur est appelé à la création du programme (donc vos raccourcis clavier « de travail » lorsque le programme commence), mais il est le actionPerformed cela est appelé quand on appuie sur la touche droite.

+0

Ça a marché! Je me sens comme un idiot que je mets ma logique dans le constructeur maintenant. Merci de votre aide. –

+0

Je vais aussi le changer pour qu'à chaque fois qu'une action de déplacement se produise, une méthode 'UpdateBoard' sera appelée pour accomplir la même chose que' SYNC_BOARD'. –