如何用双缓冲在Java中显示Pacman的张嘴/闭嘴动画?

发布于 2024-07-14 21:02:00 字数 988 浏览 10 评论 0原文

我试图在我正在制作的一次性吃豆人游戏中展示吃豆人角色著名的张嘴/闭合动画,以自学游戏编程。

我正在做的是绘制张开嘴的图像,然后在完全相同的 (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);
}

I'm trying to show the famous mouth opening/closing animation of the pacman character in a throwaway pacman game I'm making to teach myself game programming.

What I'm doing is drawing the open mouth image, then redrawing the closed mouth image at the exact same (x/y) location. But this doesn't work, and I just see the closed mouth animation all the time.

If I put this in a loop, the system just freezes and you see flickering where the open mouth image this, but you don't see the images being replaced.

I've tested and made sure that both images are being loaded correctly and as expected.

Here's my startAnim() function, its called when you double click at the applet:

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);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

入画浅相思 2024-07-21 21:02:00

你必须在两张图片之间睡觉。 否则你只会看到最后绘制的图像。

例如。

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) {}
            }
}

you have to sleep between the 2 images. otherwise you will only see the last image painted.

eg.

while( running )
{
    image 1
    draw
    sleep
    image 2
    draw
    sleep
}

something like this:

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) {}
            }
}
风和你 2024-07-21 21:02:00

正如 sfossen 所说,绘制图像之间需要一段延迟。

还有其他一些需要考虑的事情。

  • 为了获得流畅的动画效果,您可能需要的不仅仅是“张嘴”和“闭嘴”图像。 您需要两个或三个中间图像。
  • 为了使资源管理更容易,您可能希望将所有动画帧放在一个宽图像中,该图像看起来像“幻灯片”。 然后,要绘制一个框架,您可以使用您感兴趣的框架的 (x, y) 偏移量。
  • 最后,如果您每次执行程序的主循环时都绘制所有框架,吃豆人将完成一次完整的绘制每次你移动他时都会咀嚼。 您应该考虑每次通过主循环仅绘制一帧,并使用变量来跟踪您所在的帧。

示例(伪代码)

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.
}

As sfossen said, you need a delay between drawing the images.

A couple of other things to consider.

  • For smooth animation, you probably need more than just the "mouth open" and "mouth closed" images. You need two or three intermediate images.
  • To make resource management easier, you might want to put all of your animation frames together in a single, wide image, that will look like a "filmstrip". Then, to draw a frame, you use the (x, y) offset for the frame your interested in.
  • Finally, if you draw all the frames each time you go through the main loop of your program, Pac-Man will do a complete chomp every time you move him. You should think about drawing just one frame each time through the main loop and using a variable to track which frame you're on.

Example (pseudocode)

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.
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文