由于我直接在JFrame中绘画,我的游戏闪烁。我如何使用JPanel?

时间:2017-03-07 18:22:31

标签: java swing jframe jpanel

我做了一个蛇游戏作为大学的任务,它运作得很好 - 除了它像疯了一样闪烁。我知道这是因为我直接在JFrame中绘制,而不是在提供双缓冲的JPanel中,但由于我没有太多的摇摆经验,我不知道如何实际做到这一点。任何帮助将不胜感激!

import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Random;

public class SnakeGame extends JFrame implements KeyListener, ActionListener{

//Initiate all the variables we need
public ArrayList<SnakeElement> snakeBody = new ArrayList<SnakeElement>();
public SnakeElement snake = new SnakeElement(100, 100);
public AppleElement apple = new AppleElement();
public int moveSnakeX = 1;
public int moveSnakeY = 0;
public int score = 0;
public int highscore = 0;
public int timer = 0;
public static final Font scoreFont = new Font("Arial", Font.BOLD, 20);

//Create the JFrame
public SnakeGame(){
    this.setTitle("Snake");
    this.setVisible(true);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setSize(600,600);
    this.setResizable(false);
    setLocationRelativeTo(null);
    this.addKeyListener(this);
    setBackground(Color.BLACK);
    snakeBody.add(snake);
    Timer t = new Timer(5, this);
    t.start();
}

public void drawSomething(){
    timer += 5;
    //Spawns a new apple every 5 seconds
    if(timer >= 5000){
        System.out.println("Apple escaped!");
        Random pos = new Random();
        apple.setX(pos.nextInt(581 + 1 - 21) + 21); //Bound: (20, 580)
        apple.setY(pos.nextInt(581 + 1 - 21) + 21); //Bound: (20, 580)
        timer = 0;
    }

    Graphics g = this.getGraphics();
    g.clearRect(0, 0, this.getWidth(), this.getHeight());
    g.setColor(Color.WHITE);
    g.setFont(scoreFont);
    g.drawString("Score: " + score, 500, 60);
    this.checkCollision();
    this.MoveSnake();

    //Draws every element in snakeBody
    for(int i = 0; i < this.snake.getSize()-1; i++) {
        snakeBody.get(i).drawSnake(g);
    }

    //Updates the ArrayList snakeBody: all element-coordinates equals the element-coordinates before them
    for(int i = snakeBody.size()-1; i > 0; i--) {
        SnakeElement penultimate = snakeBody.get(i-1); //Gets the penultimate element in snakeBody
        SnakeElement last = snakeBody.get(i); //Gets the last element in snakeBody
        last.x = penultimate.x; //Sets the x-coordinate for the last element = the x-coordinate for the penultimate element
        last.y = penultimate.y; //Sets the y-coordinate for the last element = the y-coordinate for the penultimate element
    }

    this.snake.drawSnake(g);
    this.apple.drawApple(g);
}

public void MoveSnake(){
    this.snake.setX(this.snake.getX() + moveSnakeX); //If moveSnakeX = 1 or -1, the snake moves horizontally
    this.snake.setY(this.snake.getY() + moveSnakeY); //If moveSnakeY = 1 or -1, the snake moves vertically

    //If snake crashes into a wall, save score and show "Game over"-message
    if(this.snake.getX() == 0 || this.snake.getX() == 600 || this.snake.getY() == 0 || this.snake.getY() == 600){
        if(score > highscore){
            highscore = score;
        }
        this.GameOver();
    }
}

public void checkCollision(){
    Rectangle r1 = new Rectangle(snake.getX(), snake.getY(), snake.getHeight(), snake.getWidth());
    Rectangle r2 = new Rectangle(apple.getX(), apple.getY(), apple.getHeight(), apple.getWidth());
    Random pos = new Random();

    //If snake eats the apple, spawn a new apple and grow snake, reset the timer and add 5 points to your score
    if(r1.intersects(r2)){
        System.out.println("Snake got the apple!");
        apple.setX(pos.nextInt(581 + 1 - 21) + 21); //Random x-coordinate within (20, 580)
        apple.setY(pos.nextInt(581 + 1 - 21) + 21); //Random y-coordinate within (20, 580)

        this.snake.setSize(this.snake.getSize() +15);
        this.GrowSnake();
        timer = 0;
        score += 5;
    }
}

//Adds a snake element at the end of the snake
public void GrowSnake(){
    for(int x = 0; x < 15; x++) {
        SnakeElement snakeButt = new SnakeElement(snakeBody.get(snakeBody.size() - 1).x, snakeBody.get(snakeBody.size() - 1).y);
        this.snakeBody.add(snakeBody.size(), snakeButt);
    }
}

//Show an option message when game is over
Object [] options = {"Start over", "Exit game"};
public void GameOver(){
    int answer = JOptionPane.showOptionDialog(null,
            "Snake died!" +
                    "\nScore: " + score +
                    "\nHighscore: " + highscore,
            "Game over!",
            JOptionPane.YES_NO_OPTION,
            JOptionPane.QUESTION_MESSAGE,
            null,
            options,
            options[0]);

    //Reset variables if player wants to restart game
    if(answer == 0){
        this.snake.setX(100);
        this.snake.setY(100);
        this.snake.setSize(0);
        moveSnakeX = 1;
        moveSnakeY = 0;
        this.drawSomething();
        score = 0;
    } else { //Exit game
        System.exit(0);
    }
}

@Override
public void keyTyped(KeyEvent e) {
}

@Override
public void keyPressed(KeyEvent e) {
    this.drawSomething();

    if(e.getKeyCode() == KeyEvent.VK_UP){
        //If snake is NOT moving down, make snake move up. If snake is moving down, it's not allowed to move up
        if(moveSnakeY != 1){
            System.out.println("Up");
            moveSnakeX = 0;
            moveSnakeY = -1;
        } else {
            System.out.println("You cannot turn in the opposite direction!");
        }
    }

    if(e.getKeyCode() == KeyEvent.VK_DOWN){
        if(moveSnakeY != -1){
            System.out.println("Down");
            moveSnakeX = 0;
            moveSnakeY = 1;
        } else {
            System.out.println("You cannot turn in the opposite direction!");
        }
    }

    if(e.getKeyCode() == KeyEvent.VK_LEFT){
        if(moveSnakeX != 1){
            System.out.println("Left");
            moveSnakeX = -1;
            moveSnakeY = 0;
        } else {
            System.out.println("You cannot turn in the opposite direction!");
        }
    }

    if(e.getKeyCode() == KeyEvent.VK_RIGHT){
        if(moveSnakeX != -1){
            System.out.println("Right");
            moveSnakeX = 1;
            moveSnakeY = 0;
        } else {
            System.out.println("You cannot turn in the opposite direction!");
        }
    }
}

@Override
public void keyReleased(KeyEvent e) {
}

@Override
public void actionPerformed(ActionEvent e) {
    this.drawSomething();
}

0 个答案:

没有答案