Bài 3: Đồ hoạ cơ bản

Đây là phần mọi người luôn tìm thấy niềm vui nhất, hành động thực tế của việc đưa đồ họa lên màn hình. 
Hãy bắt đầu với dự án đơn giản nhất mà chúng ta có thể.

Chúng tôi sẽ hiển thị sprite này ( được tạo trong hướng dẫn này ):


Trên màn hình. 
Một điều quan trọng cần lưu ý, đồ họa trên là 512×256. 
OpenGL nói chung và LibGDX nói riêng, yêu cầu các tệp hình ảnh của bạn phải có sức mạnh hai chiều. 
Điều này có nghĩa là chiều rộng và chiều cao của bạn là 2,4,8,16,32,64,128,256,512,1024,2048, vv Kích thước pixel. 
Đảm bảo thêm tệp này vào thư mục assets\data trong dự án Android trước khi tiếp tục.

Hãy nhảy ngay vào với mã:

package com.gamefromscratch.graphicsdemo;

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 GraphicsDemo implements ApplicationListener {
private SpriteBatch batch;
private Texture texture;
private Sprite sprite;

@Override
public void create() {
batch = new SpriteBatch();
texture = new Texture(Gdx.files.internal("data/jet.png"));
sprite = new Sprite(texture);
}

@Override
public void dispose() {
batch.dispose();
texture.dispose();
}

@Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

batch.begin();
sprite.draw(batch);
batch.end();
}

@Override
public void resize(int width, int height) {
}

@Override
public void pause() {
}

@Override
public void resume() {
}
}

Hình ảnh được vẽ tương đối với nguồn gốc. 
Trong trường hợp LibGDX (0,0) là góc dưới bên trái của màn hình.

Đối với mã, thực sự không có một tấn mới so với ví dụ Hello World trong hướng dẫn trước. 
Các khái niệm mới duy nhất là Texture và Sprite. 
Kết cấu đại diện cho kết cấu OpenGL cơ bản. 
Một điều quan trọng cần ghi nhớ với Texture (và các lớp tương tự khác) là chúng triển khai giao diện Dùng một lần. 
Điều này có nghĩa là khi bạn hoàn thành nó, bạn phải gọi phương thức dispose (), nếu không bạn sẽ bị rò rỉ bộ nhớ! 
Sprite chứa dữ liệu hình học và màu của kết cấu, điều này có nghĩa là dữ liệu vị trí (chẳng hạn như vị trí X và Y) được lưu trữ trong Sprite. 
Chúng tôi xây dựng kết cấu của chúng tôi bằng cách chuyển đường dẫn của nó vào, thu được giống như cách chúng tôi truy cập phông chữ trong hướng dẫn trước. 
Sau đó, chúng tôi xây dựng Sprite bằng cách chuyển qua kết cấu mới được tạo của chúng tôi. 
Có nhiều cách khác để tạo Sprites, mà chúng ta sẽ thấy ngay.

Hoạ tiết động với Pixmap



