Java LibGdx-我怎么能不在每一帧加载纹理?

Java LibGdx-我怎么能不在每一帧加载纹理?,java,libgdx,Java,Libgdx,我对Java和LibGdx有点陌生,但对于我的学校项目,我需要制作一个玩家精灵的动画。 对于每个玩家只有一个动画,我为此制作的Methode一切顺利,但现在我还需要一个行走、空转和战斗动画。我设法让动画切换,但现在的问题是,每个动画只显示一帧。经过一些研究,我知道我需要停止更新我的纹理每帧,但我无法知道如何做到这一点。 到目前为止,我在更新之前尝试了一个简单的计时器,但这看起来很奇怪。 这是我的密码: public Player(){ img3 = new Texture(&qu

我对Java和LibGdx有点陌生,但对于我的学校项目,我需要制作一个玩家精灵的动画。 对于每个玩家只有一个动画,我为此制作的Methode一切顺利,但现在我还需要一个行走、空转和战斗动画。我设法让动画切换,但现在的问题是,每个动画只显示一帧。经过一些研究,我知道我需要停止更新我的纹理每帧,但我无法知道如何做到这一点。 到目前为止,我在更新之前尝试了一个简单的计时器,但这看起来很奇怪。 这是我的密码:

public Player(){
        img3 = new Texture("platform_metroidvania asset pack v1.01/herochar sprites(new)/herochar_idle_anim_strip_4.png");
        img = new Texture("platform_metroidvania asset pack v1.01/herochar sprites(new)/herochar_idle_anim_strip_4.png");
        img1 = new Texture("platform_metroidvania asset pack v1.01/herochar sprites(new)/herochar_run_anim_strip_6.png");
        img2 = new Texture("platform_metroidvania asset pack v1.01/herochar sprites(new)/herochar_sword_attack_anim_strip_4.png");

        animation();
        changeCharacter();
    }



    public static void animation(){
        if(Gdx.input.isButtonPressed(Input.Buttons.LEFT)){
            img3 = img2;
            amount = 3;
            tileWidth = 32;
        }else if(Gdx.input.isKeyPressed(Input.Keys.D) || Gdx.input.isKeyPressed(Input.Keys.A)){
            img3 = img1;
            tileWidth = 16;
            amount = 3;
        }else{
            img3 = img;
            amount = 3;
            tileWidth = 16;
        }
    }

    public static void changeCharacter(){
        batch = new SpriteBatch();
        regions = TextureRegion.split(img3, tileWidth, 16);
        sprite = new Sprite(regions[0][0]);
        sprite.setPosition(x,y);

        Timer.schedule(new Timer.Task() {
            @Override
            public void run() {
                frame++;
                if (frame > amount) {
                    frame = 0;
                }
                sprite.setRegion(regions[0][frame]);
            }
        }, 0, 1 / 12f);

    }
在render()中调用方法“动画”和“changeCharacter”。 我知道在LibGdx中有更简单的解决方案,但我的其余代码都基于此,我基本上必须重写整个项目。。。 如果你还需要其他课程,尽管问。我可能会问一个很简单的问题,但我不知道该怎么办。

您需要先重命名。
img3
看起来像是指向currentTextureSet的指针。因此,当您在
Player()
中初始化时,您可能希望将
img3
重命名为
currentTextureSet
,然后设置,而不是重复加载
herochar\u idle\u anim\u strip\u 4.png
currentTextureSet=img
之后
(您可能还希望将
img
img1
img2
重命名为
idleTextureSet
runTextureSet
swordatattackTextureSet

除此之外, 一定要去掉Timer.schedule,它将在后台线程中运行,您不希望这样

查看此处的资产包(如果是相同的资产包),应选择从左到右的图像,即
x
应递增,而不是
y
。但是,它看起来像是递增的
y
。。。
sprite.setRegion(regions[0][frame])
和不正确的数组访问被吞没,因为在后台计时器任务中,您可以访问的唯一纹理区域是
[0][0]
,即您只看到一个帧

所以把这个扔了

  Timer.schedule(new Timer.Task() {
            @Override
            public void run() {
                frame++;
                if (frame > amount) {
                    frame = 0;
                }
                sprite.setRegion(regions[0][frame]);
            }
        }, 0, 1 / 12f);
并替换为

frame++;
if (frame > amount) {
frame = 0;
}
sprite.setRegion(regions[frame][0]);
*编辑 因此,这意味着您的帧会随着每次渲染而更新,这太快了。所以-简单易碎的方式-(不是最好的,这将是德尔塔蒂姆请阅读这篇优秀的文章)。在没有时间的情况下,最简单的方法(不是最好的方法)是申报

long renderCallCount =0;
将上面的语句放在声明帧的位置,然后放在渲染方法中

renderCallCount++; //One more render call
if (renderCallCount % 60 == 0) { //Should I update frame?
    frame++;
    if (frame > amount) {
                    frame = 0;
    }
    sprite.setRegion(regions[0][frame]);
}
因此,每当使用mod运算符将
renderCallCount
除以
60
时(如果刷新率为60hz,则为每秒一次),则帧将递增。要每秒切换两次帧,请将
60
更改为
30

这假设您的监视器仅以60hz的频率运行。我认为您的应用程序可能取决于职位更新的刷新率,因此您可能希望根据本文中的一些想法在将来进行更新。在帧速率更快的显示器上,一切都会(一致地)加速。

我刚刚把一些东西按正确的顺序放好,现在就可以工作了!我真的不明白为什么mod运算符后面的数字需要这么小,但除此之外,它看起来就是不正确。另外,我知道您不应该在render()中创建Spritebatch,但是当我在构造函数中创建Spritebatch时,程序只是因为缺少Spritebatch而崩溃???但感谢您的帮助:)以下是适用于任何对此感兴趣的人的工作代码:

public static void animation(){
    if(Gdx.input.isButtonPressed(Input.Buttons.LEFT) && InfoGame.cl.isGrounded() && current > Enemy.lastDmg + Enemy.dmgCool){
        currentTextureSet = attackTexture;
        amount = 3;
        tileWidth = 32;
    }else if(Gdx.input.isKeyPressed(Input.Keys.D) || Gdx.input.isKeyPressed(Input.Keys.A)){
        currentTextureSet = runTexture;
        tileWidth = 16;
        amount = 3;
    }else{
        currentTextureSet = idleTexture;
        amount = 3;
        tileWidth = 16;
    }
}

public static void changeCharacter(){
    batch = new SpriteBatch();
    regions = TextureRegion.split(currentTextureSet, tileWidth, 16);
    sprite = new Sprite(regions[0][0]);
    sprite.setPosition(x,y);
    sprite.setOrigin(8,8);
    if (renderCallCount % 6 == 0) {
        frame++;
        if (frame > amount) {
            frame = 0;
        }
    }
    sprite.setRegion(regions[0][frame]);
}

谢谢你的帮助。我做了你建议的一切,我认为我的x和y是正确的,因为它现在已经动画了,但是因为没有计时器了,动画以非常快的速度运行。有没有办法解决这个问题?我现在想了很多方法,一个带delta time的计时器是最成功的一个,但是这导致了我一开始犯的同样的错误。所以我仍然不知道如何避免这些问题,不要使用计时器。要制作动画,请在成员字段中使用
Graphics.getDeltaTime()
,将经过的时间相加,然后计算当前应使用该字段显示的帧。对不起,我该怎么做?正如我前面所说的,我对Java是新手。是的,所以动画会改变每一帧,因为你依赖于渲染帧的时间。但是,您不知道这些天何时调用渲染。我将编辑答案。不要在
render()
中调用的方法中创建SpriteBatch。这将造成巨大的内存泄漏,并最终导致游戏崩溃。在
Create()
中创建一次SpriteBatch。至于你的问题,你可以使用libGDX动画类吗?这会让事情变得更简单。