Libgdx作者博客:http://www.badlogicgames.com/
Libgdx項目地址:http://code.google.com/p/libgdx/
Libgdx是一款支持2D與3D遊戲開發的遊戲類庫,兼容大多數微機平臺(標準JavaSE實現,能運行在Mac、Linux、Windows等系統)與Android平臺(Android1.5以上即可使用,Android2.1以上可滿功率發揮),
Libgdx由audio、files、graphics、math、physics、scenes、utils這些主要類庫所組成,它們分別對應了Libgdx中的音頻操作,文件讀取,2D/3D渲染,Libgdx繪圖相關運算,Box2D封裝,2D/3D遊戲組件(3D部分目前無組件),以及Libgdx內置工具類。
Libgdx主要構成如下所示(Libgdx作者wiki提供):
下面開始,我將就Libgdx的具體實現,開始講解如何正確使用Libgdx類庫。
不過在正式開始之前,我們首先還得講講Gdx類。
關於Libgdx中的Gdx類:
單從表面上看,Gdx類佔用空間不足2KB,甚至不具備一行可以被直接執行的函數,並沒什麼重要好說。
然而,真實的Gdx卻是Libgdx類庫運行的核心所在,沒有它你將寸步難行,不單運行Graphics、Input、Files、Audio、AndroidApplication等Libgdx關鍵部分所必需的實例會在Libgdx初始化時注入Gdx中對應的graphics、input、files、audio、app等靜態變量裏面,就連Libgdx對OpenGL接口(或OpenGLES,視Libgdx運行平臺而定,以下統稱OpenGL)的GL10、GL11、GL20、GLCommon等封裝類也會在Graphics實例化時分別注入到gl10、gl11、gl20、gl這四個同樣位於Gdx的靜態變量當中(在Graphics中也會繼續保留它們的引用,因此無論你執行Gdx.graphics.getGL10還是Gdx.gl10,其實都在調用同一個靜態變量)。事實上,如果你想不使用Gdx而正常運行Libgdx,那麼除了重構源碼,就再沒有任何辦法可想了。
PS:如果你不清楚自己究竟在什麼環境使用Libgdx,其實也不必強分gl10或gl11,大可以通過Gdx.gl方式調用Libgdx中對於OpenGL接口的默認封裝(執行某些非多版本共有接口時,依舊需要使用對應版本專屬gl)。
想要使用Libgdx,卻不明白Gdx是幹什麼用的,那麼一切就都是空談。
下面開始,我將具體講解Libgdx中的圖像處理與遊戲組件部分:
關於Libgdx的圖像處理部分:
Mesh:
本質上講,Libgdx中所有可見的3D物體首先都是一個Mesh(網格,或者說三維網格形式的高級圖元)。Mesh是如何生成的呢?衆所周知,數學上講的立體幾何由點、線、面三部分組成,無論多麼複雜的圖像也可以分解爲無數細小的這三部分,或者說可以由非常基礎的N個這三部分所組合而成;到了3D遊戲開發時,當我們要構建複雜的3D圖像,首先會以一系列有序的vertices(頂點)構成這些具體的點、線、三角要素,即構成繪圖基本圖元(Primitives),再將基本圖元組合成更完整的高級圖元也就是具體3D對象。因此,如果對Mesh概念進行簡單的理解,其實它就是一個象徵完整圖像的基本圖元集合體,Libgdx先讓我們把一個個細分的vertices組成基本圖元,再由Mesh類將基本圖元製成更加複雜的高級圖元展示出來。
具體可見Libgdx作者提供的returntomarchfeld示例,基本效果如下圖所示:
(勿看FPS,一切信真機)
PS:如果對此類認識不足,可以去玩玩模擬人生,下個修改器嘗試編輯角色或物品造型後就懂了……
Texture:
Libgdx所提供的遊戲紋理用類,其實質可理解爲保存在顯存中的Image,它以貼圖的方式通過OpenGL將圖片顯示到遊戲界面之上。Libgdx的紋理可以直接從指定文件路徑加載,也可以通過它提供的Pixmap類憑空創建(它的Texture(int width, int height, Format format)構造內部直接調用了Pixmap,不是必須在外部生成Pixmap後注入)。另外在加載Texture時,個人建議通過Libgdx提供的TextureDict.loadTexture函數調用,該方法內部提供了Texture緩存管理,能夠避免無意義的資源重複加載。此外,Texture通常會與TextureRegion類配套使用,利用TextureRegion包裝Texture後,再利用SpriteBatch進行繪製,可以很方便的修訂Texture爲我們需要的顯示範圍。還有,Libgdx中Sprite類爲TextureRegion子類,因此能夠將Sprite當作TextureRegion來使用,只是Sprite類比TextureRegion有所擴展。不過Libgdx的SpriteCache類並沒有繼承Sprite或TextureRegion,所以起不到TextureRegion的作用,只能構建一組靜態貼圖集合罷了,特此說明。
- // Libgdx的Texture與Sprite使用
- public class Main extends AndroidApplication {
- class TestSprite implements ApplicationListener {
- // 準備繪圖用SpriteBatch
- SpriteBatch spriteBatch;
- // 準備遊戲精靈
- Sprite sprite;
- // 準備圖片加載用Texture
- Texture texture;
- public void create() {
- // 構建SpriteBatch
- spriteBatch = new SpriteBatch();
- // 構建Texture,圖像寬與高大小都必須爲2的整數次冪,否則提示異常
- // PS:在Android環境使用Libgdx的internal加載時必須文件必須位於assets目錄下
- texture = new Texture(Gdx.files.internal("mySprite.png"));
- // 以指定Texture構建Sprite
- sprite = new Sprite(texture);
- // 定位到100, 180(Libgdx使用標準笛卡爾座標系,自左下0,0開始)
- sprite.setPosition(100, 180);
- }
- public void render() {
- // 清屏
- Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
- // 初始化繪圖調用
- spriteBatch.begin();
- // 繪製精靈到遊戲屏幕
- sprite.draw(spriteBatch);
- // 結束繪圖調用
- spriteBatch.end();
- }
- public void dispose() {
- // 釋放佔用的資源
- spriteBatch.dispose();
- texture.dispose();
- }
- public void resume() {
- }
- public void pause() {
- }
- public void resize(int width, int height) {
- }
- }
- public void onCreate(Bundle bundle) {
- super.onCreate(bundle);
- // 初始化遊戲屏幕,並設置是否支持GLES 2.0,如果您對向下兼容沒什麼需要選擇true即可(2.1以上),否則選擇false。
- initialize(new TestSprite(), true);
- }
- }
Pixmap:
Libgdx所提供的像素級圖像渲染用類,由於Libgdx目前以JNI方式自帶圖像解碼器,所以我們可以直接將Pixmap理解爲一個Android中Bitmap的替代者,兩者間實現細節雖有差別,但具體作用卻大同小異。Pixmap支持Alpha、LuminanceAlpha、RGB565、RGBA4444、RGB888、RGBA8888等五種圖像彩色模式,支持png、jpg、bmp等三種圖像文件的讀取和加載。一般來說,Pixmap必須和Texture混用才能真正顯示畫面。不過在事實上,Libgdx的Texture裏已經內置有Pixmap了。
- // Libgdx的Pixmap使用
- public class Main extends AndroidApplication {
- class TestPixmap implements ApplicationListener {
- // 準備繪圖用SpriteBatch
- SpriteBatch spriteBatch;
- // Pixmap是Libgdx提供的針對opengl像素操作的上級封裝,它可以憑空構建一個像素貼圖,
- // 但是它的現實必須通過Texture。
- Pixmap pixmap;
- // 準備Texture
- Texture texture;
- public void create() {
- // 構建SpriteBatch
- spriteBatch = new SpriteBatch();
- // 構建Pixmap(在Android環境使用internal加載模式時,文件必須放置於assets文件夾下)
- pixmap = new Pixmap(Gdx.files.internal("myPixmap.png"));
- // 繪製一個藍方塊到Ball圖像之上
- pixmap.setColor(Color.BLUE.r, Color.BLUE.g, Color.BLUE.b,
- Color.BLUE.a);
- pixmap.drawRectangle(15, 15, 40, 40);
- // 以指定Pixmap構建Texture
- texture = new Texture(pixmap);
- // 注入Texture後的pixmap已經沒用,可以註銷
- pixmap.dispose();
- }
- public void dispose() {
- spriteBatch.dispose();
- texture.dispose();
- }
- public void pause() {
- }
- public void render() {
- // 清屏
- Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
- // 初始化繪圖調用
- spriteBatch.begin();
- // 繪製精靈到遊戲屏幕
- spriteBatch.draw(texture, 100, 180);
- // 結束繪圖調用
- spriteBatch.end();
- }
- public void resize(int width, int height) {
- }
- public void resume() {
- }
- }
- public void onCreate(Bundle bundle) {
- super.onCreate(bundle);
- // 初始化遊戲屏幕,並設置是否支持GLES 2.0,如果您對向下兼容沒什麼需要選擇true即可(2.1以上),否則選擇false。
- initialize(new TestPixmap(), true);
- }
- }
BitmapFont:
Libgdx所提供的OpenGL文字用類,構造BitmapFont時需要一個描述文字構成的fnt文件,和一個提供文字圖片的png文件(PS:在Libgdx的com.badlogic.gdx.utils包下有提供內置字庫,目前僅支持英文、數字和常見符號),同SpriteBatch相配合時能夠完成一些基礎的文字繪圖。值得一提的是,我們也可以使用BitmapFontCache類將BitmapFont包裝成了一個靜態的Font實例,以避免大量貼圖時產生的不必要損耗。
- //libgdx的文字顯示
- public class Main extends AndroidApplication {
- class TestFont extends Game {
- // SpriteBatch是libgdx提供的opengl封裝,可以在其中執行一些常規的圖像渲染,
- // 並且libgdx所提供的大多數圖形功能也是圍繞它建立的。
- SpriteBatch spriteBatch;
- // BitmapFont是libgdx提供的文字顯示用類,內部將圖片轉化爲可供opengl調用的
- // 文字貼圖(默認不支持中文)。
- BitmapFont font;
- public void create() {
- //構建SpriteBatch用於圖像處理(內部調用opengl或opengles)
- spriteBatch = new SpriteBatch();
- //構建BitmapFont,必須有一個fnt文件描述文字構成,一個圖片文件提供文字用圖
- font = new BitmapFont(Gdx.files.internal("font.fnt"), Gdx.files
- .internal("font.png"), false);
- }
- public void render() {
- // 調用清屏
- Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
- // 初始要有begin起始
- spriteBatch.begin();
- // 顯示文字到屏幕指定位置
- // PS:Libgdx採用標準笛卡爾座標系,自左下0,0開始
- font.draw(spriteBatch, "FPS" + Gdx.graphics.getFramesPerSecond(),
- 5, 475);
- font.draw(spriteBatch, "Hello Libgdx", 255, 255);
- // 結束要有end結尾
- spriteBatch.end();
- }
- public void resize(int width, int height) {
- }
- public void pause() {
- }
- public void resume() {
- }
- public void dispose() {
- // 釋放佔用的資源
- spriteBatch.dispose();
- font.dispose();
- }
- }
- public void onCreate(Bundle bundle) {
- super.onCreate(bundle);
- // 初始化遊戲屏幕,並設置是否支持GLES 2.0,如果您對向下兼容沒什麼需要選擇true即可(2.1以上),否則選擇false。
- initialize(new TestFont(), true);
- }
- }
SpriteBatch:
Libgdx所提供的紋理渲染器,本質上是OpenGL的簡易封裝體,具體實現上與XNA中的SpriteBatch類非常近似,每次調用SpriteBatch類都必須以begin函數開頭,以end函數結尾。由於Libgdx中SpriteBatch提供的功能還非常有限,所以在完全不懂OpenGL的前提下使用其進行遊戲開發或許有一定難度。
ShaderProgram:
Libgdx所提供的着色器,在Android環境使用時需要GLES2.0或以上版本才能完整支持的高級渲染功能之一,內部封裝着GLES2.0專用的頂點着色與片斷着色Shader Model,它的本質作用是對3D對象表面進行渲染處理,此物性能基本取決於GPU(除了Google Nexus系列手機暫未見能完全跑出速度的機型)。
- //libgdx的ShaderProgram使用
- public class Main extends AndroidApplication {
- class TestShader implements ApplicationListener {
- ShaderProgram shader;
- Texture texture;
- Texture texture2;
- Mesh mesh;
- public void create() {
- // 以下命令供GPU使用(不支持GLES2.0就不用跑了)
- String vertexShader = "attribute vec4 a_position; /n"
- + "attribute vec2 a_texCoord; /n"
- + "varying vec2 v_texCoord; /n"
- + "void main() /n"
- + "{ /n"
- + " gl_Position = a_position; /n"
- + " v_texCoord = a_texCoord; /n"
- + "} /n";
- String fragmentShader = "#ifdef GL_ES/n"
- + "precision mediump float;/n"
- + "#endif/n"
- + "varying vec2 v_texCoord; /n"
- + "uniform sampler2D s_texture; /n"
- + "uniform sampler2D s_texture2; /n"
- + "void main() /n"
- + "{ /n"
- + " gl_FragColor = texture2D( s_texture, v_texCoord ) * texture2D( s_texture2, v_texCoord);/n"
- + "} /n";
- // 構建ShaderProgram
- shader = new ShaderProgram(vertexShader, fragmentShader);
- // 構建網格對象
- mesh = new Mesh(true, 4, 6, new VertexAttribute(Usage.Position, 2,
- "a_position"), new VertexAttribute(
- Usage.TextureCoordinates, 2, "a_texCoord"));
- float[] vertices = { -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, 0.0f,
- 1.0f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f, 0.0f };
- short[] indices = { 0, 1, 2, 0, 2, 3 };
- // 注入定點座標
- mesh.setVertices(vertices);
- mesh.setIndices(indices);
- // 以Pixmap生成兩個指定內容的Texture
- Pixmap pixmap = new Pixmap(256, 256, Format.RGBA8888);
- pixmap.setColor(1, 1, 1, 1);
- pixmap.fill();
- pixmap.setColor(0, 0, 0, 1);
- pixmap.drawLine(0, 0, 256, 256);
- pixmap.drawLine(256, 0, 0, 256);
- texture = new Texture(pixmap);
- pixmap.dispose();
- pixmap = new Pixmap(256, 256, Format.RGBA8888);
- pixmap.setColor(1, 1, 1, 1);
- pixmap.fill();
- pixmap.setColor(0, 0, 0, 1);
- pixmap.drawLine(128, 0, 128, 256);
- texture2 = new Texture(pixmap);
- pixmap.dispose();
- }
- public void dispose() {
- }
- public void pause() {
- }
- public void render() {
- // PS:由於使用了ShaderProgram,因此必須配合gl20模式(否則缺少關鍵opengles接口)
- Gdx.gl20.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics
- .getHeight());
- Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
- Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE0);
- texture.bind();
- Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE1);
- texture2.bind();
- // 開始使用ShaderProgram渲染
- shader.begin();
- shader.setUniformi("s_texture", 0);
- shader.setUniformi("s_texture2", 1);
- mesh.render(shader, GL20.GL_TRIANGLES);
- // 結束ShaderProgram渲染
- shader.end();
- }
- public void resize(int width, int height) {
- }
- public void resume() {
- }
- }
- public void onCreate(Bundle bundle) {
- super.onCreate(bundle);
- // 初始化遊戲屏幕,並設置是否支持GLES 2.0,如果您對向下兼容沒什麼需要選擇true即可(2.1以上),否則選擇false。
- initialize(new TestShader(), true);
- }
- }
FrameBuffer:
Libgdx所提供的幀緩衝器,在Android環境使用時需要GLES2.0或以上版本才能完整支持的高級渲染功能之一,也就是常說的FrameBuffer Object(FBO)功能封裝(用過JavaSE或JavaME開發遊戲的朋友,繪圖時大概都接觸過雙緩存這個概念,雖然有所差別,不過將FrameBuffer理解成起近似作用也未嘗不可)此物性能徹底取決於GPU(除了Google Nexus系列手機暫未見能完全跑出速度的機型)。
- //libgdx的FrameBuffer使用
- public class Main extends AndroidApplication {
- class TestFrameBuffer implements ApplicationListener {
- FrameBuffer frameBuffer;
- Mesh mesh;
- ShaderProgram meshShader;
- Texture texture;
- SpriteBatch spriteBatch;
- // PS:如果不支持GLES2.0就不用試了
- public void create() {
- mesh = new Mesh(true, 3, 0, new VertexAttribute(Usage.Position, 3,
- "a_Position"), new VertexAttribute(Usage.ColorPacked, 4,
- "a_Color"), new VertexAttribute(Usage.TextureCoordinates,
- 2, "a_texCoords"));
- float c1 = Color.toFloatBits(255, 0, 0, 255);
- float c2 = Color.toFloatBits(255, 0, 0, 255);
- float c3 = Color.toFloatBits(0, 0, 255, 255);
- mesh.setVertices(new float[] { -0.5f, -0.5f, 0, c1, 0, 0, 0.5f,
- -0.5f, 0, c2, 1, 0, 0, 0.5f, 0, c3, 0.5f, 1 });
- texture = new Texture(Gdx.files.internal("myTest.png"));
- spriteBatch = new SpriteBatch();
- frameBuffer = new FrameBuffer(Format.RGB565, 128, 128, true);
- String vertexShader = "attribute vec4 a_Position; /n"
- + "attribute vec4 a_Color;/n"
- + "attribute vec2 a_texCoords;/n" + "varying vec4 v_Color;"
- + "varying vec2 v_texCoords; /n" +
- "void main() /n"
- + "{ /n"
- + " v_Color = a_Color;"
- + " v_texCoords = a_texCoords;/n"
- + " gl_Position = a_Position; /n"
- + "} /n";
- String fragmentShader = "precision mediump float;/n"
- + "varying vec4 v_Color;/n"
- + "varying vec2 v_texCoords; /n"
- + "uniform sampler2D u_texture;/n"
- +
- "void main() /n"
- + "{ /n"
- + " gl_FragColor = v_Color * texture2D(u_texture, v_texCoords);/n"
- + "}";
- meshShader = new ShaderProgram(vertexShader, fragmentShader);
- if (meshShader.isCompiled() == false)
- throw new IllegalStateException(meshShader.getLog());
- }
- public void dispose() {
- }
- public void pause() {
- }
- public void render() {
- frameBuffer.begin();
- Gdx.graphics.getGL20().glViewport(0, 0, frameBuffer.getWidth(),
- frameBuffer.getHeight());
- Gdx.graphics.getGL20().glClearColor(0f, 1f, 0f, 1);
- Gdx.graphics.getGL20().glClear(GL20.GL_COLOR_BUFFER_BIT);
- Gdx.graphics.getGL20().glEnable(GL20.GL_TEXTURE_2D);
- texture.bind();
- meshShader.begin();
- meshShader.setUniformi("u_texture", 0);
- mesh.render(meshShader, GL20.GL_TRIANGLES);
- meshShader.end();
- frameBuffer.end();
- Gdx.graphics.getGL20().glViewport(0, 0, Gdx.graphics.getWidth(),
- Gdx.graphics.getHeight());
- Gdx.graphics.getGL20().glClearColor(0.2f, 0.2f, 0.2f, 1);
- Gdx.graphics.getGL20().glClear(GL20.GL_COLOR_BUFFER_BIT);
- spriteBatch.begin();
- spriteBatch.draw(frameBuffer.getColorBufferTexture(), 0, 0, 256,
- 256, 0, 0, frameBuffer.getColorBufferTexture().getWidth(),
- frameBuffer.getColorBufferTexture().getHeight(), false,
- true);
- spriteBatch.end();
- }
- public void resize(int width, int height) {
- }
- public void resume() {
- }
- }
- public void onCreate(Bundle bundle) {
- super.onCreate(bundle);
- // 初始化遊戲屏幕,並設置是否支持GLES 2.0,如果您對向下兼容沒什麼需要選擇true即可(2.1以上),否則選擇false。
- initialize(new TestFrameBuffer(), true);
- }
- }
關於Libgdx的遊戲組件部分:
在最近更新的Libgdx中,與遊戲顯示相關度最高的包總共有兩個,一個是graphics包,其中包含着Libgdx爲進行OpenGL渲染所提供的功能實現,而另一個,就是下面介紹的scenes包,這裏包含着Libgdx所提供的可以直接使用到遊戲中的遊戲組件,共分scenes2d以及scenes3d兩大部分(3D部分暫無內容)。其中2D部分的核心在於Actor類,Libgdx所有2D組件使用都圍繞着Actor展開。
對於Libgdx中游戲組件使用的簡單關係說明:
AndroidApplication (Activity的子類,只有啓動類繼承了AndroidApplication並執行才能啓動Libgdx類庫)
|
ApplicationListener (僅可在初始化時注入ApplicationListener,此後除非替換Activity否則無法切換ApplicationListener) - Game (ApplicationListener的libgdx抽象實現,其中Screen可切換)
|
Screen (基本函數與ApplicationListener近乎一致,唯一差別在於可以通過Game類用setScreen函數進行切換,如不使用Game類則可無視它的存在)
|
Stage (遊戲場景用類,用以管理添加其中的具體Actor,管理Actor的手段在於內置的Group類)
|
Group (本身爲Actor的具體實現,能夠處理注入其中的Actor,也能以遞歸方式管理注入其中的其它Group)
|
Actor (遊戲用演員或者說角色,與Action類組合使用時可以產生不同種類的“動畫行爲”,Action部分的具體實現基本與Cocos2D一致)
|
Image、Button、Label等 (細分Actor的具體實現,以重載方式響應事件,除Group外相互間不能組合疊加,事件能否傳遞取決於上級組件是否設置了相關監聽)
- //Libgdx中Actor的使用
- public class Main extends AndroidApplication {
- class TestActor implements ApplicationListener {
- Stage stage;
- public void create() {
- //構建等值於屏幕大小的場景
- stage = new Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
- // 構建Button
- Button btn = new Button("btn1", TextureDict.loadTexture("myButton.png")
- .get()) {
- // PS:因爲Libgdx的touchDown有內部實現,所以重載touchDown時必須調用super方法(肯定沒LGame方便啦^^~)
- protected boolean touchDown(float x, float y, int pointer) {
- super.touchDown(x, y, pointer);
- Gdx.app.log("click", "x:"+x+",y:"+y);
- return true;
- }
- };
- btn.x = 55;
- btn.y = 55;
- stage.addActor(btn);
- // 注入Stage監聽,讓Stage響應窗體事件,必須。(否則無論注入Stage什麼Actor都不會響應事件)
- Gdx.input.setInputProcessor(stage);
- }
- public void dispose() {
- stage.dispose();
- }
- public void pause() {
- }
- public void render() {
- // 繪製stage到屏幕
- stage.render();
- // PS:Libgdx無論遊戲業務或遊戲繪圖刷新都經過render
- // 傳遞屏幕刷新時間給stage,以執行內部業務操作,如果沒有這步,則所有注入Stage中Actor的act方法無法執行
- stage.act(Gdx.graphics.getDeltaTime());
- }
- public void resize(int width, int height) {
- }
- public void resume() {
- }
- }
- public void onCreate(Bundle bundle) {
- super.onCreate(bundle);
- // 初始化遊戲屏幕,並設置是否支持GLES 2.0,如果您對向下兼容沒什麼需要選擇true即可(2.1以上),否則選擇false。
- initialize(new TestActor(), true);
- }
- }
- //Libgdx中Action的使用
- public class Main extends AndroidApplication {
- class TestAction implements ApplicationListener {
- Stage stage;
- Texture texture;
- public void create() {
- // 構建場景
- stage = new Stage(Gdx.graphics.getWidth(),
- Gdx.graphics.getHeight(), false);
- // 構建紋理
- texture = new Texture(Gdx.files.internal("myImage.png"));
- texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
- // 構建圖像精靈
- Image img = new Image("actor", texture);
- img.width = img.height = 100;
- img.x = img.y = 100;
- // 依次讓圖像使用下列動作(PS:“$”符號爲調用對應Action類的靜態函數名,就那麼起的罷了(不過有緩存)……)
- img.action(Forever.$(Sequence.$(ScaleTo.$(1.1f, 1.1f, 0.3f),
- ScaleTo.$(1f, 1f, 0.3f))));
- stage.addActor(img);
- }
- public void render() {
- Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
- stage.act(Gdx.graphics.getDeltaTime());
- stage.render();
- }
- public void dispose() {
- texture.dispose();
- stage.dispose();
- }
- public void pause() {
- }
- public void resize(int width, int height) {
- }
- public void resume() {
- }
- }
- public void onCreate(Bundle bundle) {
- super.onCreate(bundle);
- // 初始化遊戲屏幕,並設置是否支持GLES 2.0,如果您對向下兼容沒什麼需要選擇true即可(2.1以上),否則選擇false。
- initialize(new TestAction(), true);
- }
- }
就目前來說,Libgdx可用的遊戲組件相對比較稀少,部分功能或者需要用戶自行實現。不過最近有一位網名moritz的手機遊戲“半全職”開發者(因爲他自己說手機遊戲並不是他唯一的收入來源)已經加入Libgdx項目,未來將重點改進Libgdx的scene2d部分,鑑於Libgdx作者爲此特意寫了一篇名爲“welcome moritz”的博文,moritz此人應該是有一定能力的傢伙,對於Lingdx未來表現大約還是值得期待的(話說,莫非moritz只對改造Libgdx的2D模塊有興趣?Libgdx作者博文中提到目前moritz開發的3D遊戲沒有使用Libgdx——那啥,先把3D組件部分做出來吧,現在是NULL啊……)。
在Libgdx的SVN,也有一些具體的遊戲示例,大家可以下載後親身體驗其效果。
PS:爲體現Libgdx最新特性,上述示例使用的Libgdx是2月1日從Libgdx SVN下載的版本(2011年1月28日更新版),請自行下載相關類庫,以保證所用版本維持在最新。
附錄,使用Libgdx時的幾點注意事項:
1、Libgdx使用笛卡爾座標系(初始座標爲左下0,0),而JavaSE、JavaME以及標準Android系統(還有LGame引擎)使用的是屏幕座標系(初始座標爲左上0,0),程序員在使用時必須分清差別,以免不知道如何定位(通常笛卡爾系Y軸由下向上延伸,屏幕系Y軸由上向下延伸)。
2、在Android環境使用Libgdx的Gdx.files.internal方法時(即FileHandle類以FileType.Internal模式工作),要讀取的文件必須置於Assets文件夾下才能讀取,在Linux、Mac、Windows環境下則可以置於除jar內部外的任何可讀取位置。
3、Libgdx以native方式自帶圖像解碼器,通過其提供的Pixmap可以對指定圖像進行像素級渲染操作,從而不依賴Android的Bitmap加載處理圖像,不過目前只支持png、jpg、bmp三種圖片格式。
4、Libgdx要求在遊戲中使用的圖片寬與高皆爲2的整數次冪,否則會產生一個Gdx異常並禁止加載行爲(texture width and height must be powers of two)。
5、Libgdx以ApplicationListener作爲遊戲的基礎界面容器,其作用近似LGame中的Screen,但並不完全一致,因爲Libgdx並沒有提供可以直接切換ApplicationListener的函數。目前最新版本的Libgdx中提供了Game類(ApplicationListener子類,本身爲抽象類)和一個供Game類調用的Screen類用以解決此問題。具體的Libgdx切換遊戲畫面方法是,先用繼承Game類的遊戲窗體進行initialize讓基礎畫面顯示,再讓具體的細分遊戲模塊繼承Screen類進行不同遊戲畫面的具體繪圖,而後Game類通過setScreen方法進行畫面切換。
6、Libgdx的圖像加載處理(以及部分渲染),音頻播放和自帶的Box2D封裝皆通過JNI方式實現,因此必須在libs文件夾下添加armeabi(或高版本Android系統支持的armeabi-v7a)文件夾以及相關so文件Android版Libgdx才能正常運行。
7、千萬不要以模擬器上的Libgdx運行速度判定其性能,否則很容易產生誤判(也不建議用性能不好的真機運行)
————————————————————