Nguồn Texture của bạn không phải đến từ một tập tin. 
Ở đây chúng ta sẽ sử dụng lớp Pixmap để tạo nguồn của kết cấu một cách linh hoạt.
package com.gamefromscratch.graphicsdemo; import com.badlogic.gdx.ApplicationListener; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL10; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.SpriteBatch; public class GraphicsDemo implements ApplicationListener {     private SpriteBatch batch;     private Pixmap pixmap;     private Texture texture;     private Sprite sprite;         @Override     public void create() {                batch = new SpriteBatch();                 // A Pixmap is basically a raw image in memory as repesented by pixels         // We create one 256 wide, 128 height using 8 bytes for Red, Green, Blue and Alpha channels         pixmap = new Pixmap(256,128, Pixmap.Format.RGBA8888);                 //Fill it red         pixmap.setColor(Color.RED);         pixmap.fill();                 //Draw two lines forming an X         pixmap.setColor(Color.BLACK);         pixmap.drawLine(0, 0, pixmap.getWidth()-1, pixmap.getHeight()-1);         pixmap.drawLine(0, pixmap.getHeight()-1, pixmap.getWidth()-1, 0);                 //Draw a circle about the middle         pixmap.setColor(Color.YELLOW);         pixmap.drawCircle(pixmap.getWidth()/2, pixmap.getHeight()/2, pixmap.getHeight()/2 - 1);                         texture = new Texture(pixmap);                 //It's the textures responsibility now... get rid of the pixmap         pixmap.dispose();                 sprite = new Sprite(texture);     }     @Override     public void dispose() {         batch.dispose();         texture.dispose();     }     @Override     public void render() {                Gdx.gl.glClearColor(0, 0, 0, 1);         Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);                 batch.begin();         sprite.setPosition(0, 0);                sprite.draw(batch);         sprite.setPosition(Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/2);         sprite.draw(batch);         batch.end();     }     @Override     public void resize(int width, int height) {     }     @Override     public void pause() {     }     @Override     public void resume() {     } }
Một lần nữa, mã tương tự như ví dụ trước của chúng tôi. 
Sự khác biệt lớn nhất là thay vì tải dữ liệu hình ảnh họa tiết từ tệp, chúng tôi tạo một cách linh hoạt bằng Pixmap. 
Đơn giản nhất, một pixmap có thể được coi là một lưới dữ liệu pixel trong bộ nhớ. 
Nó chứa một số chức năng đồ họa, nhiều chức năng chúng tôi đã giới thiệu ở trên. 
Mã bản vẽ được nhận xét khá tốt về những gì nó làm, vì vậy tôi sẽ không đi vào chi tiết ở đây. 
Mặc dù vậy, một chi tiết rất quan trọng, trong thế giới điều khiển GPU hiện đại, các loại hoạt động trên mỗi pixel này là THỰC SỰ THỰC SỰ CHẬM. 
Nói chung bạn muốn tránh chúng càng nhiều càng tốt. 

Điều duy nhất khác cần lưu ý trong ví dụ này là những thay đổi trong phương thức render (). 
Lưu ý làm thế nào cùng một sprite được rút ra hai lần cho lô sprite? 
Vâng, hành vi này là hoàn toàn OK, và có hiệu suất tối thiểu trong việc làm như vậy. 
Phương thức setP vị trí của Sprite được sử dụng để định vị một sprite, một lần nữa, (0,0) là góc dưới bên trái của màn hình theo mặc định. 
Mã mới duy nhất khác ở đây là các lệnh gọi phương thức Gdx.graphics.getWidth () và getHeight (). 
Chúng trả về kích thước của cửa sổ (hoặc Canvas trong trường hợp HTML5). 
Tất nhiên trong mã sản xuất, bạn có thể sẽ lưu trữ chúng cục bộ thay vì truy xuất chúng mỗi lần qua vòng lặp kết xuất.

TextureAtlas

Rất thường xuyên bạn muốn xử lý một tấm sprite, đó là một số sprite kết hợp với nhau thành một hình ảnh duy nhất. 
Chức năng này được tích hợp vào LibGdx. 
Điều đầu tiên bạn cần là một thư mục các hình ảnh sẽ được kết hợp thành một bảng sprite. 
Như thế này:

Mở một dòng lệnh hoặc cửa sổ đầu cuối và chạy lệnh sau:
java -cp gdx.jar; extend / gdx-tools / gdx-tools.jar com.badlogic.gdx.tools.imagepacker.TexturePacker2 c: \ tmp c: \ tmp spritesheet

tmp
Có vẻ khó sử dụng hơn nó. 
Về cơ bản, bạn đang chạy lớp TexturePacker2 bên trong jar công cụ gdx. 
Tham số đầu tiên là thư mục nguồn, tham số thứ hai là hướng đích và tham số cuối cùng là tên tệp sẽ sử dụng. 
Nó sẽ tự động thêm các phần mở rộng tập tin cần thiết. 
Quá trình này sẽ tạo hai tệp, tệp .atlas và .png. 
Tệp atlas là một tệp văn bản mô tả cách các họa tiết được đặt trong hình ảnh spritesheet, với tên tệp hình ảnh được sử dụng làm khóa (phần mở rộng trừ), như vậy:
spritesheet.atlas :

Định dạng 
spritesheet.png 
:

Bộ lọc 
RGBA8888 
: Gần nhất,

Lặp lại 
gần nhất 
: không có

0001

  xoay: false

  xy: 1, 651

  kích thước: 192, 128

  orig: 192, 128

  offset: 0, 0

  index: -1

0002

  xoay: false

Trong khi bản thân sprite trông như thế này:

Công cụ spritepacker tự động đệm hình ảnh thành một sức mạnh có kích thước 2. 
Tôi chỉ vạch ra bề mặt của những gì công cụ này có thể làm. 
Bạn có thể thiết lập nó để chạy như một phần của quá trình xây dựng của mình, chạy nếu từ mã hoặc trong Eclipse hoặc thậm chí chạy nó trong thời gian chạy chương trình. 
Có rất nhiều tùy chọn bạn có thể cấu hình. 
Bạn có thể đọc nhiều 
hơn về nó ngay tại đây .

Vì vậy, làm thế nào để bạn thực sự sử dụng một tập bản đồ kết cấu sau đó? 
Rất đơn giản, đầu tiên hãy sao chép tệp png và atlas được tạo vào tài sản của bạn. 
Đoạn mã sau cho biết cách sử dụng TextureAtlas:
Đây là phiên bản HTML5 của đoạn mã trên:

Như bạn có thể thấy, nó rất phù hợp. 
Phần lớn các mã ở trên thực sự là một phần của bản demo liên quan, trái ngược với việc là một phần của việc sử dụng TextureAtlas. 
Thay vào đó, chỉ nhập mã mới là:
lô =
SpriteBatch
mới ();
textureAtlas =
new TextureAtlas (
tập tin Gdx .iternal
(
“data / spritesheet.atlas” ));

Vùng AtlasRegion =
textureAtlas .findRegion (
“0001” );
sprite =
new Sprite (vùng);
Cũng giống như làm việc với một kết cấu, nhưng thay vào đó bạn tải TextureAtlas. 
Sau đó, thay vì gán kết cấu cho sprite, bạn sử dụng AtlasRegion, mô tả tọa độ của sprite riêng lẻ trong spritesheet. 
Bạn nhận được vùng theo tên bằng cách gọi phương thức findRegion () và truyền khóa. 
Hãy nhớ giá trị này được đặt theo tên tệp của hình ảnh nguồn. 
TextureAtlas cần phải được xử lý () ‘nếu không bạn sẽ bị rò rỉ bộ nhớ.
Như bạn có thể thấy qua cuộc gọi:
sprite .setRegion ( textureAtlas .findRegion ( currentAtlasKey ));
Bạn có thể thay đổi vùng trong bảng sprite mà sprite sẽ tham chiếu bằng cách gọi setRegion ().

Phần còn lại của mã chỉ đơn giản là định vị và chia tỷ lệ sprite lên 2,5 lần. 
Sau đó chúng tôi lên lịch tác vụ bằng Timer.schedule (). 
Nhiệm vụ này sẽ được gọi là 30 giây. 
Nó chỉ đơn giản là thay đổi khóa mà chúng ta sẽ sử dụng trong TextureAtlas. 
Trong trường hợp này, các tệp được đặt tên là 0001.png, 0002.png, v.v. 
Kết quả là cứ sau 30 giây, sprite chuyển sang khung hình động tiếp theo, lăn qua khi đến cuối.

EDIT: Tôi nên nêu rõ về bản ghi, đây KHÔNG phải là cách bạn sẽ sử dụng TextureAtlas để thực hiện hoạt hình, mã này chỉ đơn giản cho mục đích trình diễn. 
Có các lớp hoạt hình chuyên dụng và chúng tôi sẽ đề cập đến chúng sau này.

Mặc dù được cảnh báo, nếu bạn cố chạy nó dưới GWT, bạn sẽ thấy:

Điều này là do trình biên dịch GWT (điều này không liên quan gì đến LibGDX) không hỗ trợ String.format () vì một số lý do. 
Nếu bạn muốn chạy ví dụ này trong trình duyệt, bạn chỉ cần thay thế
currentAtlasKey = String.format ( “% 04d” , currentFrame );
Với:
Chuỗi cơ sở =
Chuỗi
mới ();

if (
currentFrame > = 10)

cơ sở =
“00” ;
cơ sở
khác =
“000” ;

currentAtlasKey = cơ sở +
currentFrame ;

Bây giờ mục tiêu HTML sẽ chạy tốt.

Trong phần tiếp theo, chúng ta sẽ xem xét việc kiểm soát đầu vào trong LibGDX.

Định cấu hình LibGDX để sử dụng GL 2

Nó đã được đưa đến sự chú ý của tôi bằng cách 
Mario Zechner rằng LibGDX không giới hạn sức mạnh của 2 kích thước kết cấu. 
Thay vào đó là một vật phẩm của OpenGL ES 1. Nếu bạn chạy bằng OpenGL ES2, nó sẽ hoạt động tốt. 
Điều đó nói rằng, OpenGL và phần cứng cơ bản vẫn hoạt động tốt hơn nếu bạn sử dụng sức mạnh của hai. 
Nếu bạn muốn sử dụng GL2, bạn đặt nó trong quá trình cấu hình, chúng tôi đã thảo luận ngắn gọn trong 
hướng dẫn Hello World . 
Chỉ cần đặt giá trị useGL20 thành true trong cấu hình bạn chuyển đến trình nghe ứng dụng của bạn. 
Ví dụ ở đây là Main từ dự án máy tính để bàn được cấu hình để sử dụng GL 2.

public class Main {
public static void main (String [] args) {

LwjglApplicationConfiguration cfg =
new LwjglApplicationConfiguration ();

cfg.
title =
“đồ họa” ;
cfg.
sử dụngGL20 =
đúng ;
cfg.
chiều rộng = 480;

cfg.
chiều cao = 320;

LwjglApplication
mới (
GraphicsDemo
mới (), cfg);

}

}

Tất nhiên hãy nhớ để cấu hình điều này cho tất cả các mục tiêu bạn đang hỗ trợ.

BIÊN TẬP:
18/12/2013 – Tôi đã chỉ ra rằng tôi không bao gồm các tập tin atlas, khiến cho hướng dẫn này khó thực hiện theo. 
Tôi đã bao gồm một kho lưu trữ của thư mục dữ liệu được sử dụng cho ví dụ này, 
bạn có thể tải xuống ở đây .

Bài 2: Tạo project HelloWorld

Hello World nói chung là một trong những chương trình đơn giản nhất bạn có thể tạo, bạn chỉ cần hiển thị các từ Hello World trên màn hình. Tất nhiên, luôn có những điều phức tạp trong cuộc sống. Đó là điều khiến nó thú vị!

Chúng ta sẽ nhảy vào với mã trong một giây, nhưng trước tiên chúng ta hãy xem nhanh mã được tạo bởi công cụ dự án, gdx-setup-ui. Dự án của bạn sẽ trông như thế này:

Rõ ràng tên tệp của bạn sẽ thay đổi tùy thuộc vào những gì bạn đã sử dụng trong công cụ thiết lập dự án. Điều quan trọng cần lưu ý là những điều cơ bản về cách đặt mã. Thư mục không có hậu tố (hello-world) là nơi mã được chia sẻ đi. Các thư mục của các loại máy tính và các loại dữ liệu nền tảng là nơi mà mã cụ thể của nền tảng đi và hy vọng bạn sẽ có nhu cầu tối thiểu để sử dụng các thư mục này. Tôi sẽ xem xét chúng gần hơn một chút trong vài phút, nhưng bây giờ, đó là tệp HelloWorld.java mà chúng tôi quan tâm. Đây là nơi một lớp rất quan trọng được gọi là ApplicationListener được triển khai. Đây là mã tôi đã sử dụng:

package com.gamefromscratch.helloworld;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class HelloWorld implements ApplicationListener {
private SpriteBatch batch;
private BitmapFont font;

@Override
public void create() {
batch = new SpriteBatch();
font = new BitmapFont();
font.setColor(Color.RED);
}

@Override
public void dispose() {
batch.dispose();
font.dispose();
}

@Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

batch.begin();
font.draw(batch, "Hello World", 200, 200);
batch.end();
}

@Override
public void resize(int width, int height) {
}

@Override
public void pause() {
}

@Override
public void resume() {
}
}

Điều đầu tiên bạn có thể nhận thấy là không có Main! Vâng, có một cái và chúng ta sẽ xem xét nó trong một giây. Vào cuối ngày, LibGDX là một công cụ điều khiển sự kiện. Bạn triển khai ApplicationListener và GDX gọi một số hàm mà bạn có thể đáp ứng. Phương thức render () sẽ được gọi là mỗi khung, vì vậy nếu bạn muốn, bạn có thể coi đó là vòng lặp sự kiện. Mặt khác, có các hàm được gọi để đáp ứng với các sự kiện khác nhau, bao gồm tạo, thay đổi kích thước, tạm dừng và tiếp tục. Tôi tưởng tượng bạn có thể đoán sự kiện mà mỗi người đang phản ứng!

Phần lớn mã của chúng tôi là trong tạo () và render (). Trong phần tạo (), chúng tôi phân bổ một SpriteBatch mới, BitmapFont và đặt phông chữ thành màu đỏ. SpriteBatch’ing là một hoạt động phổ biến trong các công cụ trò chơi 2D được xây dựng trên các thư viện 3D, nếu bạn đã sử dụng XNA, bạn đã quen với nó. Về cơ bản đằng sau hậu trường, LibGDX đang sử dụng OpenGL (hoặc WebGL tùy thuộc vào nền tảng) để thực hiện kết xuất. Trong OpenGL, có một chút chi phí hợp lý trong việc vẽ tốt, bất cứ điều gì. Một spritebatch kết hợp tất cả chúng vào một hoạt động duy nhất để giảm lượng chi phí. Tóm lại, nó làm cho kết xuất 2D nhanh hơn rất nhiều. BitmapFont chính xác là âm thanh của nó, bitmap 2D chứa tất cả các ký tự. Nếu bạn không chỉ định Phông chữ trong hàm tạo, bạn sẽ nhận được phông chữ mặc định Arial-15 đi kèm với LibGDX. Các tập tin phông chữ trông như thế này:

 

Trong phương thức render (), chúng ta xóa màn hình thành màu trắng bằng cách thực hiện hàm OpenGL gọi glClear () và glClearColor (). Các tham số cho glClearColor là các giá trị đỏ, lục, lam và alpha (trong suốt) để xóa màn hình. Chức năng glClear thực sự xóa màn hình. Như bạn có thể thấy, chức năng OpenGL cơ bản được bộc lộ trong Gdx.gl, mặc dù nhìn chung bạn sẽ không làm việc ở mức đó rất thường xuyên.

Tiếp theo, chúng tôi bắt đầu đợt sprite của mình bằng cách gọi start (), sau đó kết xuất văn bản của chúng tôi với lô bằng phương thức font.draw. Các tham số để vẽ () là lô cần vẽ, văn bản cần vẽ và tọa độ x và y để vẽ văn bản tại. Nếu bạn chạy mã này (nhấp chuột phải vào hello-world-desktop và chọn Run As-> Ứng dụng Java), bạn sẽ thấy:

Voila! Đó là Hello World.

Một điều quan trọng cần biết là dự án hello-world không phải là một ứng dụng mà bạn có thể chạy, đó là một thư viện được sử dụng bởi các dự án khác. Tôi sẽ cho bạn thấy ý tôi là gì, hãy xem mã trong màn hình hello-world-desktop chẳng hạn:

Nhìn này, nó chính! Hãy kiểm tra mã:

package com.gamefromscratch.helloworld;

import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;

public class Main {
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.title = "hello-world";
cfg.useGL20 = false;
cfg.width = 480;
cfg.height = 320;

new LwjglApplication(new HelloWorld(), cfg);
}
}

Đây là điểm vào thực tế cho ứng dụng của bạn hoặc ít nhất là dành cho mục tiêu trên máy tính để bàn. Đây là nơi cấu hình cụ thể của Desktop xảy ra. Sau đó, bạn bắt đầu trò chơi của mình bằng cách tạo một đối tượng LwjglApplication, chuyển qua một thể hiện của ApplicationListener cũng như các cài đặt cấu hình cụ thể của Lwjgl. Nếu Lwjgl là mới đối với bạn, thì đó là trình bao bọc trò chơi dựa trên Java so với OpenGL và là thứ LibGDX sử dụng để kết xuất máy tính để bàn. Ngoài việc cấu hình nó ở đây, bạn sẽ không có tương tác nào khác với nó, LibGDX sẽ lo tất cả những điều đó cho bạn.

Để thực sự hiểu cách thức hoạt động của ma thuật đa nền tảng trong LibGDX, chúng ta cũng hãy xem Main cho dự án chính. Trong trường hợp này, nó không thực sự được gọi là Main, mà thay vào đó là GwtLauncher.java.

Gwt là viết tắt của Google Web Toolkit và đó là công nghệ mà Google cung cấp để biên dịch Java thành JavaScript để sử dụng trong trình duyệt. Đó là nước sốt bí mật mà LibGDX sử dụng để làm cho trò chơi của bạn chạy bằng HTML. Đôi khi cũng thật khó chịu, bạn đã được cảnh báo! Điều đó nói rằng, nếu bạn không quan tâm đến HTML, bạn có thể loại bỏ hoàn toàn dự án này và tiết kiệm cho mình một số vấn đề đau đầu. 

