Libgdx舞台添加演员低FPS



我正在使用ApplicationAdapter。当我在create((方法中有下面的代码时,我的fps总是在14左右。

for (i in 0..1000) {
stage.addActor(Food(
Food.TEXTURE_PURPLE!!,
100f,
(random.nextInt(MAP_SIZE)).toFloat(),
(random.nextInt(MAP_SIZE)).toFloat()))
stage.addActor(Food(
Food.TEXTURE_GREEN!!,
100f,
(random.nextInt(MAP_SIZE)).toFloat(),
(random.nextInt(MAP_SIZE)).toFloat()))
}

但是当我在create((方法中有这个时,我的fps总是60。为什么?

for (i in 0..1000) {
stage.addActor(Food(
Food.TEXTURE_PURPLE!!,
100f,
(random.nextInt(MAP_SIZE)).toFloat(),
(random.nextInt(MAP_SIZE)).toFloat()))
}
for (i in 0..1000) {
stage.addActor(Food(
Food.TEXTURE_GREEN!!,
100f,
(random.nextInt(MAP_SIZE)).toFloat(),
(random.nextInt(MAP_SIZE)).toFloat()))
}

问题在于纹理交换。SpriteBatch的工作方式是使用其draw函数之一提交项目以绘制到其队列中。一旦添加了无法用队列中的其他内容绘制的内容,它就会通过调用OpenGL绘制来刷新队列,然后启动一个新队列。

两个不同的纹理不能在同一个OpenGL绘制调用中绘制,因此当您的食物项目没有按纹理排序时,它们中的每一个都会触发另一次刷新。冲洗是一项昂贵的手术,你希望避免超过几十次。

解决方案是使用TextureAtlas,它将多个图像组合成一个纹理,通过TextureRegion访问。您可以将TextureRegions提交给SpriteBatch.draw(...)。只要TextureRegions共享相同的"纹理",就可以在单个批处理队列中绘制具有不同"纹理区域"的许多项目。

顺便说一句。。。我强烈建议不要使用对纹理的静态引用。这里最常见的libgdx问题是"为什么我的纹理是黑色的",这总是因为他们使用静态纹理引用,而不了解如何正确处理纹理和重新加载。在安卓系统上,静态引用的寿命比你的游戏长,这可能会导致大的内存泄漏,如果你懒惰地加载任何东西,也会导致奇怪的错误,这在使用静态引用时很容易意外发生。

一个更干净的设计是有一个Assets类(如果游戏中每个阶段有很多独特的东西,可能每个阶段都有一个(,它有一个用于加载所有东西的AssetManager。单个资产实例可以传递给所有游戏对象构造函数。例如:

class Assets: Disposable {
private val assetManager = AssetManager()
lateinit val foodGreenTexture: Texture
lateinit val foodRedTexture: Texture
lateinit val foodBlueTexture: Texture
//...
init {
assetManager.load("green.png", Texture::class.java)
assetManager.load("red.png", Texture::class.java)
//...
assetManager.finishLoading()
foodGreenTexture = assetManager.get("green.png")
//...
}
override fun dispose (){
assetManager.dispose()
}
}

不要忘记在初始化Assets类的同一对象(游戏或屏幕(中调用dispose。

我还建议考虑使用CoveTools库,该库有一个名为AssignmentAssetManager的助手,它可以删除上面的一堆样板。同一个班会是这样的。注意init块是如何超短的,无论您加载多少不同的资产:

class Assets: Disposable {
private val assetManager = AssignmentAssetManager()
@Asset("green.png") val foodGreenTexture: Texture = null
@Asset("red.png") val foodRedTexture: Texture = null
@Asset("blue.png") val foodBlueTexture: Texture = null
//...
init {
assetManager.loadAssetFields(this)
assetManager.finishLoading()
}
override fun dispose (){
assetManager.dispose()
}
}

还有第二个旁注。。。我强烈建议不要使用Sprite类,尤其是在使用Actors时。请改用TextureRegion类。Sprite是一个高度专业化的类,它扩展了TextureRegion,但包括额外的数据,如位置、大小、旋转等。如果您使用Actor,这些额外的数据是多余的,因此来回复制数据很容易出错,并且浪费CPU和内存。

最新更新