Debug some situations

Can’t see my FBO

Pixmap.IO / ScreenUtils

Can’t see my mesh

use GLTFExporter…

Gradle issues

Gradle can’t find dependencies looking at .m2 local repository.

Maven local repository sometimes mess with gradle dependencies cache, you need to remove your .m2 directory. and rebuild your project

GWT super dev mode, my changes are not applied, even if i clean rebuild all my project.

Super dev has cache outside of your project, not clear it, go to super dev web page and click clean button.

Scene2D

  • Any actor provides setUserObject to attach any of your logic object to it.
  • Any actor provides setName to attach an ID to it. It can be retrieved later using Group#findActor.

Framebuffer

Gist In order to preserve alpha with your fbo, you should draw non opaque graphics using a special blending function : batch.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_SRC_ALPHA, GL20.GL_ONE);

Error handling

Catch any errors (TODO gist)

for Lwjgl3 you can override Lwjgl3Application#cleanup method or wrap #loop method with a try catch if you need the error.

public class DesktopApplication extends LwjglApplication
{
    public DesktopApplication(ApplicationListener listener, LwjglApplicationConfiguration config) 
    {
        super(listener, config);
    }
    
    @Override
    public boolean executeRunnables() {
        try{
            return super.executeRunnables();
        }catch(Throwable e){
            // run code when app exiting with a crash
            return true;
        }
    }
}

public class GameBase extends Game 
{
    @Override
    public void render() 
    {
        try
        {
            super.render();
        } 
        catch (Throwable e) 
        {
            // run code when app exiting with a crash
        }
    }
}

public class MyGame extends GameBase 
{
    @Override
    public void dispose() 
    {
        // run code when app exiting without crash
    }
}

Snippets

Scene2D Animated Image



import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;

public class ImageAnimation extends Image
{
    private Animation<TextureRegion> animation;
    private float time;
    
    private TextureRegionDrawable drawable = new TextureRegionDrawable();
    
    public ImageAnimation() {
        super();
        setDrawable(drawable);
    }
    
    public void setAnimation(Animation<TextureRegion> animation) {
        this.animation = animation;
    }
    
    @Override
    public void act(float delta) 
    {
        time += delta;
        if(animation != null && animation.getAnimationDuration() > 0){
            TextureRegion frame = animation.getKeyFrame(time, true);
            drawable.setRegion(frame);
            setDrawable(drawable);
        }else{
            setDrawable(null);
        }
        super.act(delta);
    }
    
}

Scene2D Particles Actor

import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.ParticleEffect;
import com.badlogic.gdx.scenes.scene2d.Actor;

public class ParticleEffectActor extends Actor
{
    private ParticleEffect effect;
    
    public ParticleEffectActor(ParticleEffect effect) {
        super();
        this.effect = effect;
    }
    
    public ParticleEffect getEffect() {
        return effect;
    }

    public void start(){
        effect.start();
    }
    
    public void stop(){
        effect.allowCompletion();
    }
    
    @Override
    public void act(float delta) {
        effect.setPosition(getX(), getY());
        effect.update(delta);
        super.act(delta);
    }
    
    @Override
    public void draw(Batch batch, float parentAlpha) {
        effect.draw(batch);
    }
}

Shape Prototype


import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport;

public class MyGame extends Game{

    private Viewport viewport;
    private ShapeRenderer shapeRenderer;
    private float time;
    
    @Override
    public void create() {
        viewport = new FitViewport(1000, 500);
        shapeRenderer = new ShapeRenderer();
    }
    
    @Override
    public void resize(int width, int height) {
        viewport.update(width, height);
    }
    
    @Override
    public void render() {
        final float delta= Gdx.graphics.getDeltaTime();
        // update
        time += delta;
        // draw
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        shapeRenderer.setProjectionMatrix(viewport.getCamera().combined);
        shapeRenderer.setColor(time % 1f, 1, 1, 1);
        shapeRenderer.begin(ShapeType.Line);
        shapeRenderer.line(0, 0, 490, 240);
        shapeRenderer.end();
    }
}

3D Environement