Hãy xem GwtLauncher.java:

package com.gamefromscratch.helloworld.client;

import com.gamefromscratch.helloworld.HelloWorld;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.backends.gwt.GwtApplication;
import com.badlogic.gdx.backends.gwt.GwtApplicationConfiguration;

public class GwtLauncher extends GwtApplication {
@Override
public GwtApplicationConfiguration getConfig () {
GwtApplicationConfiguration cfg = new GwtApplicationConfiguration(480, 320);
return cfg;
}

@Override
public ApplicationListener getApplicationListener () {
return new HelloWorld();
}
}

Trông rất giống với dự án chính của desktop phải không? Khái niệm cơ bản hoàn toàn giống nhau, bạn tạo các bit cấu hình cụ thể của nền tảng và tạo một thể hiện của ApplicationListener. Tuy nhiên, lớp GwtApplication là gọi lại dựa trên, do đó, nó trông hơi khác một chút. Một lần nữa, bạn hiếm khi nên làm việc ở cấp độ này. Một điều quan trọng cần lưu ý là các giá trị được truyền cho GwtApplicationConfiguration, điều này thể hiện kích thước của khung vẽ HTML được tạo. Vì vậy, nếu bạn muốn ứng dụng HTML của bạn có nhiều hơn một hình vuông nhỏ ở giữa màn hình, đây là nơi bạn thay đổi nó.

