2013-09-28 81 views
0

在我的游戏中有一个Canvas object,并且此对象未设置为focus,因为这是我的snake is not moving on the Board我该如何设置焦点对象

基本上我的工作snake game项目,我要的是当从PlayGame.java JDialog点击play button,游戏应该开始,但我面临的问题是,点击按钮后gamescreen appearing on window but snake is not moving,所以有人建议我,你的canvas object is not in focus whenever it is called。 那就是为什么KeyLisener not able to listen to keyPresses /key strokes

这是声明和实现画布对象的类。

package org.psnbtech; 

import java.awt.Canvas; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Font; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.event.KeyAdapter; 
import java.awt.event.KeyEvent; 
import javax.swing.JFrame; 
import org.psnbtech.GameBoard.TileType; 
import org.psnbtech.Snake.Direction; 


public class Engine extends KeyAdapter { 

    private static final int UPDATES_PER_SECOND = 15; 

    private static final Font FONT_SMALL = new Font("Arial", Font.BOLD, 20); 

    private static final Font FONT_LARGE = new Font("Arial", Font.BOLD, 40); 

    public Canvas canvas; 

    public GameBoard board; 

    public Snake snake; 

    public int score; 

    public boolean gameOver; 


    public Engine(Canvas canvas) { 
       this.canvas = canvas; 
      this.board = new GameBoard(); 
     this.snake = new Snake(board); 

     resetGame(); 

     canvas.addKeyListener(this); 
       //new Engine(canvas).startGame(); 
    } 


    public void startGame() { 
     canvas.createBufferStrategy(2); 

     Graphics2D g = (Graphics2D)canvas.getBufferStrategy().getDrawGraphics(); 
     g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 

     long start = 0L; 
     long sleepDuration = 0L; 
     while(true) { 
      start = System.currentTimeMillis(); 

      update(); 
      render(g); 

      canvas.getBufferStrategy().show(); 

      g.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); 

      sleepDuration = (1500L/UPDATES_PER_SECOND) - (System.currentTimeMillis() - start); 

      if(sleepDuration > 0) { 
       try { 
        Thread.sleep(sleepDuration); 
       } catch(Exception e) { 
            e.printStackTrace(); 
       } 
      } 
     } 
    } 

    public void update() { 
     if(gameOver || !canvas.isFocusable()) { 
      return; 
     } 
     TileType snakeTile = snake.updateSnake(); 
     if(snakeTile == null || snakeTile.equals(TileType.SNAKE)) { 
      gameOver = true; 
     } else if(snakeTile.equals(TileType.FRUIT)) { 
      score += 10; 
      spawnFruit(); 
     } 
    } 

    public void render(Graphics2D g) { 
     board.draw(g); 

     g.setColor(Color.WHITE); 

     if(gameOver) { 
      g.setFont(FONT_LARGE); 
      String message = new String("Your Score: " + score); 
      g.drawString(message, canvas.getWidth()/2 - (g.getFontMetrics().stringWidth(message)/2), 250); 

      g.setFont(FONT_SMALL); 
      message = new String("Press Enter to Restart the Game"); 
      g.drawString(message, canvas.getWidth()/2 - (g.getFontMetrics().stringWidth(message)/2), 350); 
     } else { 
      g.setFont(FONT_SMALL); 
      g.drawString("Score:" + score, 10, 20); 
     } 
    } 

    public void resetGame() { 
     board.resetBoard(); 
     snake.resetSnake(); 
     score = 0; 
     gameOver = false; 
     spawnFruit(); 
    } 

    public void spawnFruit() { 
     int random = (int)(Math.random() * ((GameBoard.MAP_SIZE * GameBoard.MAP_SIZE) - snake.getSnakeLength())); // if '*' replace by '/' then only one fruit is there for snake 

     int emptyFound = 0; 
     int index = 0; 
     while(emptyFound < random) { 
      index++; 
      if(board.getTile(index % GameBoard.MAP_SIZE, index/GameBoard.MAP_SIZE).equals(TileType.EMPTY)) { // if '/' replaced by '*' then nothing displays on the board 
       emptyFound++; 
      } 
     } 
     board.setTile(index % GameBoard.MAP_SIZE, index/GameBoard.MAP_SIZE, TileType.FRUIT); // it also show nothing when replacing '/' by '/' 
    } 

    @Override 
    public void keyPressed(KeyEvent e) { 
     if((e.getKeyCode() == KeyEvent.VK_UP)||(e.getKeyCode() == KeyEvent.VK_W)) { 
      snake.setDirection(Direction.UP); 
     } 
     if((e.getKeyCode() == KeyEvent.VK_DOWN)||(e.getKeyCode() == KeyEvent.VK_S)) { 
      snake.setDirection(Direction.DOWN); 
     } 
     if((e.getKeyCode() == KeyEvent.VK_LEFT)||(e.getKeyCode() == KeyEvent.VK_A)) { 
      snake.setDirection(Direction.LEFT); 
     } 
     if((e.getKeyCode() == KeyEvent.VK_RIGHT)||(e.getKeyCode() == KeyEvent.VK_D)) { 
      snake.setDirection(Direction.RIGHT); 
     } 
     if(e.getKeyCode() == KeyEvent.VK_ENTER && gameOver) { 
      resetGame(); 
     } 
    } 

     public static void main(String[] args) { 
     new PlayGame().setVisible(true); 

     /**JFrame frame = new JFrame("SnakeGame"); 
     frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); 
     frame.setResizable(false); 

     Canvas canvas = new Canvas(); 
     canvas.setBackground(Color.black); 
     canvas.setPreferredSize(new Dimension(GameBoard.MAP_SIZE * GameBoard.TILE_SIZE, GameBoard.MAP_SIZE * GameBoard.TILE_SIZE)); 

     frame.getContentPane().add(canvas); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 

     new Engine(canvas).startGame();*/ 


      }   
} 

,也是我很attching的actionPerformed()播放按钮的方法,其中我指canvas object

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {           
    JFrame frame = new JFrame("SnakeGame"); 
    frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); 
    frame.setResizable(false); 

    Canvas canvas = new Canvas(); 
    canvas.setBackground(Color.black); 
    canvas.setPreferredSize(new Dimension(GameBoard.MAP_SIZE *GameBoard.TILE_SIZE,GameBoard.MAP_SIZE * GameBoard.TILE_SIZE)); 

    frame.add(canvas); 
    frame.pack(); 
    frame.setLocationRelativeTo(null); 
    frame.setVisible(true); 

    new Engine(canvas).startGame(); 

    }  

所以,请告诉/建议我how can i set canvas object in focus。从别人

回答

3

建议谁一直在那里:

  • 你的焦点问题是一个真正的XY problem
  • 相反,你不应该混AWT(画布)和Swing(JFrame的)组件,而是应该具有全Swing组件
  • 使用Key Bindings,而不是KeyListener的和你的焦点问题只会融化粘。
  • 按照this tutorial按照JPanel的paintComponent(...)方法进行绘制。
  • 请勿覆盖Swing应用程序的更新方法。
+0

那么我怎样才能将KeyListener替换为KeyBinding而不影响代码,或者我必须从我的项目中删除keyListener。 –

+0

@AnkushPruthi:它代替KeyListener。请查看教程。无论如何,无论如何,你真的应该摆脱Canvas和AWT。 –

+0

好的,我确实在教程中进行检查,如果有任何疑问,我会在评论框中发帖。 –