下面我们通过Hello world的Demo进入底层看看LibGDX的整个生命周期:
@Override
public void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initialize(new HelloWorld(), false);
}
}
Android 的Hello World只有这么几行,重点在上面红色部分,具体实现在下面
SpriteBatch spriteBatch;
Texture texture;
BitmapFont font;
Vector2 textPosition = new Vector2(100, 100);
Vector2 textDirection = new Vector2(1, 1);
@Override
public void create () {
font = new BitmapFont();
font.setColor(Color.RED);
texture = new Texture(Gdx.files.internal("data/badlogic.jpg"));
spriteBatch = new SpriteBatch();
}
@Override
public void render () {
int centerX = Gdx.graphics.getWidth() / 2;
int centerY = Gdx.graphics.getHeight() / 2;
Gdx.graphics.getGL10().glClear(GL10.GL_COLOR_BUFFER_BIT);
// more fun but confusing :)
// textPosition.add(textDirection.tmp().mul(Gdx.graphics.getDeltaTime()).mul(60));
textPosition.x += textDirection.x * Gdx.graphics.getDeltaTime() * 60;
textPosition.y += textDirection.y * Gdx.graphics.getDeltaTime() * 60;
if (textPosition.x < 0) {
textDirection.x = -textDirection.x;
textPosition.x = 0;
}
if (textPosition.x > Gdx.graphics.getWidth()) {
textDirection.x = -textDirection.x;
textPosition.x = Gdx.graphics.getWidth();
}
if (textPosition.y < 0) {
textDirection.y = -textDirection.y;
textPosition.y = 0;
}
if (textPosition.y > Gdx.graphics.getHeight()) {
textDirection.y = -textDirection.y;
textPosition.y = Gdx.graphics.getHeight();
}
spriteBatch.begin();
spriteBatch.setColor(Color.WHITE);
spriteBatch.draw(texture, centerX - texture.getWidth() / 2, centerY - texture.getHeight() / 2, 0, 0, texture.getWidth(),
texture.getHeight());
font.draw(spriteBatch, "Hello World!", (int)textPosition.x, (int)textPosition.y);
spriteBatch.end();
}
@Override
public void resize (int width, int height) {
spriteBatch.getProjectionMatrix().setToOrtho2D(0, 0, width, height);
textPosition.set(0, 0);
}
@Override
public void pause () {
}
@Override
public void resume () {
}
@Override
public void dispose () {
}
}
若讲生命周期的话,这里我们只关心creat()和reader()是谁在调用。其他的先不用看。
HelloWorldAndroid继承了AndroidApplication,并调用了它的initialize(new HelloWorld(), false)方法
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
config.useGL20 = useGL2IfAvailable;
initialize(listener, config);
}
继续进入红色的部分往下看
graphics = new AndroidGraphics(this, config, config.resolutionStrategy == null ? new FillResolutionStrategy()
: config.resolutionStrategy);
input = new AndroidInput(this, graphics.view, config);
audio = new AndroidAudio(this);
files = new AndroidFiles(this.getAssets());
this.listener = listener;
this.handler = new Handler();
Gdx.app = this;
Gdx.input = this.getInput();
Gdx.audio = this.getAudio();
Gdx.files = this.getFiles();
Gdx.graphics = this.getGraphics();
try {
requestWindowFeature(Window.FEATURE_NO_TITLE);
} catch (Exception ex) {
log("AndroidApplication", "Content already displayed, cannot request FEATURE_NO_TITLE", ex);
}
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
setContentView(graphics.getView(), createLayoutParams());
createWakeLock(config);
}
继续往下看,graphics是AndroidGraphics的实例,它的getView()方法返回一个GLSurfaceView在构造器里由createGLSurfaceView()初始化,
EGLConfigChooser configChooser = getEglConfigChooser();
if (useGL2 && checkGL20()) {
GLSurfaceView20 view = new GLSurfaceView20(activity, resolutionStrategy);
if (configChooser != null)
view.setEGLConfigChooser(configChooser);
else
view.setEGLConfigChooser(config.r, config.g, config.b, config.a, config.depth, config.stencil);
view.setRenderer(this);
return view;
} else {
config.useGL20 = false;
configChooser = getEglConfigChooser();
if (Integer.parseInt(android.os.Build.VERSION.SDK) <= 4) {
GLSurfaceViewCupcake view = new GLSurfaceViewCupcake(activity, resolutionStrategy);
if (configChooser != null)
view.setEGLConfigChooser(configChooser);
else
view.setEGLConfigChooser(config.r, config.g, config.b, config.a, config.depth, config.stencil);
view.setRenderer(this);
return view;
} else {
android.opengl.GLSurfaceView view = new DefaultGLSurfaceView(activity, resolutionStrategy);
if (configChooser != null)
view.setEGLConfigChooser(configChooser);
else
view.setEGLConfigChooser(config.r, config.g, config.b, config.a, config.depth, config.stencil);
view.setRenderer(this);
return view;
}
}
}
注意这里的AndroidGraphics是实现了renderer接口的所以view.setRenderer(this),
this.width = width;
this.height = height;
updatePpi();
gl.glViewport(0, 0, this.width, this.height);
if (created == false) {
app.listener.create();
created = true;
synchronized (this) {
running = true;
}
}
app.listener.resize(width, height);
}
这里就是调用了我们上面所说的creat(),
setupGL(gl);
logConfig(config);
updatePpi();
Mesh.invalidateAllMeshes(app);
Texture.invalidateAllTextures(app);
ShaderProgram.invalidateAllShaderPrograms(app);
FrameBuffer.invalidateAllFrameBuffers(app);
Gdx.app.log("AndroidGraphics", Mesh.getManagedStatus());
Gdx.app.log("AndroidGraphics", Texture.getManagedStatus());
Gdx.app.log("AndroidGraphics", ShaderProgram.getManagedStatus());
Gdx.app.log("AndroidGraphics", FrameBuffer.getManagedStatus());
Display display = app.getWindowManager().getDefaultDisplay();
this.width = display.getWidth();
this.height = display.getHeight();
mean = new WindowedMean(5);
this.lastFrameTime = System.nanoTime();
gl.glViewport(0, 0, this.width, this.height);
}
这里设置了Viewport,下面到重点中的重点了
long time = System.nanoTime();
deltaTime = (time - lastFrameTime) / 1000000000.0f;
lastFrameTime = time;
mean.addValue(deltaTime);
boolean lrunning = false;
boolean lpause = false;
boolean ldestroy = false;
boolean lresume = false;
synchronized (synch) {
lrunning = running;
lpause = pause;
ldestroy = destroy;
lresume = resume;
if (resume) {
resume = false;
}
if (pause) {
pause = false;
synch.notifyAll();
}
if (destroy) {
destroy = false;
synch.notifyAll();
}
}
if (lresume) {
app.listener.resume();
Gdx.app.log("AndroidGraphics", "resumed");
}
if (lrunning) {
synchronized (app.runnables) {
for (int i = 0; i < app.runnables.size(); i++) {
app.runnables.get(i).run();
}
app.runnables.clear();
}
app.input.processEvents();
app.listener.render();
}
if (lpause) {
app.listener.pause();
((AndroidApplication)app).audio.pause();
Gdx.app.log("AndroidGraphics", "paused");
}
if (ldestroy) {
app.listener.dispose();
((AndroidApplication)app).audio.dispose();
((AndroidApplication)app).audio = null;
Gdx.app.log("AndroidGraphics", "destroyed");
}
if (time - frameStart > 1000000000) {
fps = frames;
frames = 0;
frameStart = time;
}
frames++;