繁体   English   中英

LibGdx - 如何不加载每一帧的纹理?

[英]LibGdx - How can I not load my textures every single frame?

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

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 中有更简单的解决方案,但我的代码的 rest 是基于此的,我基本上必须重写整个项目......如果您需要任何其他类,请问。 我可能会问一个非常简单的事情,但我不知道该怎么做。

您需要先重命名。 img3看起来像是用作指向 currentTextureSet 的指针。 因此,当您在Player()中初始化时,您可能希望将img3重命名为currentTextureSet ,然后设置currentTextureSet = img;而不是herochar_idle_anim_strip_4.png的重复加载之后(您可能还想将imgimg1img2重命名为idleTextureSetrunTextureSetswordAttackTextureSet )。

除此之外,绝对摆脱您从渲染调用的 Timer.schedule 将在您不希望的后台线程中运行。

在这里查看资产包https://o-lobster.itch.io/platformmetroidvania-pixel-art-asset-pack?download如果这是同一个,则应从左到右选择图像,即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]);

*编辑所以这意味着你的帧随着每次渲染而更新,这太快了。 所以 - 简单易碎的方式 - (不是最好的 deltaTime 请阅读这篇优秀的文章https://gafferongames.com/post/fix_your_timestep/ )。 在没有时间的情况下,最简单的方法不是最好的方法是声明

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]);
}

因此,每当renderCallCount使用 mod 运算符https://www.edureka.co/blog/mod-method-in-java/可被60整除时,如果您的刷新率为 60hz,这将是每秒一次,那么您的帧就会递增. 每秒切换两次帧将60更改为30 这假设您的显示器只能以 60hz 运行。 我认为您的应用程序可能取决于 position 更新的刷新率时间,因此您可能希望将来根据文章中的一些想法对其进行更新。 在具有更快帧速率的显示器上,一切都会(始终如一地)加速。

我只是按正确的顺序放置了一些东西,它现在可以工作了。 我真的不明白为什么 mod 运算符之后的数字需要这么小,否则它看起来不正确? 我也知道你不应该在 render() 中创建 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]);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM