我正在重新创建经典的贪吃蛇游戏。我已经完成了蛇的编码。我现在要做的是对墙壁进行编码(应该位于框架的边缘)。
由于蛇的画家每 30 毫秒“重新绘制”一次,我认为让这位画家也绘制墙壁并不是非常有效,因为墙壁在整个游戏过程中都保持在同一个位置,所以它不是'确实没有必要每 30 毫秒重新绘制一次墙。
因此,我想知道我的游戏中是否可以有两个画家,一个每 30 毫秒重新绘制蛇,另一个只绘制一次(它在游戏开始时绘制墙壁)?我该怎么做?
这些是与问题相关的代码中最重要的部分(完整代码可以在下面找到):
//this is in the main class
public Snake(){
painter = new Painter(this);
this.add(painter, BorderLayout.CENTER);
this.setSize(500, 500);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.addKeyListener(this);
this.requestFocusInWindow();
timer = new Timer(30, this);
startGame();
}
public void startGame(){
snakeList = new LinkedList<Point>();
snakeList.addFirst(new Point(10, 10));
snakeSegments(3);
setFood(30, 30);
movementX = 0;
movementY = 0;
timer.start(); //timer triggers gameUpdate();
}
public void gameUpdate(){
snakeMove(movementX, movementY);
snakeInstructor();
snakeEat();
snakeCollision();
painter.repaint();
}
-
// this is in the painter class
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, 500, 500);
paintSnake(g);
paintFood(g);
}
这是完整的代码:
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.JFrame;
import javax.swing.Timer;
public class Snake extends JFrame implements KeyListener, ActionListener{
Painter painter;
LinkedList<Point> snakeList;
Timer timer;
Point foodLocation;
int direction;
int snakeSize;
int movementX, movementY;
public static void main(String[] arg){
new Snake();
}
public Snake(){
painter = new Painter(this);
this.add(painter, BorderLayout.CENTER);
this.setSize(500, 500);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.addKeyListener(this);
this.requestFocusInWindow();
timer = new Timer(30, this);
startGame();
}
public void startGame(){
snakeList = new LinkedList<Point>();
snakeList.addFirst(new Point(10, 10));
snakeSegments(3);
setFood(30, 30);
movementX = 0;
movementY = 0;
timer.start();
}
public void gameUpdate(){
snakeMove(movementX, movementY);
snakeInstructor();
snakeEat();
snakeCollision();
painter.repaint();
}
public void snakeCollision(){
for(int i = 4; i < getSnakeSize(); i++){
if(getFirst().equals(snakeList.get(i))){
gameOver();
}
}
}
public void gameOver(){
timer.stop();
}
public void snakeEat(){
if(getFirst().equals(getFood())){
newFood();
setSnakeSize();
snakeSegments(4);
}
}
public void snakeSegments(int i){
snakeSize = i;
while(snakeSize > 0){
snakeList.addLast(new Point(getLast()));
snakeSize--;
}
}
public void snakeInstructor(){
int currentDirection = getDirection();
if (currentDirection == 1){
snakeMove(-1, 0);
} else if (currentDirection == 2){
snakeMove(1, 0);
} else if (currentDirection == 3){
snakeMove(0, -1);
} else if (currentDirection == 4){
snakeMove(0, 1);
}
}
public void snakeMove(int directionX, int directionY){
snakeList.getFirst().x = snakeList.getFirst().x + directionX;
snakeList.getFirst().y = snakeList.getFirst().y + directionY;
for(int i = getSnakeSize()-1; i >=1; i--) {
snakeList.get(i).setLocation(snakeList.get(i-1));
}
}
public void newFood(){
Random generator = new Random();
int x = generator.nextInt(49);
int y = generator.nextInt(47);
setFood(x, y);
}
public void setFood(int x, int y){
foodLocation = new Point(x, y);
}
public Point getFood(){
return foodLocation;
}
public void setDirection(int newDirection){
direction = newDirection;
}
public int getDirection (){
return direction;
}
Point getFirst(){
return snakeList.getFirst();
}
Point getLast(){
return snakeList.getLast();
}
Point get(int i){
return snakeList.get(i);
}
public void addFirst(Point p){
snakeList.addFirst(p);
}
public void addLast(Point p){
snakeList.addLast(p);
}
public int getSnakeSize(){
return snakeList.size();
}
public void setSnakeSize(){
snakeSize = getSnakeSize() + 1;
}
@Override
public void actionPerformed(ActionEvent event) {
gameUpdate();
}
@Override public void keyReleased(KeyEvent e){ }
@Override public void keyTyped(KeyEvent e){ }
@Override public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if((key == KeyEvent.VK_LEFT) && direction != 2){
setDirection(1);
} else if ((key == KeyEvent.VK_RIGHT) && direction != 1){
setDirection(2);
} else if ((key == KeyEvent.VK_UP) && direction != 4){
setDirection(3);
} else if ((key == KeyEvent.VK_DOWN) && direction != 3){
setDirection(4);
} else if (key == KeyEvent.VK_SPACE){
startGame();
}
}
}
-
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
public class Painter extends JPanel{
Snake snake;
public Painter(Snake snake){
this.snake = snake;
}
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, 500, 500);
paintSnake(g);
paintFood(g);
}
public void paintSnake(Graphics g){
for(int i = 0; i < snake.getSnakeSize(); i++){
g.setColor(Color.WHITE);
Point p = snake.snakeList.get(i);
g.fillRect(p.x*10, p.y*10, 10, 10);
}
}
public void paintFood(Graphics g){
Point p = snake.getFood();
g.setColor(Color.RED);
g.fillRect(p.x*10, p.y*10, 10, 10);
}
}
最佳答案
是与否...
您可以使 Painter
透明并将蛇覆盖在墙壁顶部,但是调用 g.fillRect(0, 0, 500, 500);
会使它变得多余,因为它用当前颜色填充整个组件......
每次您想要更新 UI 时,两个画家的 paintComponent
方法都会被调用,这也是毫无意义的。
更好的解决方案是将 map 渲染到 BufferedImage
并在绘制蛇之前在 painter
中绘制它。
关于java - javax.swing 是否可以在一帧中使用两个画家?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26666369/