Vì vậy, về cơ bản LibGDX hoạt động bằng cách bạn tạo một thư viện chung duy nhất thực hiện trò chơi của bạn theo cách đa nền tảng dưới dạng ApplicationListener. Để hỗ trợ nhiều nền tảng, bạn có một dự án cho mỗi nền tảng nơi bạn tạo một ứng dụng cụ thể cho nền tảng (một trường hợp của GwtApplication trong trường hợp các mục tiêu HTML, LwjglApplication cho các mục tiêu trên máy tính để bàn, AndroidApplication cho các mục tiêu Android, Ứng dụng cho các mục tiêu iOS không được hiển thị vì tôi hiện đang làm việc trên Windows), định cấu hình và chuyển vào ApplicationListener. Chính lớp ứng dụng này sẽ gọi lại cho ApplicationListener của bạn từng khung. Tin vui là, hầu hết thời gian, bạn sẽ không quan tâm đến bất kỳ điều gì trong số này nhưng thật tiện để hiểu những gì đang xảy ra đằng sau tấm màn.

Tuyệt vời, thêm một chút về GWT:

Hãy nhớ tôi đã nói rằng đó là một chút đau? Vâng, hãy xem điều gì xảy ra khi bạn chạy ứng dụng hello-world-html (nhấp chuột phải vào hello-world-html-> Run As->Web Application):

