javaobjectcameralibgdxorthographic

LibGDX orthographic camera movement using object?


In Java in LibGDX I'm trying to make my camera follow an object created by shaperenderer. I don't want to use a sprite, but can only find tutorials for sprites. Using spritebatch and such.

I just want it to follow a rect I created in shaperenderer in a different class that I have getters and setters for- but no amount of camera updating and changing the position works. Is it possible to use Orthographic camera without a sprite?

public class Main extends ApplicationAdapter {
    Ground g;
    ShapeRenderer sr;
    Player square;
    OrthographicCamera camera;


    @Override
    public void create() {

        sr = new ShapeRenderer();
        g = new Ground(0, 20,Gdx.graphics.getWidth(), 5, new Color(Color.WHITE));
        square = new Player(20, 25, 50,50, new Color(Color.PURPLE), 3);
        camera = new OrthographicCamera();
        camera.update();

    }



    @Override
    public void render() {
        ScreenUtils.clear(0.15f, 0.15f, 0.2f, 1f);
        
        camera.lookAt(square.getX(), square.getY(), 0);
        handleInput();
        camera.update();



        float dt = Gdx.graphics.getDeltaTime();
        square.moveplayer(g, dt);



        sr.begin(ShapeRenderer.ShapeType.Filled);
        g.draw(sr);
        sr.end();

        sr.begin(ShapeRenderer.ShapeType.Filled);
        square.draw(sr);
        sr.end();
    }

    private void handleInput() {
        if (Gdx.input.isKeyPressed(Input.Keys.DPAD_LEFT)) {
            camera.translate(-3, 0, 0);
        }
        if (Gdx.input.isKeyPressed(Input.Keys.DPAD_RIGHT)) {
            camera.translate(3, 0, 0);
        }
    }

As you can see I've tried a bunch of stuff like just moving the screen based on user input, or looking at the object, but maybe I'm missing something silly, because nothing changes/happens.


Solution

  • I am assuming this is for 2D, you don't need to use the lookAt method to position the Camera as it is always just observing an area. You can just set the .position of the Camera to whatever coordinates you want it to observe.

    camera.position.set(5, 6, 0); // setting position to 5, 6  
    

    Also note that you haven't defined a viewport for the Camera, that is to say you have not yet defined how much of the world it sees. There are many ways of doing this, in the example below I show how to set it so that aspect ratio of the window is respected and a fix number of horizontal world units are visible.

    Further, you need to set the projection matrix of the ShapeRenderer to the combined matrix of the camera.

     shapeRenderer.setProjectionMatrix(camera.combined);
    

    A simple example with a stationary camera that then is made to follow a moving object might look like this:

    example gif

    The full source for the example above is:

    package com.bornander.gdxsandbox;
    
    import com.badlogic.gdx.ApplicationAdapter;
    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.Input;
    import com.badlogic.gdx.graphics.Color;
    import com.badlogic.gdx.graphics.OrthographicCamera;
    import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
    import com.badlogic.gdx.math.MathUtils;
    import com.badlogic.gdx.math.Vector2;
    import com.badlogic.gdx.utils.ScreenUtils;
    
    public class SandboxGame extends ApplicationAdapter {
    
        private OrthographicCamera camera;
        private ShapeRenderer shapeRenderer;
    
        private Vector2 moverPosition = new Vector2(0, 0);
        private Vector2 moverTargetPosition = new Vector2(0, 0);
        private Vector2 delta = new Vector2(MathUtils.random(-50, 50), MathUtils.random(-50, 50));
    
        private boolean cameraFollowMover = false;
    
        @Override
        public void create () {
            // Set up a camera and define how much it is supposed to "see",
            // in this case I create a camera that views 100 units wide, and what ever units tall
            // that the current aspect ratio of the window requires
            float aspectRatio = (float)Gdx.graphics.getWidth() / Gdx.graphics.getHeight();
            float w = 100.0f;
            camera = new OrthographicCamera(w, w / aspectRatio);
            camera.position.set(0, 0, 0); // Camera is looking at (0, 0)
    
            shapeRenderer = new ShapeRenderer();
        }
    
        @Override
        public void render () {
            if (Gdx.input.isKeyJustPressed(Input.Keys.SPACE))
                cameraFollowMover = !cameraFollowMover;
    
            // At random times, set a new target for the mover
            if (MathUtils.random() > 0.96f)
                moverTargetPosition.set(MathUtils.random(-50, 50), MathUtils.random(-50, 50));
    
            delta.set(moverTargetPosition).sub(moverPosition).nor().scl(Gdx.graphics.getDeltaTime() * 8.0f);
            moverPosition.add(delta);
    
            if (cameraFollowMover)
                camera.position.set(moverPosition.x, moverPosition.y, 0);
    
            camera.update();
            ScreenUtils.clear(Color.BLACK);
    
            shapeRenderer.setProjectionMatrix(camera.combined);
            shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
            // Draw a grid
            shapeRenderer.setColor(Color.LIGHT_GRAY);
            for(int x = 0; x < 100; x += 10) {
                shapeRenderer.setColor(x == 0 ? Color.GREEN : Color.LIGHT_GRAY);
                shapeRenderer.line(x, -100, x, 100);
                shapeRenderer.line(-x, -100, -x, 100);
            }
            for(int y = 0; y < 100; y += 10) {
                shapeRenderer.setColor(y == 0 ? Color.RED : Color.LIGHT_GRAY);
                shapeRenderer.line(-100, y, 100, y);
                shapeRenderer.line(-100, -y, 100, -y);
            }
    
    
            shapeRenderer.setColor(Color.MAGENTA);
            shapeRenderer.circle(moverPosition.x, moverPosition.y, 8, 24);
            shapeRenderer.end();
        }
    
    }