java - javax.swing 是否可以在一帧中使用两个画家?

标签 java swing

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

由于蛇的画家每 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/

相关文章:

java - ms access编码问题(与jsp连接)

java - 使用按钮将文件添加到 JList

java - 从 Java 应用程序向 Zebra 打印机发送条码

java - 如何将图像添加到 JButton

java - 在 JFileChooser 上显示文件名 ToolTipText

java - 制作更改程序GUI

swing 中的 java.lang.NullPointerException

java - LibGdx : Keep one spriteBatch as singleton in Game? 或每个屏幕一个 spriteBacth?

JavaFX HTML 编辑器 : Text is in one single line

Java 导入,不带 CLASSPATH