LibGdx----Texture, TextureRegion, SpriteBatch

Introduction

  本章介绍2D图形相关的一些基本内容,包括如何使用Texture,TextureRegion和SpriteBatch。

Texture

  略。。

SpriteBatch

  LibGdx使用SpriteBatch来完成纹理映射并在屏幕上显示被纹理映射的四边形的所有工作。它使得在屏幕上绘制图形极为简单,并且经过优化。它在屏幕坐标系中工作,使用屏幕像素的绝对坐标。左下角是原点(0,0),X轴向右,Y轴向上。由于SpriteBatch可以同时处理多个绘制请求、使用GPU进行渲染加速并序列化请求,所以程序员只要启动它就行。
  下面的代码把一张图片绘制到屏幕上:
public class TextureFun implements ApplicationListener {

        private Texture                 druidTexture;           // #1
        private SpriteBatch     batch;                          // #2
        
        @Override
        public void create() {
                druidTexture = new Texture(Gdx.files.internal("druid.png"));    // #3
                batch = new SpriteBatch();                                      // #4
        }

        @Override
        public void render() {
                batch.begin();                                  // #5
                batch.draw(druidTexture, 100, 100);             // #6
                batch.end();                                    // #7
        }

        // … rest of methods omitted … //
}
1. 声明一张纹理
2. 声明用来把纹理显示到屏幕的SpriteBatch
3. 创建纹理。图片druid.png需要位于asset文件夹里,图片格式可以是jpg,png或bmp,图片宽度和高度必须是2的n次幂,如1,2,4,8,16,32,64,128...另外,宽度和高度不需要相等
4. 创建SpriteBatch
5. 调用begin()函数后,SpriteBatch开始接收请求
6. 一条绘制请求,它请求SpriteBatch把纹理绘制到(100,100)的位置。注意这个坐标是屏幕绝对坐标。
7. 告诉SpriteBatch暂时没有其他请求了,它可以开始处理刚才收到的请求了。
显示结果和坐标系统如下所示:
  你可以通过在begin()和end()函数之间添加多条draw()指令来绘制多个图形,绘制顺序和draw()的调用顺序相同,所以如果有重叠的部分,后来的图片会在覆盖在先前的图片上面。
  除了简单的draw(),SpriteBatch还有一些其他功能,如设置混合颜色、设置转换矩阵。不过转换矩阵必须在begin()之前设置。
  下面的代码启用SpriteBatch的纹理混合功能并设置混合方法。不过纹理混合在默认就是启用的。
...
batch.enableBlending();
batch.setBlendFunction(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
...

  纹理有多种不同的创建方式,都在源码的注释中有详细介绍。
  当需要使用mipmaps(多级纹理)时,Texture会在初始化时就创建它们。MipMaps是指预先计算好的,同一张图片的不同尺寸的副本,在需要缩放图片以适应四边形时,选择最恰当的那个副本,可以提高渲染效率。
  draw()函数有多种重载,各种参数的意义在源码注释中都很详细。下面是其中之一:
public void render() {
        batch.begin();
        batch.draw(druidTexture, 100, 100);
        batch.draw(druidTexture, 200, 100, 32, 32, 64, 64, 1f, 2.0f, 45f, 0, 0, 64, 64, false, false);
        batch.end();
}

  在注释中有提一些参数是Texel空间的,texel是指导图片上的一个像素,要和屏幕上的一个像素区别开。

TextureRegion

  在一个游戏里,必然有很多需要绘制的元素,如果每个元素都要转换成一张纹理,对GPU的资源消耗是很大的,因为在绘制前,GPU都要把图片载入显存并绑定到OpenGL上,然后OpenGL再绘制需要的纹理并在不同纹理间切换,而绑定和切换的代价都是很昂贵的。
  TextureRgion能解决这个问题,它从一个纹理上切割出一个区域并让SpriteBatch作用于该区域。这样,一张纹理上可以包含多个需要绘制的元素,而只有与该元素对应的那部分才会绘制出来。包含多个绘制元素的纹理也称为sprite sheet。
  下图说明一张纹理如何被分割成多个元素。这种方式能避免在不同纹理间切换的昂贵代价。纹理的大小必须是2的n次幂,但纹理区域可以随意定义。

  下面的代码创建并绘制这张纹理的四个区域,还在(0,0)位置显示了一张缩小的纹理。
public class TextureFun implements ApplicationListener {

        private Texture                 texture;                        // #1
        private SpriteBatch             batch;
        private TextureRegion[]         regions = new TextureRegion[4]; // #2
        
        @Override
        public void create() {
                texture = new Texture(Gdx.files.internal("sprite_sheet.png"));
                batch = new SpriteBatch();
                regions[0] = new TextureRegion(texture, 0, 0, 64, 64);          // #3
                regions[1] = new TextureRegion(texture, 0.5f, 0f, 1f, 0.5f);    // #4
                regions[2] = new TextureRegion(texture, 0, 63, 64, 64);         // #5
                regions[3] = new TextureRegion(texture, 0.5f, 0.5f, 1f, 1f);    // #6
        }

        @Override
        public void render() {
                batch.begin();
                batch.draw(texture, 0, 0, 64, 64);                              // #7
                for (int i = 0; i < regions.length; i++) {
                        batch.draw(regions[i], 75 * (i + 1), 100);              // #8
                }
                batch.end();
        }
        
        // … rest of methods ommited... //

}


  如果要被分割的纹理区域大小相等且没有间隔,可以用一种更简单的方式来创建TextureRegion:
TextureRegion[][] regions = TextureRegion.split(texture, 64, 64)


你可能感兴趣的:(优化,工作,REST,Class,图形,methods)