Vì vậy, về cơ bản, mã của chúng tôi đang cố gắng làm điều gì đó mà GWT không cho phép. Nếu chúng ta quay trở lại Eclipse trong bảng điều khiển Console, chúng ta có thể hiểu rõ hơn một chút về bản chất của Exception (ngoại lệ).

Đó là dòng 17 trong HelloWorld.Java đang gây ra ngoại lệ:

font = new BitmapFont();

Vì vậy, những gì chính xác đang xảy ra ở đây? Chà, hãy nhớ trước đó khi tôi nói với bạn rằng hàm tạo mặc định của BitmapFont sẽ sử dụng phông chữ arial-15 tích hợp. Chà, khi tôi nói tích hợp sẵn, tập tin đó thực sự nằm trong gdx.jar được bao gồm trong dự án của bạn. Một tệp jar thực sự chỉ là một zip, vì vậy nếu bạn giải nén tệp, bạn có thể thấy tất cả mã và tài sản tạo nên thư viện gdx. Quan tâm đặc biệt đối với chúng tôi là thư mục \gdx\com\badlogic\gdx\utils, đây là nơi tập tin phông chữ nằm trong số các tệp khác:

Về cơ bản, GwtApplication đang cố gắng truy cập tệp này và không được phép làm như vậy. Đạo đức của câu chuyện là gì? Nền tảng chéo là tuyệt vời, nhưng không phải lúc nào cũng miễn phí! Trừ khi bạn cần hỗ trợ HTML, tôi khuyên bạn không nên tạo dự án HTML, vì đây là phần dễ vỡ nhất của LibGDX và làm việc với GWT gây ra tất cả các loại đau lòng và biến chứng. Số dặm của bạn có thể thay đổi!

