我正在重新创建经典的蛇游戏。我已经完成了对蛇的编码。我现在要做的是编码墙壁(应该位于框架的边缘)。
当蛇的画家每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
方法,这也是毫无意义的。
更好的解决方案是在绘制蛇之前将地图渲染为BufferedImage
并在painter
内部进行绘制。