import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.VertexAttributes;
import com.badlogic.gdx.graphics.g3d.Environment;
import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.ModelBatch;
import com.badlogic.gdx.graphics.g3d.ModelInstance;
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
import com.badlogic.gdx.graphics.g3d.utils.CameraInputController;
import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport;

public class MyGame extends Game
{
    private Array<ModelInstance> models = new Array<ModelInstance>();
    private ModelBatch modelBatch;
    private Viewport viewport;
    private CameraInputController cameraController;
    private Environment env;
    
    @Override
    public void create() {
        PerspectiveCamera camera = new PerspectiveCamera(60f, 1, 1);
        camera.near = .1f;
        camera.far = 100f;
        camera.position.set(10, 10, 10);
        camera.up.set(Vector3.Y);
        camera.lookAt(Vector3.Zero);
        camera.update();
        viewport = new FitViewport(1000, 500, camera);
        cameraController = new CameraInputController(camera);
        modelBatch = new ModelBatch();
        Material material = new Material();
        material.set(ColorAttribute.createDiffuse(Color.ORANGE));
        long attributes = VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal;
        float s = 10;
        models.add(new ModelInstance(new ModelBuilder().createBox(s, s, s, material, attributes)));
        env = new Environment();
        env.add(new DirectionalLight().set(Color.WHITE, new Vector3(-1, -3, -2).nor()));
        float l = 0.3f;
        env.set(new ColorAttribute(ColorAttribute.AmbientLight, new Color(l,l,l,1)));
        Gdx.input.setInputProcessor(cameraController);
    }
    
    @Override
    public void resize(int width, int height) {
        viewport.update(width, height);
    }
    
    @Override
    public void render() {
        cameraController.update();
        Gdx.gl.glClearColor(0,0,0,0);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
        modelBatch.begin(viewport.getCamera());
        modelBatch.render(models, env);
        modelBatch.end();
    }
    
}

Universal Keyboard Inputs

Universal arrow control for QWERTY and AZERTY and arrow keys :


import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;

// Layouts ARROWS, WSAD, ZSQD
int [][] keyLayouts = {
        {Input.Keys.UP, Input.Keys.DOWN, Input.Keys.LEFT, Input.Keys.RIGHT},
        {Input.Keys.W, Input.Keys.S, Input.Keys.A, Input.Keys.D},
        {Input.Keys.Z, Input.Keys.S, Input.Keys.Q, Input.Keys.D},
};

// Check states
boolean [] isKeyPressed = {false, false, false, false};
boolean [] isKeyJustPressed = {false, false, false, false};
for(int [] keyLayout : keyLayouts){
    for(int i=0 ; i<4 ; i++){
        int key = keyLayout[i];
        isKeyPressed[i] |= Gdx.input.isKeyPressed(key);
        isKeyJustPressed[i] |= Gdx.input.isKeyJustPressed(key);
    }
}

// Get the results (order WSAD : up, down, left, right)
boolean isUp = isKeyPressed[0];
boolean isDown = isKeyPressed[1];
boolean isLeft = isKeyPressed[2];
boolean isRight = isKeyPressed[3];

boolean isJustUp = isKeyJustPressed[0];
boolean isJustDown = isKeyJustPressed[1];
boolean isJustLeft = isKeyJustPressed[2];
boolean isJustRight = isKeyJustPressed[3];

or as class :

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;

public class UniControl {

    public static final int DOWN = 1, RIGHT = 3, UP = 0, LEFT = 2;
    
    // Layouts ARROWS, WSAD, ZSQD
    private static final int [][] keyLayouts = {
            {Input.Keys.UP, Input.Keys.DOWN, Input.Keys.LEFT, Input.Keys.RIGHT},
            {Input.Keys.W, Input.Keys.S, Input.Keys.A, Input.Keys.D},
            {Input.Keys.Z, Input.Keys.S, Input.Keys.Q, Input.Keys.D},
    };

    public static boolean isPressed(int direction){
        for(int [] keyLayout : keyLayouts){
            if(Gdx.input.isKeyPressed(keyLayout[direction])) return true;
        }
        return false;
    }
    
    public static boolean isJustPressed(int direction){
        for(int [] keyLayout : keyLayouts){
            if(Gdx.input.isKeyJustPressed(keyLayout[direction])) return true;
        }
        return false;
    }


}