在我的游戏中有一个Canvas object并且这个对象没有被设置focus,因为这个我的snake is not moving on the Board。
基本上我正在做snake game项目,我想要的是什么时候play button点击PlayGame.java JDialog,游戏应该开始,但我面临的问题是点击按钮后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();*/
}
}
而且我正在附加我所指的播放按钮的 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。