私はスネークゲームを書いています。アニメーションを滑らかにしたいので、アニメーションにこだわっています。ダブルバッファリングを取得するために画像をダブルバッファリングする方法がわかりません。これがダブルバッファリングされるようにするには、何をする必要がありますか? JFrame を拡張するメイン フレームを使用します。ここでは、2 つの JPanel を追加します。1 つはステータス バー用、もう 1 つはアニメーション用です。ヘビのアニメーションに使用されるクラスは次のとおりです。
Player.class
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();
}
}