Как показать открытую / закрытую анимацию Пакмана в Java с двойной буферизацией? - PullRequest
0 голосов
/ 07 марта 2009

Я пытаюсь показать знаменитую анимацию открытия / закрытия рта персонажа 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);
}

Ответы [ 2 ]

3 голосов
/ 07 марта 2009

Вы должны спать между 2 изображениями. в противном случае вы увидите только последнее нарисованное изображение.

например.

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) {}
            }
}
2 голосов
/ 07 марта 2009

Как сказал sfossen, вам нужна задержка между рисованием изображений.

Пара других вещей, которые стоит рассмотреть.

  • Для плавной анимации вам, вероятно, нужно больше, чем просто изображения "с открытым ртом" и "с закрытым ртом". Вам нужны два или три промежуточных изображения.
  • Чтобы упростить управление ресурсами, вы можете объединить все кадры анимации в одно широкое изображение, которое будет выглядеть как «кинолента». Затем, чтобы нарисовать рамку, вы используете смещение (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.
}
...