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

LibGDX精灵点击输入方法中timesClicked变量修改问题

解决LibGDX精灵点击计数与计时器的变量访问问题

问题根源

Java中内部类(比如你用到的TimerTask)访问方法内的局部变量时,要求变量必须是final或等效final,但基本类型的局部变量一旦声明为final就无法修改,这就是核心矛盾。而直接用静态变量会导致多个精灵共享同一计数,出现点击不同精灵时计数混乱的问题,并非合理方案。

可行解决方案

方案1:使用可变包装类

用可修改内部值的对象包装计数,比如AtomicInteger(线程安全)或自定义简单Holder类,内部类可通过final的对象引用修改内部值。

示例代码(用AtomicInteger):

import java.util.concurrent.atomic.AtomicInteger;

public static void displayItem(Player Dawid, Item item, Sprite itemSprite){
    // 用AtomicInteger包装点击计数
    AtomicInteger timesClicked = new AtomicInteger(0);

    if (Gdx.input.justTouched()) {
        camera.unproject(touchPoint.set(Gdx.input.getX(), Gdx.input.getY(), 0));
        if (itemSprite.getBoundingRectangle().contains(touchPoint.x, touchPoint.y)) {
            if (timesClicked.get() == 1){
                Shop.checkRequirement(item.getBuyPrice(), Dawid, item);
                Dawid.setGold(Dawid.getGold() - item.getBuyPrice());
                item.setStock(item.getStock()+1);
                topText = "Kupiłeś eliksir zdrowia!";
            }
            Assets.sellText = item.getSellPrice() + "g";
            Assets.buyText = item.getBuyPrice() + "g";
            
            timesClicked.incrementAndGet();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    timesClicked.set(0);
                }
            }, 500);
        }
    }
}

自定义Holder类替代方案:

// 在当前类内部定义静态Holder类
static class IntHolder {
    int value;
}

// 方法内使用
public static void displayItem(Player Dawid, Item item, Sprite itemSprite){
    IntHolder timesClicked = new IntHolder();

    if (Gdx.input.justTouched()) {
        camera.unproject(touchPoint.set(Gdx.input.getX(), Gdx.input.getY(), 0));
        if (itemSprite.getBoundingRectangle().contains(touchPoint.x, touchPoint.y)) {
            if (timesClicked.value == 1){
                Shop.checkRequirement(item.getBuyPrice(), Dawid, item);
                Dawid.setGold(Dawid.getGold() - item.getBuyPrice());
                item.setStock(item.getStock()+1);
                topText = "Kupiłeś eliksir zdrowia!";
            }
            Assets.sellText = item.getSellPrice() + "g";
            Assets.buyText = item.getBuyPrice() + "g";
            
            timesClicked.value++;
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    timesClicked.value = 0;
                }
            }, 500);
        }
    }
}

方案2:将计数设为类成员变量(非静态)

如果点击计数属于当前类实例而非全局共享,把timesClicked定义为类的非静态成员变量,内部类可直接访问,无需final修饰。

示例代码:

// 在类内部声明成员变量
private int timesClicked = 0;

public void displayItem(Player Dawid, Item item, Sprite itemSprite){
    if (Gdx.input.justTouched()) {
        camera.unproject(touchPoint.set(Gdx.input.getX(), Gdx.input.getY(), 0));
        if (itemSprite.getBoundingRectangle().contains(touchPoint.x, touchPoint.y)) {
            if (timesClicked == 1){
                Shop.checkRequirement(item.getBuyPrice(), Dawid, item);
                Dawid.setGold(Dawid.getGold() - item.getBuyPrice());
                item.setStock(item.getStock()+1);
                topText = "Kupiłeś eliksir zdrowia!";
            }
            Assets.sellText = item.getSellPrice() + "g";
            Assets.buyText = item.getBuyPrice() + "g";
            
            timesClicked++;
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    timesClicked = 0;
                }
            }, 500);
        }
    }
}

注意:若方法处理多个精灵点击,需给每个精灵绑定独立计数(比如在Item类中添加点击计数属性),避免不同精灵共用同一计数。

方案3:使用LibGDX自带的Timer

LibGDX的com.badlogic.gdx.utils.Timer在主线程执行任务,避免Java Timer的线程问题,写法更简洁:

import com.badlogic.gdx.utils.Timer;

public static void displayItem(Player Dawid, Item item, Sprite itemSprite){
    AtomicInteger timesClicked = new AtomicInteger(0);

    if (Gdx.input.justTouched()) {
        camera.unproject(touchPoint.set(Gdx.input.getX(), Gdx.input.getY(), 0));
        if (itemSprite.getBoundingRectangle().contains(touchPoint.x, touchPoint.y)) {
            if (timesClicked.get() == 1){
                Shop.checkRequirement(item.getBuyPrice(), Dawid, item);
                Dawid.setGold(Dawid.getGold() - item.getBuyPrice());
                item.setStock(item.getStock()+1);
                topText = "Kupiłeś eliksir zdrowia!";
            }
            Assets.sellText = item.getSellPrice() + "g";
            Assets.buyText = item.getBuyPrice() + "g";
            
            timesClicked.incrementAndGet();
            // LibGDX Timer参数为秒,0.5秒即500毫秒
            Timer.schedule(new Timer.Task() {
                @Override
                public void run() {
                    timesClicked.set(0);
                }
            }, 0.5f);
        }
    }
}

注意事项

  • 禁止用静态变量存点击计数:静态变量全局共享,多精灵点击时会互相干扰,导致计数逻辑混乱。
  • 线程安全:Java的TimerTask在后台线程执行,修改UI相关变量需注意线程安全;LibGDX的Timer任务在主线程执行,更适配UI操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 14:20:32