Как показать анимацию открытия/закрытия рта Пакмана на Java с двойной буферизацией?
Вопрос
Я пытаюсь показать знаменитую анимацию открытия/закрытия рта персонажа pacman в одноразовой игре pacman, которую я создаю, чтобы научиться программированию игр.
Я рисую изображение открытого рта, а затем перерисовываю изображение закрытого рта в том же месте (x/y).Но это не работает, и я все время вижу анимацию закрытого рта.
Если я включу это в цикл, система просто зависнет, и вы увидите мерцание там, где изображение открытого рта, но вы не увидите, как изображения заменяются.
Я протестировал и убедился, что оба изображения загружаются правильно и так, как ожидалось.
Вот мой startAnim()
функция, она вызывается при двойном щелчке по апплету:
public void beginGame() //Called from engine.java
{
isRunning=true;
repaint();
pacman.startAnim();
}
public void startAnim() //In different class, pacman.java
{
Image orig;
while (engine.isRunning)
{
orig=this.getCurrentImg();
draw(engine.getGraphics());
this.setCurrImg(currImg2);
this.draw(engine.getGraphics());
this.setCurrImg(orig);
this.draw(engine.getGraphics());
try
{
Thread.sleep(100);
}
catch (InterruptedException e) {}
}
}
public void draw(Graphics g) //Called from engine.paint()
{
g.drawImage(getCurrentImg(), getX(),
getY(), engine);
}
Решение
вам придется спать между двумя изображениями.в противном случае вы увидите только последнее нарисованное изображение.
например.
while( running )
{
image 1
draw
sleep
image 2
draw
sleep
}
что-то вроде этого:
public void startAnim() //In different class, pacman.java
{
final int cnt = 2;
Image[] imgs = new Image[ cnt ];
int step = 0;
imgs[ 0 ] = closedMouthImage;
imgs[ 1 ] = openMouthImage;
while ( engine.isRunning )
{
this.setCurrImg( imgs[ step ] );
draw(engine.getGraphics());
step = ( step + 1 ) % cnt;
try
{
Thread.sleep(100);
}
catch (InterruptedException e) {}
}
}
Другие советы
Как сказал Сфоссен, вам нужна задержка между рисованием изображений.
Еще несколько вещей, которые следует учитывать.
- Для плавной анимации вам, вероятно, понадобится нечто большее, чем просто изображения «рот открыт» и «рот закрыт».Вам понадобятся два или три промежуточных изображения.
- Чтобы упростить управление ресурсами, вы можете объединить все кадры анимации в одно широкое изображение, которое будет выглядеть как «диафильм».Затем, чтобы нарисовать кадр, вы используете смещение (x, y) для интересующего вас кадра.
- Наконец, если вы рисуете все кадры каждый раз, когда проходите основной цикл вашей программы, Pac-Man будет полностью пережевывать каждый раз, когда вы его перемещаете.Вам следует подумать о том, чтобы каждый раз рисовать только один кадр в основном цикле и использовать переменную для отслеживания, в каком кадре вы находитесь.
Пример (псевдокод)
frameWidth = 32
frameIndex = 0
while(running) {
// Draw just the frame of your animation that you want
drawImage(pacmanX, pacmanY, filmStrip, frameIndex * frameWidth, 0, frameWidth, frameHeight)
frameIndex = (frameIndex + 1) % frameCount
// Update position of pacman & ghosts
// Update sound effects, score indicators, etc.
}