精灵批
在LibGDX中,精灵批(SpriteBatch
)扮演着非常重要的角色,因为该类的功能是将所有渲染命令发送给显卡设备,完成每一帧的绘图过程。游戏场景中显示的所有内容都是由精灵批发送给显卡的渲染命令实现的。精灵批可以渲染纹理、纹理域、精灵、字体(文本)以及应用着色器。精灵批的一般使用步骤如下:
- 创建精灵批对象
SpriteBatch batch = new SpriteBatch();
- 渲染
batch.setColor(1.0f, 1.0f, 1.0f, 1.0f); batch.begin(); batch.draw(texture); batch.end();
第一步创建对象非常简单,这里不再解释。第二步我们需要详细分析一下,因为后面的所有渲染过程都必须使用上面这种形式。首先我们调用了精灵批的setColor()
方法设置渲染时的着色,该方法包括两个重载的版本:
public void setColor (Color tint)
public void setColor (float r, float g, float b, float a)
第一种方法使用一个Color
对象设置颜色,Color
是LibGDX内建的一个颜色类,提供了大量重载的构造方法和常量字段,我们可以利用该类简单的引用一个预定义颜色,或者也可以创建更多的颜色。第二种方法使用四个浮点数设置颜色,每个浮点数表示一个颜色通道,表示颜色的浮点数必须位于0-1之间,由于RGBA8888颜色的每个通道的整数范围是0-255,所以,对于每个通道,我们需要使用一个位于0-1之间的浮点数来解析0-255。
接下来我们依次调用了begin()
、draw()
和end()
方法,切记这里的调用顺序不能改变。其中,begin()
方法用于启动每一帧的渲染,draw()
方法用于执行具体的渲染过程,end()
方法用于提交渲染命令,结束当前帧的渲染。begin()
和end()
方法必须成对出现,否则应用将会发生崩溃。draw()
方法必须位于begin()
和end()
方法之间,可以没有,也可以调用多次。
了解上述结构之后,我们最关心的应该是draw()
方法,因为该方法才是渲染过程的真正工作者。draw()
方法包含非常多的重载版本,下面列举了一部分:
渲染纹理对象:
public void draw (Texture texture, float x, float y) public void draw (Texture texture, float x, float y, float width, float height) public void draw (Texture texture, float[] spriteVertices, int offset, int count) public void draw (Texture texture, float x, float y, int srcX, int srcY, int srcWidth, int srcHeight) public void draw (Texture texture, float x, float y, float width, float height, float u, float v, float u2, float v2) public void draw (Texture texture, float x, float y, float width, float height, int srcX, int srcY, int srcWidth, int srcHeight, boolean flipX, boolean flipY) public void draw (Texture texture, float x, float y, float originX, float originY, float width, float height, float scaleX,float scaleY, float rotation, int srcX, int srcY, int srcWidth, int srcHeight, boolean flipX, boolean flipY)
关于上述方法,我们只需要解释每个参数的意义即可。其中,
x
、y
、width
、height
表示世界坐标系的矩形区域,单位为逻辑单位。originX
、originY
表示本地坐标系的原点位置,单位同样是逻辑单位。scaleX
、scaleY
、rotation
分别表示缩放大小和旋转角度。flipX
、flipY
表示是否在x方向和y方向镜像渲染。srcX
、srcY
、srcWidth
、srcHeight
表示纹理(图片)中需要渲染的矩形区域,单位为像素。u
、v
、u2
、v2
表示以浮点数(百分比)定义纹理的渲染区域。spriteVertices
是一个以x
,y
,color
,u
,v
为顺序组成的顶点集,顶点必须为4个,offset
和count
表示偏移量和长度。如果width
和height
省略,则默认等于渲染区域的像素尺寸。如果srcX
和srcY
省略,则默认等于0,如果srcWidth
和srcHeight
省略,则默认等于纹理的像素尺寸。可能你会觉得逻辑单位和像素单位好难记。其实这里并不需要记忆,只需要理解即可,在世界坐标系中定义的区域可以理解为目标区域,即纹理将要绘制的区域。所有与目标区域有关的变量都是以逻辑单位定义的,所有定义纹理渲染区域的参数都是以像素为单位的。等到下一节学习了相机和投影的概念之后,我们就会知道,逻辑单位只有在世界坐标系中才有意义。
- 渲染纹理域对象
渲染纹理域的方法与渲染纹理的方法所包含的参数意义相同。上述方法还包含一个public void draw (TextureRegion region, float x, float y) public void draw (TextureRegion region, float x, float y, float width, float height) public void draw (TextureRegion region, float x, float y, float originX, float originY, float width, float height, float scaleX, float scaleY, float rotation) public void draw (TextureRegion region, float x, float y, float originX, float originY, float width, float height,float scaleX, float scaleY, float rotation, boolean clockwise)
clockwise
参数,该参数表示是否顺时针旋转。
通过对比,我们可以发现:渲染纹理域时,我们并不需要指定任何像素尺寸或坐标,因为纹理域内部已经封装了具体的渲染区域,不需要再次指定。所以将纹理域作为渲染对象会更加简单,这也是纹理域使用频率比纹理高的原因,等到第二章学习了纹理集的概念之后,我们就会发现,使用纹理域会更加简单,因为纹理集技术可以免去创建纹理域时指定渲染区域的麻烦。
在上一节中,我们知道渲染精灵对象时,需要为draw()
方法传递一个SpriteBatch
对象。所以精灵对象的正确渲染代码应该如下:
batch.begin();
sprite.draw(batch);
batch.end();
因为精灵对象内部已经封装了目标区域的尺寸和位置信息,所以我们不需要再传递任何额外参数了。