Search code examples
libgdxgame-development

Shape Drawer draws nothing in lib gdx


Simple, the shape drawer renders nothing and its just a black screen. Why is this so overly complicated to use? I can't figure this out like it just simply doesn't render anything and why is stack overflow asking for more details? What a dumb feature. Can this stupid thing reach 220 characters yet? Why is this a thing? I need to keep writing this to ask a simple question? Not almost done yet, fix this site to make it easy for people to actually use please.

package com.davidclue.tanksii;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.ScreenUtils;
import com.davidclue.tanksii.input.InputHandler;

import space.earlygrey.shapedrawer.ShapeDrawer;

public class TanksII extends ApplicationAdapter {
    
    long lastTime = System.nanoTime();
    double amountOfTicks = 60.0;
    double ns = 1000000000 / amountOfTicks;
    double delta = 0;
    long timer = System.currentTimeMillis();
    int updates = 0;
    int frames;
    
    private PolygonSpriteBatch batch;
    private ShapeDrawer drawer;
    private TextureRegion region;
    
    public static int WIDTH = 1600, HEIGHT = 900;
    public int fullWidth, fullHeight;
    public static int tileSize = 64;
    public String title = "Tanks II";
    
    public static Handler handler;
    private Level level;
    
    @Override
    public void create() {
        batch = new PolygonSpriteBatch();
        region = new TextureRegion(new Texture(WIDTH, HEIGHT, Format.RGBA8888));
        drawer = new ShapeDrawer(batch, region);
        
        handler = new Handler();
        new Camera(0, 0);
        new InputHandler(this);
        level = new Level(this, handler);
        handler.setLevel(level);
        
        level.load("levels/default/level1.png");
    }
    private void tick() {
        handler.tick();
        Camera.tick();
    }
    @Override
    public void render() {
        long now = System.nanoTime();
        delta += (now - lastTime) / ns;
        lastTime = now;
        while (delta >= 1) {
            tick();
            updates++;
            delta--;
        }
        if (System.currentTimeMillis() - timer > 1000) {
            timer += 1000;
            System.out.println("FPS: " + frames + " TICKS: " + updates);
            frames = 0;
            updates = 0;
        }
        
        // render
        
        ScreenUtils.clear(0, 0, 0, 1);
        batch.begin();
        
        level.render(drawer);
        handler.render(drawer);
        drawer.filledRectangle(10, 10, 100, 100, Color.CYAN);
        
        batch.end();
        frames++;
    }
    @Override
    public void dispose() {
        batch.dispose();
    }
}


Solution

  • The Texture constructor that takes only a width and height instead of an image creates a fully black texture. So if you draw black on black, you won't see anything. You should be using a pure white texture with ShapeDrawer so it can tint it to whatever color you're trying to use. Tinting with the default shaders works by multiplying a tint color by the texture color, so the texture needs to be white to be able to accurately take on the tint color.

    Also, the Texture you use for ShapeDrawer might as well be 1x1 size.

    And, you must always dispose of Textures in dispose(), or they will leak memory.

    Example:

    private Texture shapeDrawerTexture;
    
    @Override
    public void create() {
        batch = new PolygonSpriteBatch();
      
        Pixmap pixmap = new Pixmap(1, 1, Format.RGBA8888);
        pixmap.setColor(Color.WHITE);
        pixmap.fill();
        shapeDrawerTexture = new Texture(pixmap);
        pixmap.dispose();
        region = new TextureRegion(shapeDrawerTexture);
    
        drawer = new ShapeDrawer(batch, region);
    
        // ...
    }
    
    // ...
    
    @Override
    public void dispose() {
        batch.dispose();
        shapeDrawerTexture.dispose();
    }
    

    Side note: there's something very weird about your Camera and InputHandler because you call their constructors and immediately release the newly created instances to the GC.

    If you're going to release on Android, be extremely careful about using static fields in any of your classes, because they can stay around between sessions of the game, leaking memory and causing invalid state.