CurZ
CurZ

Reputation: 23

How can i fix the libgdx camera bug with high x - positions?

I tried to do a game like Jetpack Joyride where the character keeps moving until you die.

The camera follows the character and everything is fine until the x-position of the camera(and the character) reaches about 5000.

I tested to let everything in the world start at a x-position of 5.000.000.

Everything started to look really weird, the sprites changed their sizes and positions o.O.

I have then created a simple screen that just renders 2 rectangles and when I use "low" x-positions everything looks fine but when I start using a "high" x-position for the camera the rectangles change their form.

Please try it and tell me how to fix this.

   public ArsenalScreen(AwesomeRun game)
    {

        this.game = game;

        renderer = new ShapeRenderer();
        batch = new SpriteBatch();
        camera = new OrthographicCamera();
        camera.setToOrtho(false, 20, 20);
        camera.viewportWidth = 30;
        camera.viewportHeight = 20;
            camera.position.x = 3;
//      camera.position.x = 300000000;
        camera.update(true);
    }
    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(0.5f,0.5f,0.5f,1);
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        renderer.setProjectionMatrix(camera.combined);
        renderer.begin(ShapeType.Rectangle);
        renderer.identity();
        renderer.rect(camera.position.x, camera.position.y, camera.viewportWidth/4, camera.viewportHeight/4);
        renderer.rect(camera.position.x-camera.viewportWidth/2+0.5f, camera.position.y-camera.viewportHeight/2, camera.viewportWidth, camera.viewportHeight);
        renderer.end();
    }

Upvotes: 2

Views: 732

Answers (1)

P.T.
P.T.

Reputation: 25177

You're probably running into floating point precision problems at large x values. Libgdx uses Java's float which is a 32-bit floating point value. If you're using OpenGL 2.0, the GLSL shader also constrains the floating point values a good bit, too (it can depend on the specific hardware even). Also, any of the transformations done on the values as they're converted into screen coordinates (via your camera matrix) might reduce the precision you have available.

For some background on floating point precision available in a 32-bit float, see the answer on What range of numbers can be represented in a 16-, 32- and 64-bit IEEE-754 systems?, which says:

If you want an accuracy of +/-0.5 (or 2^-1), the maximum size that the number can be is 2^23. Any larger than this and the distance between floating point numbers is greater than 0.5.

What Every Computer Scientist Should Know About Floating-Point Arithmetic is a good reference if you really want to understand what's going on in a float or double.

Back to your specific problem. I'm surprised you're seeing big problems at an x offset of 5 million (I'd expect you to see minor problems at an offset of around 8 million), but anyway you'll definitely run problems sooner or later.

You can't fix this by using double because many the of APIs you're using only accept float.

I think the way to fix this is to "reset" the floating-point X coordinate down every once in a while (e.g., when a section of a level is completed). So instead of just using a float x to track location, use an integer segment number plus a float x within that segment (say between 0 and 10000 or so). You'll have to deal with some boundary cases at the transition between segments, though.

Upvotes: 2

Related Questions