2
votes

Im new in Libgdx. I tried to make pixel art game but i have a problem. When i render sprite with texture, pixels are deformated stretched (i added red arrows o second image). I made 400x400 window and scaled sprite to fit screen width in 1:1 ratio (sprite width = screen width and sprite heigh = screen width too)

Images:

This is a code of main game class:

public class Pixel implements ApplicationListener {

    SpriteBatch batch;
    Texture testTexture;
    Sprite testSprite;
    int w;
    int h;

    @Override
    public void create() {
        batch = new SpriteBatch();
        testTexture = new Texture(Gdx.files.internal("test.png"));
        testSprite = new Sprite(testTexture);
        testSprite.setSize(w, w);
    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(1, 1, 1, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        batch.begin();
        testSprite.draw(batch);
        batch.end();
    }

    @Override
    public void resize(int width, int height) {
        w = width;
        h = height;
        create();
    }

    @Override
    public void pause() {
        // TODO Auto-generated method stub
    }

    @Override
    public void resume() {
        // TODO Auto-generated method stub
    }

    @Override
    public void dispose() {
        // TODO Auto-generated method stub
    }
}

and this is desktop starter class:

public class DesktopLauncher {
    public static void main(String[] arg) {
        LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
        config.width = 400;
        config.height = 400;
        new LwjglApplication(new Pixel(), config);
    }
}
2

2 Answers

3
votes

Firstly, is not a good ideea to call create each time you resize your game because you create a spritebatch and a sprite. Make other function that will change the sprite size.

Your create method:

 @Override
public void create() {
    batch = new SpriteBatch();
    testTexture = new Texture(Gdx.files.internal("test.png"));
    testSprite = new Sprite(testTexture);
    testSprite.setSize(w, w);
}

As you can see, you set your sprite size to w and w, you probably want to set it to w and h. Make other function that will only do this, or don't even bother making other function just change your sprite size in your resize method.

public void resize(int width, int height) {
    w = width;
    h = height;
    testSprite.setSize(w, h);
}
2
votes

The stretch artifacts are due to not scaling the sprite by an integer multiple. 400 is not an integer multiple of the dimensions of your texture (64). With nearest filtering, you're getting rounding going in various directions. There's no way to avoid that. Your window is 6.25 times bigger than the texture, so some of those pixels will have to be scaled more than others in order to fill the entire window. If you want to work around this, consider using a FitViewport.

As Paul said, testSprite.setSize should be in the resize method. You should not call create from the resize method. Aside from wasting time re-creating everything, you're leaking stuff like the shader program that's inside your original sprite batch.