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

LibGDX中如何在for循环内实现延迟执行效果?

LibGDX 实现Simon Says按钮序列播放的解决方案

原有代码问题分析

原有代码无法实现预期效果,核心问题有两点:

  • 循环中所有定时任务的延迟参数完全相同,循环执行耗时极短,所有按钮会几乎同时触发状态切换,没有按顺序播放的效果
  • LibGDX的Timer默认在后台线程执行任务,直接在任务中修改按钮UI属于跨线程操作,存在线程安全风险,可能出现画面闪烁、操作无响应等异常

方案1:修正Timer调度逻辑(快速实现)

调整每个任务的延迟时间,实现按顺序亮灭,同时将UI操作抛到LibGDX的GL渲染线程执行,避免线程安全问题:

val stepDelay = 1f // 单个按钮的亮灯时长,单位秒
val gapDelay = 0.3f // 两个按钮亮灯之间的间隔时长,单位秒

for (i in 0 until array.size) {
    // 计算当前按钮的点亮、熄灭时间点
    val lightOnTime = i * (stepDelay + gapDelay)
    val lightOffTime = lightOnTime + stepDelay

    // 调度点亮任务
    Timer.schedule(object : Timer.Task() {
        override fun run() {
            // 把UI操作抛到渲染线程执行
            Gdx.app.postRunnable {
                array[i].toggle()
            }
        }
    }, lightOnTime)

    // 调度熄灭任务
    Timer.schedule(object : Timer.Task() {
        override fun run() {
            Gdx.app.postRunnable {
                array[i].toggle()
            }
        }
    }, lightOffTime)
}

方案2:自定义序列控制器(更稳定可控)

游戏场景更推荐该方案,完全在渲染线程执行,没有线程安全问题,还可以自由控制暂停、重播、快进等操作:
首先定义序列控制器类:

class SimonSequencePlayer(
    private val buttons: List<Button>, // 你的按钮数组
    private val stepDelay: Float = 1f,
    private val gapDelay: Float = 0.3f
) {
    private var isPlaying = false
    private var elapsedTime = 0f
    private var currentStep = 0
    private var isLightOn = false // 当前步骤的按钮是否处于亮灯状态

    fun startPlay() {
        isPlaying = true
        elapsedTime = 0f
        currentStep = 0
        isLightOn = false
    }

    // 在render方法中每帧调用,传入delta时间
    fun update(delta: Float) {
        if (!isPlaying || currentStep >= buttons.size) return

        elapsedTime += delta
        val targetDuration = if (isLightOn) stepDelay else gapDelay

        if (elapsedTime >= targetDuration) {
            elapsedTime -= targetDuration
            if (isLightOn) {
                // 熄灭当前按钮
                buttons[currentStep].toggle()
                currentStep++
                isLightOn = false
                // 所有步骤播放完成
                if (currentStep >= buttons.size) {
                    isPlaying = false
                }
            } else {
                // 点亮下一个按钮
                buttons[currentStep].toggle()
                isLightOn = true
            }
        }
    }
}

使用方式:

  1. 初始化控制器实例val player = SimonSequencePlayer(buttonArray)
  2. 需要播放序列时调用player.startPlay()
  3. 在游戏的render()方法中每帧调用player.update(Gdx.graphics.deltaTime)即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 14:27:03