Libgdx:从多个纹理图集中渲染已排序的精灵

时间:2014-01-07 12:23:24

标签: java opengl libgdx depth-buffer

我需要在屏幕上以 libgdx (平均20-30)渲染对象,所有对象都按Y值排序,因此首先渲染具有最低Y值的精灵。 (想想这个观点http://i.stack.imgur.com/m1VQA.gif

该游戏使用纹理图集,每个尺寸为2048 * 2048.

我目前有三张地图集。一个用于可玩角色,一个用于NPC角色,一个用于动物/怪物。最终我们计划添加许多不同的对象,npc集等等,所以将所有精灵混合到一个大的地图集不是一个选项(在设计和硬件上都会非常有限)。

当前渲染方法首先在屏幕上按Y值对屏幕上的对象进行排序,然后绘制它们。这种方法非常有效,除了事实,这样一来,很多纹理切换都会出现。

例如,渲染: - 3只动物 - 2 npc's - 球员 - 1 npc - 1只动物 - 1 npc - 2只动物,

需要7次纹理切换。这完全取决于屏幕上的物体位置。

通过地图集对精灵进行排序不是一种选择(首先绘制动物,然后是npc,然后是玩家),因为这会使Y排序变得不可能。

(我想到的第一件事就是将纹理图集增加到8192 * 8192,但许多旧的台式机和移动设备将无法运行游戏。我想到的第二件事是某种深度缓冲,但如果可能的话,我不确定如何做到这一点。)

必须使用哪种方法来实现所需的结果(从多个纹理中分类精灵),同时保持稳定的帧速率?有没有可行的openGL技巧呢?我应该担心每帧有6-7个纹理切换吗?

2 个答案:

答案 0 :(得分:1)

看到此链接是libgdx test,测试时有z作为深度,但你可以使用y轴

SortedSpriteTest

你需要使用比较器并对数组进行排序,这显然会降低游戏的性能。

答案 1 :(得分:-1)

实际上,如果你给你的Actor指定的Sprite为attribut,那应该不是问题。你渲染东西时永远不会加载任何东西。如果你创建你的Actors,你会从Atlas加载精灵,纹理等,并将它交给你的Actor。像这样:

Texture monster = getTextureByType(type);
Monster mon = new Monster(level, new Sprite(monster), screen, ai,npc);

你的怪物(演员!)里面你把它们保存为你的精灵。我认为常规构造函数

public Monster(int level, Sprite sprite, GameScreen screen, AIInterface ai,
                boolean npc) {
            this.life = 300;
            this.curLife = 200;
            this.ai = ai;
            this.level = level;
            this.sprite = sprite;
            this.sprite.setRegion(0, 0, 32, 48);
    }

抽奖很简单:

    @Override
    public void draw(SpriteBatch batch, float parentAlpha) {
        if (alife) {
            sprite.setPosition(this.getX() + ofset, this.getY());
            sprite.draw(batch);
        }
     }

如果你这样做,你将没有任何帧率问题。不是这么低的演员数。简单地说,不要在绘制/渲染周期内加载纹理,它应该没有任何问题。并且多个Atlas不应该有任何问题。地图集不用于渲染。它用于将多个纹理放入一个纹理中,以便更轻松地处理它。你从不从图集中加载draw或render方法中的内容。如果你这样做,你会得到一个非常糟糕的表现。

对于排序,请使用insertionsort。这应该比szenario中的集合排序更快。也许每10帧调用一次。你甚至不应该注意到它们在那么短的时间内没有被正确分类。

private void sortList(Array<Actor> array) {
    // double starttime = System.nanoTime();
    for (int i = 1; i < array.size; i++) {
        Actor temp = array.get(i);
        int j = i - 1;

        while (j >= 0 && array.get(j).getY() < temp.getY()) {
            array.set(j + 1, array.get(j));
            j--;
        }
        array.set(j + 1, temp);
    }
    // System.out.println("Time taken: " + (System.nanoTime() - starttime));
}