我正在写蛇游戏。我被动画困住了,因为我想获得流畅的动画。我不知道如何加倍缓冲图像以获得双缓冲。必须做什么才能使其成为双缓冲?我使用扩展 JFrame 的主框架,在这里我添加了两个 JPanel - 一个用于状态栏,一个用于动画。以下是用于蛇动画的类:
播放器类
package snake;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.ImageIcon;
public class Player
{
private int headSizeX;
private int headSizeY;
private int tailSizeX;
private int tailSizeY;
private int x;
private int y;
private int speed = 5;
private int snakeSize = 40;
private Image[] snake = new Image[5];
private ArrayList<Integer> X,Y;
private static int imageNr = 0;
private int c = 0;
private int tmp;
private boolean death = false;
static int player;
private static boolean inverse = false;
private boolean left = false;
private boolean right = false;
private boolean up = true;
private boolean down = false;
public Player()
{
initPlayer();
headSizeX = snake[0].getWidth(null);
headSizeY = snake[0].getHeight(null)-2;
tailSizeX = snake[4].getWidth(null);
tailSizeY = snake[4].getHeight(null);
System.out.println("tail: "+tailSizeX+" "+tailSizeY);
x = MainGamePanel.getSizeX()/2;
y= MainGamePanel.getSizeY()-130;
}
public void initPlayer()
{
int imgNr = 5;
X = new ArrayList<Integer>();
Y = new ArrayList<Integer>();
String name = "green";
switch (player)
{
case 1:
name = "green"; break;
case 2:
name = "red"; break;
case 3:
name = "blue"; break;
}
for (int nr = 1; nr <= imgNr; nr++)
{
snake[nr-1] = new ImageIcon("img/" +name+"/snake" +nr+".png").getImage();
}
X.add(MainGamePanel.getSizeX()/2);
Y.add( MainGamePanel.getSizeY()-200);
X.add( MainGamePanel.getSizeX()/2);
Y.add( MainGamePanel.getSizeX()/2+33);
for (int i = 2; i < snakeSize; i++) {
X.add( MainGamePanel.getSizeX()/2);
Y.add( MainGamePanel.getSizeX()/2 + i*20+13);
}
}
public void paint(Graphics g)
{
//g.drawImage(snake[imageNr], x,y,headSizeX,headSizeY,null);
for (int i = 0; i < snakeSize; i++) {
if (i == 0)
g.drawImage(snake[imageNr], X.get(i), Y.get(i), null);
else
g.drawImage(snake[4], X.get(i), Y.get(i), null);
}
/*g.drawImage(snake[4],x, y+headSizeY, tailSizeX, tailSizeY, null);
for (int i = 1;i<snakeSize;i++)
g.drawImage(snake[4],x, y+i*tailSizeY+headSizeY, tailSizeX, tailSizeY, null);*/
}
public void update()
{
y = MainGamePanel.getSizeY()-headSizeY - 35;
for (int i = snakeSize-1; i > 0; i--) {
X.set(i, X.get(i-1));
Y.set(i, Y.get(i-1));
}
if (left) {
tmp = X.get(0);
X.set(0, tmp-20);
imageNr = 3;
}
if (right) {
tmp = X.get(0);
X.set(0, tmp+20);
imageNr = 1;
}
if (up) {
tmp = Y.get(0);
Y.set(0, tmp-20);
imageNr = 0;
}
if (down) {
tmp = Y.get(0);
Y.set(0, tmp+20);
imageNr = 2;
}
}
public void keyPressed(KeyEvent e)
{
int key = e.getKeyCode();
if ((key == KeyEvent.VK_LEFT) && (!right)) {
left = true;
up = false;
down = false;
System.out.println("LEWO");
}
if ((key == KeyEvent.VK_RIGHT) && (!left)) {
right = true;
up = false;
down = false;
System.out.println("PRAWO");
}
if ((key == KeyEvent.VK_UP) && (!down)) {
up = true;
right = false;
left = false;
System.out.println("GÓRA");
}
if ((key == KeyEvent.VK_DOWN) && (!up)) {
down = true;
right = false;
left = false;
System.out.println("DÓŁ");
}
}
public void collision()
{
death = true;
}
public void reset()
{
imageNr = 0;
death = false;
}
public void setInverse(boolean set)
{
inverse = set;
}
public void increaseSpeed(int inc)
{
speed += inc;
}
public void decreaseSpeed(int dec)
{
speed -=dec;
}
public int getSnakeSize()
{
return snakeSize;
}
public void increaseSnakeSize()
{
snakeSize += 1;
}
public void decreaseSnakeSize(int dec)
{
snakeSize -= dec;
}
}
MainGamePanel.class
package snake;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class MainGamePanel extends JPanel implements KeyListener{
private Image bounds;
private Player player;
public static int sizex;
private Image tail;
private Image background;
private int lives;
private int speed;
private int levels;
private int counter = 0;
private int appleCounter = 0;
private static int level = 1;
public static int sizeX = 784;
public static int sizeY = 617;
public static int applesNumber;
private boolean gameover = false;
private boolean gameend = false;
private boolean death = false;
private boolean levelCompleted = false;
private Graphics buffer;
private BufferedImage img;
public MainGamePanel(int[] settings)
{
lives = settings[0];
speed = settings[1];
levels = settings[2];
bounds = new ImageIcon("img/bounds.jpg").getImage();
setFocusable(true);
addKeyListener(this);
//new Apple();
}
public void init()
{
player = new Player();
img = new BufferedImage(sizeX, sizeY, 2);
Levels.getLevel(1);
this.applesNumber = Levels.getApplesNumber();
this.background = new ImageIcon("img/bg/" + Levels.getBackground()).getImage();
}
public void addNotify()
{
super.addNotify();
init();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
buffer = img.getGraphics();
buffer.drawImage(background, 0,0, sizeX, sizeY, null);
player.paint(buffer);
for (int i = 0; i <= getWidth(); i += 12) {
buffer.drawImage(bounds, i, 0, this);
buffer.drawImage(bounds, i, getHeight()-12, this);
}
for (int i = 12; i < getHeight(); i += 12) {
buffer.drawImage(bounds, 0, i, this);
buffer.drawImage(bounds, getWidth()-12, i, this);
}
g.drawImage(this.img, 0, 0, getWidth(), getHeight(), null);
buffer.clearRect(12, 12, sizeX, sizeY);
}
public void play()
{
if (level == this.levels) gameend = true;
this.player.reset();
this.counter = 0;
this.appleCounter = 0;
long StartTime = System.currentTimeMillis();
player.update();
repaint();
/*do
{
Thread.yield();
}
while (System.currentTimeMillis() - StartTime < this.speed);*/
}
public void gameLoop()
{
while(true)
{
play();
try
{
Thread.sleep(150);
}
catch (InterruptedException ex)
{
}
if (death)
{
lives -= 1;
death = false; continue;
}
levelCompleted = false;
level+=1;
Levels.getLevel(level);
applesNumber = Levels.getApplesNumber();
}
}
public static int getApp()
{
return applesNumber;
}
public static int getSizeX()
{
return sizeX;
}
public static int getSizeY()
{
return sizeY;
}
public void setGameOver()
{
gameover = true;
}
@Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) System.exit(0);
player.keyPressed(e);
}
@Override
public void keyReleased(KeyEvent e) {}
@Override
public void keyTyped(KeyEvent e) {}
}
和 JFrame 的 Game.class
package snake;
import java.awt.Dimension;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import java.awt.BorderLayout;
@SuppressWarnings("serial")
public class Game extends JFrame {
//public SnakeTheGame start;
private ImageIcon icon;
StatBar statbar;
private MainGamePanel start;
public static final int WIDTH = 800;
public static final int HEIGHT = 700;
public static final int MIN_WIDTH = 450;
public static final int MIN_HEIGHT = 450;
public Game()
{
start = new MainGamePanel(new int[] { Settings.getLives(), Settings.getSpeed(), Settings.getLevels() });
statbar = new StatBar();
icon = new ImageIcon("img//icon.png");
setBounds(200, 200, WIDTH, HEIGHT);
setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
setTitle("Snake The Game");
setIconImage(this.icon.getImage());
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
getContentPane().add(statbar, BorderLayout.SOUTH);
getContentPane().add(start, BorderLayout.CENTER);
// this.createBufferStrategy(2);
this.start.setVisible(true);
start.requestFocus();
}
public void start()
{
start.gameLoop();
}
}