libgdx-Actions创建了口吃

时间:2014-02-21 11:13:18

标签: java libgdx action game-physics

我试图改善我的数字的运动,但我找不到他们口吃的真正原因。我正在使用SequenceAction移动它们,其中MoveToActionRunnableAction会重置moveDone标记,以便可以开始新动作。

游戏本身是基于网格的,因此如果移动完成,则序列开始根据方向移动到下一个网格。所以这是它的样子:

请注意,这是图中的行为

....//some more here
if (checkNextMove(Status.LEFT)) //check if the position is valid
{
    status = Status.LEFT; //change enum status
    move(Status.LEFT); // calls the move
    screen.map.mapArray[(int) mapPos.x][(int) mapPos.y] = Config.EMPTYPOSITION;
    screen.map.mapArray[(int) (mapPos.x - 1)][(int) mapPos.y] = Config.CHARSTATE;
    mapPos.x--;
    moveDone = false;
}
//... same for the up down right and so on.
//at the end of this checking the updating of the actor:
// methode from the absctract to change sprites
updateSprite(delta);
super.act(delta); // so the actions work
//end of act

这是移动方法,它确实添加了动作

protected void move(Status direction)
{
    // delete all old actions if there are some left.
    clearActions();
    moveAction.setDuration(speed);
    //restart all actions to they can used again
    sequence.restart();
    switch (direction)
    {
    case LEFT:
        moveAction.setPosition(getX() - Config.TILE_SIZE, getY());
        addAction(sequence);
        break;
    case RIGHT:
        moveAction.setPosition(getX() + Config.TILE_SIZE, getY());
        addAction(sequence);
        break;
    case UP:
        moveAction.setPosition(getX(), getY() + Config.TILE_SIZE);
        addAction(sequence);
        break;
    case DOWN:
        moveAction.setPosition(getX(), getY() - Config.TILE_SIZE);
        addAction(sequence);
        break;
    default:
        break;
    }
}

这些数字并没有真正变得模糊不清。

  • 任何人确实看到了一个错误,或者是不是可以让他们像这样移动?
  • 如果开始新动作,它总会有点卡顿。所以我认为这可能不会很好。是否有不同的方法将它们从一个网格移动到另一个网格? (尝试使用movingpeed * delta时间,但这不能正常工作,我使用了动作模型)
  • 它似乎会使一个框架出现问题,例如它不会移动。

这是口吃的mp4视频: stuttering.mp4

就提一下,相机运动就好了。它是模糊的,但你可以看到这个数字口吃,我希望

2 个答案:

答案 0 :(得分:0)

如果您使用moveAction每次移动,则应致电moveAction.restart()重置其中的计数器:

// delete all old actions if there are some left.
clearActions();
sequence.reset(); // clear sequence
// add movementspeed. Note it can change!
moveAction.restart();
moveAction.setDuration(speed);

<强>更新

现在出现问题,因为您在restart之后致电SequenceAction clearActions()。如果您的clearActions()移除了SequenceAction中的所有操作,则restart将调用空SequenceAction。所以,请改为:

//restart all actions to they can used again
sequence.restart();
// delete all old actions if there are some left.
clearActions();
moveAction.setDuration(speed);

答案 1 :(得分:0)

好的,所以我自己解决了。它与周围的序列变化无关。它与act()数字的更新频率有关。 MoveToAction在时间给出的2个点之间进行插值。因此,如果上次更新,将MoveToAction更新为“很长时间”,则需要超过100%的操作。所以它会向远方移动,但行动不会这样做,它设定了最终位置,这就是它应该做的事情。这就是为什么它看起来不流畅。

Discription of the real problem

那么如何解决这个问题呢?

通过减少更新时间,“到远距离移动”也会因步长变小而减小。所以我需要增加60fps以上的更新速度。幸运的是,我得到了一个更新数字和位置的线索,等等。 GameLogicThread。这也是60fps。所以我通过增加它的频率解决了口吃。目前高达210fps左右,因此“超越”是最小的。你甚至都注意不到它。

显示我的主题如何运作:

public class GameLogicThread extends Thread
{
    private GameScreen m_screen;
    private boolean m_runing;
    private long m_timeBegin;
    private long m_timeDiff;
    private long m_sleepTime;
    private final static float FRAMERATE = 210f;

    public GameLogicThread(GameScreen screen)
    {
        m_screen = screen;
        setName("GameLogic");
    }

    @Override
    public void run()
    {
        m_runing = true;
        Logger.log("Started");
        while (m_runing)
        {
            m_timeBegin = TimeUtils.millis();
            // hanlde events
            m_screen.m_main.handler.processEvents();
            synchronized (m_screen.figureStage)
            {
                // now figures
                if (m_screen.m_status == GameStatus.GAME)
                {
                    m_screen.character.myAct(1f / GameLogicThread.FRAMERATE);// and here it is ;)
                    m_screen.figureStage.act(1f / GameLogicThread.FRAMERATE);
                }
            }
            m_timeDiff = TimeUtils.millis() - m_timeBegin;
            m_sleepTime = (long) (1f / GameLogicThread.FRAMERATE * 1000f - m_timeDiff);
            if (m_sleepTime > 0)
            {
                try
                {
                    Thread.sleep(m_sleepTime);
                }
                catch (InterruptedException e)
                {
                    Logger.error("Couldn't sleep " + e.getStackTrace());
                }
            }
            else
            {
                Logger.error("we are to slow! " + m_sleepTime);
            }
        }
    }

    public void stopThread()
    {
        m_runing = false;
        boolean retry = true;
        while (retry)
        {
            try
            {
                this.join();
                retry = false;
            }
            catch (Exception e)
            {
                Logger.error(e.getMessage());
            }
        }
    }
}