Android游戲引擎libgdx使用教程2:如何繪制圖形
本文主要為大家講解使用libgdx時圖形的繪制,文章詳細(xì)介紹了圖形繪制方法和步驟,大家可以細(xì)細(xì)研讀。
首先了解一下何為texture。按照英文解釋來理解:一個圖片從原始格式解碼并上傳到GPU就被稱為紋理。
為了繪制texture,常常使用幾何來描述,通過幾何對應(yīng)的頂點(diǎn)來描述紋理。比如要描述一個矩形,可以通過描述每個頂點(diǎn)來描述矩形。
要繪圖時,首先要綁定紋理,然后傳遞一個幾何描述給OpenGL進(jìn)行繪制。而繪圖的大小和位置由幾何描述和OpenGL的viewport的設(shè)置共同決定。
當(dāng)然大部分的游戲都會讓viewport的大小和屏幕一致。這就意味使用像素更容易讓紋理繪制在合適的大小和位置。
繪制一個矩形的幾何圖形是非常常見的,同樣讓同一個紋理在不同位置以不同大小位置也是非常常見的,比如漫天的彈幕。但是每次都傳遞每個形狀到GPU進(jìn)行繪制的效率是較低的。
所以許多相同紋理可以一起描述并一起送入GPU,這就是SpriteBatch類所要做的。
SpriteBatch被賦予了紋理和坐標(biāo)以便每個圖形的繪制。它(SpriteBatch)匯集了很多圖形而沒有直接提交給GPU。如果它被賦予的紋理不同于原有的,它將保持原有的圖形,并獲取新的圖形。
上一篇文章其實(shí)就使用了SpriteBatch,但是沒有繪制圖形,現(xiàn)在我們來試試?yán)L制。
先找張圖片來,分辨率必須是2的次方(如32*32,256*512)。
我截取了我的桌面的一部分,分辨率調(diào)成512*512。
拷貝到assets文件夾中,圖片文件最好都是放在這個里面哈。
然后修改代碼
private Texture texture;
實(shí)例化texture,texture=new Texture(Gdx.files.internal("image1.jpg"));然后來說一下為什么要將圖片放在assets文件夾中。 Gdx.files是libgdx的文件模塊,主要提供以下5大功能。
1、讀取文件
2、寫文件
3、復(fù)制文件
4、移動文件
5、列出文件和目錄
而獲取操作文件的FileHandle有4種方法。
1、Classpath
路徑相對于classpath,文件通常為只讀。
2、Internal
內(nèi)部文件路徑相對于程序根目錄或者android 的assets文件夾。
3、External
外部文件路徑是相對于SD卡根目錄。
4、Absolute
assets文件夾本身就是存儲資源的文件夾,而且相比resource文件夾,它其中的資源不會生成R中的ID,用來放圖片很是合適。
所以用Gdx.files.internal("image1.jpg")獲取圖片,然后調(diào)用batch.draw(texture,20,10);繪制圖形,20,10是坐標(biāo),笛卡爾座標(biāo),以左下角為原點(diǎn)。
完整代碼:
- package com.cnblogs.htynkn;
- import com.badlogic.gdx.ApplicationListener;
- import com.badlogic.gdx.Gdx;
- import com.badlogic.gdx.graphics.GL10;
- import com.badlogic.gdx.graphics.Texture;
- import com.badlogic.gdx.graphics.g2d.SpriteBatch;
- public class FirstGame implements ApplicationListener {
- //繪圖用的SpriteBatch
- private SpriteBatch batch;
- //紋理
- private Texture texture;
- @Override
- public void create() {
- batch = new SpriteBatch(); //實(shí)例化
- texture=new Texture(Gdx.files.internal("image1.jpg"));
- }
- @Override
- public void dispose() {
- // TODO Auto-generated method stub
- }
- @Override
- public void pause() {
- // TODO Auto-generated method stub
- }
- @Override
- public void render() {
- Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); //清屏
- batch.begin();
- batch.draw(texture,20,10);
- batch.end();
- }
- @Override
- public void resize(int width, int height) {
- // TODO Auto-generated method stub
- }
- @Override
- public void resume() {
- // TODO Auto-generated method stub
- }
- }
效果:
可以看到圖片不能完整顯示,而實(shí)際操作中我們也經(jīng)常使用圖片的一部分,或者將多個圖片資源集合在一個圖片文件中。
而要顯示圖片的一部分就可以使用TextureRegion類了。
最常用的方法是draw(TextureRegion region, float x, float y, float width, float height)
指定初始點(diǎn)和長寬。
修改代碼:
- package com.cnblogs.htynkn;
- import com.badlogic.gdx.ApplicationListener;
- import com.badlogic.gdx.Gdx;
- import com.badlogic.gdx.graphics.GL10;
- import com.badlogic.gdx.graphics.Texture;
- import com.badlogic.gdx.graphics.g2d.SpriteBatch;
- import com.badlogic.gdx.graphics.g2d.TextureRegion;
- public class FirstGame implements ApplicationListener {
- //繪圖用的SpriteBatch
- private SpriteBatch batch;
- //紋理
- private Texture texture;
- //區(qū)域
- private TextureRegion region;
- @Override
- public void create() {
- batch = new SpriteBatch(); //實(shí)例化
- texture=new Texture(Gdx.files.internal("image1.jpg"));
- region=new TextureRegion(texture, 30,80, 200,200);
- }
- @Override
- public void dispose() {
- // TODO Auto-generated method stub
- }
- @Override
- public void pause() {
- // TODO Auto-generated method stub
- }
- @Override
- public void render() {
- Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); //清屏
- batch.begin();
- batch.draw(region,0,0);
- batch.end();
- }
- @Override
- public void resize(int width, int height) {
- // TODO Auto-generated method stub
- }
- @Override
- public void resume() {
- // TODO Auto-generated method stub
- }
- }
效果:
也許你覺得TextureRegion不夠強(qiáng)大,沒有關(guān)系,還可以使用Sprite。
Sprite不光包含TextureRegion的功能,還可以指定位置和顏色。
關(guān)鍵代碼:
sprite=new Sprite(texture, 80, 80, 400, 300);
sprite.setPosition(10, 10); //位置
sprite.setRotation(15);
稍微想一下前幾個例子就可以發(fā)現(xiàn),其實(shí)Sprite的功能就是以上的集合。但是Sprite更方便,它用一個對象描述了一切。
完整代碼如下:
- package com.cnblogs.htynkn;
- import com.badlogic.gdx.ApplicationListener;
- import com.badlogic.gdx.Gdx;
- import com.badlogic.gdx.graphics.GL10;
- import com.badlogic.gdx.graphics.Texture;
- import com.badlogic.gdx.graphics.g2d.Sprite;
- import com.badlogic.gdx.graphics.g2d.SpriteBatch;
- public class FirstGame implements ApplicationListener {
- //繪圖用的SpriteBatch
- private SpriteBatch batch;
- //紋理
- private Texture texture;
- //精靈
- private Sprite sprite;
- @Override
- public void create() {
- batch = new SpriteBatch(); //實(shí)例化
- texture=new Texture(Gdx.files.internal("image1.jpg"));
- sprite=new Sprite(texture, 80, 80, 400, 300);
- sprite.setPosition(10, 10); //位置
- sprite.setRotation(15); //旋轉(zhuǎn)
- }
- @Override
- public void dispose() {
- // TODO Auto-generated method stub
- }
- @Override
- public void pause() {
- // TODO Auto-generated method stub
- }
- @Override
- public void render() {
- Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); //清屏
- batch.begin();
- sprite.draw(batch);
- batch.end();
- }
- @Override
- public void resize(int width, int height) {
- // TODO Auto-generated method stub
- }
- @Override
- public void resume() {
- // TODO Auto-generated method stub
- }
- }
效果:
同時可以通過sprite的setColor方法為圖形著色。
setColor(float r, float g, float b, float a)
其中顏色的表述都是介于0,1之間的數(shù)。
繪制的內(nèi)容基本就這么多,下一篇是關(guān)于關(guān)于2D場景的。
寫在最后
1、關(guān)于混合問題,默認(rèn)是開啟混合了的。這意味著圖形繪制完成時半透明的部分已經(jīng)被混合了。當(dāng)混合被關(guān)閉是任何已經(jīng)在場景上的東西都會被紋理代替,這適合繪制大背景。
batch.disableBlending();
backgroundSprite.draw(batch);
batch.enableBlending();
2、關(guān)于性能優(yōu)化
SpriteBatch 有個構(gòu)造函數(shù)可以指定最大緩沖數(shù)目。如果數(shù)值過低會造成額外的GPU調(diào)用;過高的話將占用過多的內(nèi)存。
在SpriteBatch有個字段為maxSpritesInBatch,可以先設(shè)置一個很高的緩沖數(shù)目,然后觀察maxSpritesInBatch的值以確定合適的緩沖值。
還有一個字段renderCalls,在end被調(diào)用時,它的值表示在begin和end之間幾何聲明被送入GPU的次數(shù)。
還有一個構(gòu)造函數(shù)可以指定緩沖大小和數(shù)量,合理的設(shè)置可以極大地提供性能。