LibGdx----Texture, TextureRegion, SpriteBatch

Introduction

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

Texture

  略。。

SpriteBatch

  LibGdx使用SpriteBatch来完成纹理映射并在屏幕上显示被纹理映射的四边形的所有工作。它使得在屏幕上绘制图形极为简单,并且经过优化。它在屏幕坐标系中工作,使用屏幕像素的绝对坐标。左下角是原点(0,0),X轴向右,Y轴向上。由于SpriteBatch可以同时处理多个绘制请求、使用GPU进行渲染加速并序列化请求,所以程序员只要启动它就行。
  下面的代码把一张图片绘制到屏幕上:
[java] view plaincopy
 
  1. public class TextureFun implements ApplicationListener {  
  2.   
  3.         private Texture                 druidTexture;           // #1  
  4.         private SpriteBatch     batch;                          // #2  
  5.           
  6.         @Override  
  7.         public void create() {  
  8.                 druidTexture = new Texture(Gdx.files.internal("druid.png"));    // #3  
  9.                 batch = new SpriteBatch();                                      // #4  
  10.         }  
  11.   
  12.         @Override  
  13.         public void render() {  
  14.                 batch.begin();                                  // #5  
  15.                 batch.draw(druidTexture, 100, 100);             // #6  
  16.                 batch.end();                                    // #7  
  17.         }  
  18.   
  19.         // … rest of methods omitted … //  
  20. }  
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的纹理混合功能并设置混合方法。不过纹理混合在默认就是启用的。
[java] view plaincopy
 
  1. ...  
  2. batch.enableBlending();  
  3. batch.setBlendFunction(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);  
  4. ...  
 
  纹理有多种不同的创建方式,都在源码的注释中有详细介绍。
  当需要使用mipmaps(多级纹理)时,Texture会在初始化时就创建它们。MipMaps是指预先计算好的,同一张图片的不同尺寸的副本,在需要缩放图片以适应四边形时,选择最恰当的那个副本,可以提高渲染效率。
  draw()函数有多种重载,各种参数的意义在源码注释中都很详细。下面是其中之一:
[java] view plaincopy
 
  1. public void render() {  
  2.         batch.begin();  
  3.         batch.draw(druidTexture, 100, 100);  
  4.         batch.draw(druidTexture, 200, 100, 32, 32, 64, 64, 1f, 2.0f, 45f, 0, 0, 64, 64, false, false);  
  5.         batch.end();  
  6. }  

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

TextureRegion

  在一个游戏里,必然有很多需要绘制的元素,如果每个元素都要转换成一张纹理,对GPU的资源消耗是很大的,因为在绘制前,GPU都要把图片载入显存并绑定到OpenGL上,然后OpenGL再绘制需要的纹理并在不同纹理间切换,而绑定和切换的代价都是很昂贵的。
  TextureRgion能解决这个问题,它从一个纹理上切割出一个区域并让SpriteBatch作用于该区域。这样,一张纹理上可以包含多个需要绘制的元素,而只有与该元素对应的那部分才会绘制出来。包含多个绘制元素的纹理也称为sprite sheet。
  下图说明一张纹理如何被分割成多个元素。这种方式能避免在不同纹理间切换的昂贵代价。纹理的大小必须是2的n次幂,但纹理区域可以随意定义。
  下面的代码创建并绘制这张纹理的四个区域,还在(0,0)位置显示了一张缩小的纹理。
[python] view plaincopy
 
  1. public class TextureFun implements ApplicationListener {  
  2.   
  3.         private Texture                 texture;                        // #1  
  4.         private SpriteBatch             batch;  
  5.         private TextureRegion[]         regions = new TextureRegion[4]; // #2  
  6.          
  7.         @Override  
  8.         public void create() {  
  9.                 texture = new Texture(Gdx.files.internal("sprite_sheet.png"));  
  10.                 batch = new SpriteBatch();  
  11.                 regions[0] = new TextureRegion(texture, 0, 0, 64, 64);          // #3  
  12.                 regions[1] = new TextureRegion(texture, 0.5f, 0f, 1f, 0.5f);    // #4  
  13.                 regions[2] = new TextureRegion(texture, 0, 63, 64, 64);         // #5  
  14.                 regions[3] = new TextureRegion(texture, 0.5f, 0.5f, 1f, 1f);    // #6  
  15.         }  
  16.  
  17.         @Override  
  18.         public void render() {  
  19.                 batch.begin();  
  20.                 batch.draw(texture, 0, 0, 64, 64);                              // #7  
  21.                 for (int i = 0; i < regions.length; i++) {  
  22.                         batch.draw(regions[i], 75 * (i + 1), 100);              // #8  
  23.                 }  
  24.                 batch.end();  
  25.         }  
  26.           
  27.         // … rest of methods ommited... //  
  28.   
  29. }  

  如果要被分割的纹理区域大小相等且没有间隔,可以用一种更简单的方式来创建TextureRegion:
[java] view plaincopy
 
  1. TextureRegion[][] regions = TextureRegion.split(texture, 64, 64)  
原文地址:https://www.cnblogs.com/tonny-li/p/4146929.html