You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LibGDX开发蛇梯棋时如何通过setPosition让Sprite缓慢移动?

问题根源

你现在看到玩家瞬间跳位,根本原因是updatePlayer(int dice)里的for循环会在同一帧内全部跑完。LibGDX的游戏循环规则是:先把当前帧的所有逻辑代码执行完,再统一渲染一次。哪怕你在循环里多次调用渲染方法,本质上一帧就把骰子对应的所有位移都算完了,自然看不到移动过程。

解决方法

别把多步移动塞在一个for循环里一次性跑完,把移动拆成多帧推进,每帧只动一点点,自然就能看到平滑的移动效果。

第一步:给玩家类加几个状态变量

不再触发移动就一次性移完,而是把移动任务存起来,交给每帧循环处理:

// 标记玩家是否正在移动中
private boolean isMoving = false;
// 还剩多少步没走
private int remainingSteps = 0;
// 平滑移动的速度,单位 像素/秒,自己根据手感调
private float moveSpeed = 120f;
// 单步移动的起点、终点坐标,用来做平滑插值
private float startX, startY, targetX, targetY;

第二步:写移动触发的入口

掷出骰子拿到点数后,别直接跑旧的for循环,而是把移动任务登记好:

public void startMove(int dice) {
    // 点数校验,正在移动的时候不接新的移动指令
    if (dice < 1 || dice > 6 || isMoving) return;
    remainingSteps = dice;
    isMoving = true;
    // 算第一步要去的位置
    calculateNextStepTarget();
}

// 算下一格的目标位置,替换你原来循环里的位移逻辑
private void calculateNextStepTarget() {
    // 把当前位置记为这一步的起点
    startX = getX();
    startY = getY();
    float gridSize = 48; // 就是你代码里用的单格宽度48
    float nextX = startX + gridSize;
    // 到棋盘右边界了,就换行到最左侧,往上走一格
    if (nextX > GameInfo.WIDTH - 20) {
        targetX = 20; // 换成你棋盘最左侧的实际x坐标就行
        targetY = startY + gridSize;
    } else {
        targetX = nextX;
        targetY = startY;
    }
}

第三步:每帧推进移动逻辑

改原来的无参updatePlayer方法,记得要把LibGDX每帧传的deltaTime(两帧之间的间隔秒数)当参数传进来,用时间差算移动距离,不然不同帧率的设备上移动速度会不一样:

public void updatePlayer(float deltaTime) {
    // 没在移动的话,正常渲染就行
    if (!isMoving) {
        drawSprite();
        return;
    }
    // 算这一帧能走的距离
    float frameMoveDist = moveSpeed * deltaTime;
    // 算当前这一步起点到终点的总距离
    float totalStepDist = (float) Math.hypot(targetX - startX, targetY - startY);
    // 如果这一帧走的距离已经超过到终点的剩余距离,说明这一步走完了
    if (frameMoveDist >= totalStepDist) {
        setPosition(targetX, targetY);
        remainingSteps--;
        // 还有剩的步数,就算下一格的目标
        if (remainingSteps > 0) {
            calculateNextStepTarget();
        } else {
            // 所有步数走完,结束移动状态
            isMoving = false;
        }
    } else {
        // 还没到终点,按比例平滑挪过去
        float progress = frameMoveDist / totalStepDist;
        float newX = startX + (targetX - startX) * progress;
        float newY = startY + (targetY - startY) * progress;
        setPosition(newX, newY);
    }
    // 渲染当前位置的Sprite
    drawSprite();
}

// 把你原来的渲染逻辑封装一下
private void drawSprite() {
    game.getBatch().begin();
    draw(game.getBatch());
    game.getBatch().end();
}
几个代码里的注意点
  • 原来的逻辑里每挪一点就开关一次SpriteBatch,这完全是不必要的性能浪费。实际一帧只需要在所有渲染前开一次begin(),所有东西画完关一次end()就行,不用单个Sprite就开关一次batch。
  • 想更像真实蛇梯棋的节奏,可以在单步走完之后加个0.2秒左右的停顿,等停完再走下一格,不然移动会太急。
  • moveSpeed的数值可以根据实际视觉效果调整,数值越大移动越快。

内容的提问来源于stack exchange,提问作者Melih

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.27 06:15:02