我正在重新创建经典的蛇游戏。我已经完成了对蛇的编码。我现在要做的是编码墙壁(应该位于框架的边缘)。

当蛇的画家每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内部进行绘制。

07-25 22:46