为什么我的java使pacMan克隆有时候会变得迟钝?

时间:2011-09-29 19:40:38

标签: java eclipse lag

我正在使用eclipse在java中使用pacman克隆,有时它看起来更加特别,因为pacman / ghosts的运动很慢,有时它很好。一旦它在我运行时发生,所以它不是在我添加代码之后,它似乎不是在游戏中的任何特定事件之后。我无法找到任何触发器或故意产生延迟

资源管理器显示相同的CPU使用率(仅约50%)/内存使用量。此外,FPS似乎在延迟时间和运行良好期间始终保持在200左右。

有谁知道这可能是什么?

我遗漏的任何信息是否有用?

编辑 - 我基于计时器的动作是不是很糟糕?我将在下面发布运动相关代码是否有一个很好的方式在这里发布整个代码?

Timer movement = new Timer(20, new ActionListener()//500 is time in milliseconds between
      //calls to actionPerformed as far as I know.
    {
        public void actionPerformed(ActionEvent arg0) 
        {
            if(movingUp == true)
            {
                moveUp();
            }
            else if(movingDown == true)
            {
                moveDown();
            }
            else if(movingRight == true)
            {
                moveRight();
            }
            else if(movingLeft == true)
            {
                moveLeft();
            }

        }

    });


public void moveUp()
    {
        yPos -= 1;
        this.rect.y -= 1;
    }

public void setDirUp()
    {
        movingUp = true;
        movingDown = false;
        movingRight = false;
        movingLeft = false;
    }

在public void keyPressed的主类中:

if(keyCode == KeyEvent.VK_W)
        {
            if(pacMan.isUpHittingWall == false)
            {
                pacMan.setDirUp();

                pacMan.isDownHittingWall = false;
                pacMan.isRightHittingWall = false;
                pacMan.isLeftHittingWall = false;
            }

        }

编辑2 - 感谢帮助人员。我现在使用系统时间的运动,它似乎已经修复了这个问题,因为我最初只为pacman实现了它,并且幽灵仍然很慢。现在有一个问题,向右和向下移动要比向左或向上移动慢得多。我看到的唯一区别是向右和向下都是加法,左右都在减去。我该怎么办?

更新的代码如下。

//updated movement code
public void moveUp(long timePassed)
    {
        yPos -= vy * timePassed;
        this.rect.y -= vy * timePassed;
    }

    public void moveDown(long timePassed)
    {
        yPos += vy * timePassed;
        this.rect.y += vy * timePassed;
    }

    public void moveRight(long timePassed)
    {
        xPos += vx * timePassed;
        this.rect.x += vx * timePassed;
    }

    public void moveLeft(long timePassed)
    {
        xPos -= vx * timePassed;
        this.rect.x -= vx * timePassed;
    }


//I passed timePassed through a globalInputObject because my input is handled in public //void keyPressed(KeyEvent e) and I didnt know how else to get timePassed in to the //movement method

//Here is the code in gameLoop()
                 globalInputObject.isPacManMovingUp(timePassed);
             globalInputObject.isPacManMovingDown(timePassed);
             globalInputObject.isPacManMovingRight(timePassed);
         globalInputObject.isPacManMovingLeft(timePassed);




//This is inside the GlobalInputObject
public void isPacManMovingUp(long timePassed)
    {
        if(pacMan.movingUp == true)
        {
            pacMan.moveUp(timePassed);
        }
    }

    public void isPacManMovingDown(long timePassed)
    {
        if(pacMan.movingDown == true)
        {
            pacMan.moveDown(timePassed);
        }
    }

    public void isPacManMovingRight(long timePassed)
    {
        if(pacMan.movingRight == true)
        {
            pacMan.moveRight(timePassed);
        }
    }

    public void isPacManMovingLeft(long timePassed)
    {
        if(pacMan.movingLeft == true)
        {
            pacMan.moveLeft(timePassed);
        }
    }

3 个答案:

答案 0 :(得分:2)

每次定时器运行时,不应总是将pacman移动一个恒定距离(1像素,它出现),你应该:

  1. 将计时器设置为尽可能快地运行(例如每毫秒或更少一次)。 编辑:如果你设置得太快,游戏可能最终会慢慢运行,你必须进行实验。
  2. 使用system clock计算每帧之间经过的时间,并将pacman移动一个与之成比例的数量。
  3. 执行上述操作意味着如果系统“滞后”,它将只显示每秒更少的帧数,而不是实际上将所有帧移动得更慢。

答案 1 :(得分:2)

正如我所担心的那样,你的距离是基于计时器的时间块。你不应该这样做,因为所有的定时器都是可变的和不可靠的,特别是对于小的时间块。最好根据系统时间差异进行移动。所以是的,使用计时器或其他东西来运行你的“游戏循环”,但是使用双精度知道精灵的位置和速度,并根据速度矢量(数学矢量而非Java矢量)计算移动距离*系统时间的差异。这样,如果计时器被垃圾收集延迟,使得时间块更大,移动的距离将相应更大并且看起来更平滑。

答案 2 :(得分:1)

你应该考虑创建一个适当的“主循环”或“游戏循环”。看看this wikipedia article.的游戏结构部分。基本上,这些输入事件是从主线程以外的单独线程中调用的,它们直接修改游戏对象的几何体。而是考虑这样的主循环:

loop:
    process collision detection
    process animation (alters geometry of game objects)
    process input (more on this later)
    any other game specific logic
    render screen

您的流程输入可能是这样的

if (globalInputObject.movingUp==true) {
   hero.y -= 10;
}
if (globalInputObject.movingDown==true) {
   hero.y += 10;
}
if (globalInputObject.movingLeft==true) {
   hero.x -= 10;
}
if (globalInputObject.movingRight==true) {
   hero.x += 10;
}

并且您的输入处理程序将如下所示:

public void actionPerformed(ActionEvent evt) {
    if (evt.button==UP_BUTTON) {
        globalInputObject.movingUp=true;
    }
    if (evt.button==DOWN_BUTTON) {
        globalInputObject.movingDown=true;
    }
    if (evt.button==LEFT_BUTTON) {
        globalInputObject.movingLeft=true;
    }
    if (evt.button==RIGHT_BUTTON) {
        globalInputObject.movingRight=true;
    }

}

基本上,您在“额外”线程(输入线程)中执行的处理是最小的,因此不会干扰您的主线程。此外,这种方法有利于同时轻松支持多个方向(即:UP + RIGHT =对角线)。

只有超高端游戏才有多个线程(如果他们甚至需要它)。处理游戏中的同步对性能不利。