Điều đó nói rằng, có một cách khắc phục rất đơn giản cho vấn đề này và nó minh họa độc đáo cách bạn xử lý các tệp giữa các dự án của bạn, một quy trình có thể không đặc biệt trực quan. Giải pháp đơn giản là thêm các tệp arial-15.fnt và arial-15 vào dự án và thay đổi dòng:

font = new BitmapFont();

thành

font = new BitmapFont(Gdx.files.internal("data/arial-15.fnt"),false);

Phiên bản hàm tạo của BitmapFont này xử lý tệp của tệp phông chữ mà bạn muốn BitmapFont sử dụng. Gdx.files được sử dụng để thao tác tệp, nội bộ trả về một tệp xử lý tệp cho tệp được bao gồm trong dự án. Tham số sai đang chỉ định rằng đồ họa của phông chữ không bị lộn ngược.

Vì vậy, làm thế nào để bạn thực sự thêm các tập tin vào dự án? Bạn thêm chúng vào thư mục assets\data của dự án hello-world-android:

Bạn có thể thêm các tệp bằng cách kéo / thả từ Finder hoặc Explorer vào thư mục dữ liệu trong Package Explorer.

Bây giờ tệp phông chữ đã được thêm vào, bây giờ chúng ta có thể chạy mục tiêu HTML:

Vậy đó là Hello World trong LibGDX. Tiếp theo, chúng tôi xem xét một cái gì đó cao cấp hơn Hello World