zoukankan      html  css  js  c++  java
  • 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)  
  • 相关阅读:
    用mathematica求六元一次方程组且方程个数比变量个数少一个
    abaqus学习笔记-abaqus与umat调用基本原理
    abaqus UMAT二次开发能用fortran90吗?
    vba遗传算法之非一致性突变
    学习刘伟择优excel视频
    EXCEL中R1C1样式引用
    Oracle常见问题
    Oracle数据库 —— DML完结
    Bootstrap前端框架
    Jsoup学习笔记
  • 原文地址:https://www.cnblogs.com/tonny-li/p/4146929.html
Copyright © 2011-2022 走看看