2013-09-28 113 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

好的,我確實在教程中進行檢查,如果有任何疑問,我會在評論框中發帖。 –