首页 > 代码库 > LibGDX详细介绍一

LibGDX详细介绍一

Libgdx 是一个Java framework 提供了跨平台 API 的游戏开发框架. 你开发的游戏直接就可以在Android和桌面运行,不需要修改。当然你可能会觉得桌面的是个鸡肋。不过它对实时调试作用很大。

 

下面我们通过Hello world的Demo进入底层看看LibGDX的整个生命周期:

public class HelloWorldAndroid extends AndroidApplication {
    @Override
    public void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initialize(new HelloWorld(), false);
    }

 

 Android 的Hello World只有这么几行,重点在上面红色部分,具体实现在下面

  public class HelloWorld implements ApplicationListener { 

    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)方法

    public void initialize (ApplicationListener listener, boolean useGL2IfAvailable) {
        AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
        config.useGL20 = useGL2IfAvailable;
        initialize(listener, config);

    } 

 继续进入红色的部分往下看

public void initialize (ApplicationListener listener, AndroidApplicationConfiguration 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()初始化,

private View createGLSurfaceView (Activity activity, boolean useGL2, ResolutionStrategy resolutionStrategy) {
        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),

public void onSurfaceChanged (javax.microedition.khronos.opengles.GL10 gl, int width, int height) {
        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(), 

public void onSurfaceCreated (javax.microedition.khronos.opengles.GL10 gl, EGLConfig config) {
        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,下面到重点中的重点了

public void onDrawFrame (javax.microedition.khronos.opengles.GL10 gl) {
        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++;
 

 onDrawFrame是被系统不断自动调用的,它里面调用了我们上面所说的render(),这就是Hello World呈现在我们面前的整个步骤。

 这张图显示了整个生命周期:

LibGDX详细介绍一