game101

Add Camera, Action !

Required

Add a Camera Object to move game view according to a target position in the game play area. the target must be an Entity.

Adding a camera will help to implement a platformer

Here are:

Implementation proposal

The Camera object will drive the rendering view port to follow a GameObject target, with a certain delay fixed by the tween factor value.

The Camera object

The Camera class will inherit from Entity and introduce 3 new attributes:

The Camera mechanism implementation

And the main Camera processing will be a dedicated computing on the target position, according to the tween delay factor:

cam.pos = cam.pos
    + (target.pos-(viewport.size-target.size)) 
      x 0.5
      x tweenFactor
      x elapsedTime

So the update method in the Camera object will be :

class Camera {
    //...  
    public GameObject update(double elapsed) {
        x += target.x - ((viewport.getWidth() - target.width)) * 0.5 * tween * elapsed;
        y += target.y - ((viewport.getHeight() - target.height)) * 0.5 * tween * elapsed;
    }
    //...
}

The App with an active Camera

The class App must be enhanced with a new Camera attribute name activeCamera, and initialize it during the App#create() method processing:

class App implements Game {
    //...
    private Camera activeCamera;

    //...
    @Override
    public void create() {
        //...
        setActiveCamera((Camera) new Camera("cam01")
                .setTarget(player)
                .setTween(0.2)
                .setViewport(new Rectangle2D.Double(
                        0.0, 0.0,
                        ((double) screenWidth), ((double) screenHeight))));
    }

    //...
    public void setActiveCamera(Camera activeCamera) {
        this.activeCamera = activeCamera;
        this.renderer.setCurrentCamera(activeCamera);
    }
    //...

}

Add a current Camera to Renderer

The class Renderer now need to use a current Camera instance to move the rendering viewport to the currentCamera position, and apply this move on concerned GameObject.

class Renderer {
    //..
    private Camera currentCamera;

    public void draw(Map<String, Object> attributes) {
        Graphics2D g = (Graphics2D) buffer.getGraphics();
        //...
        // draw all the things you need.
        game.getEntityManager().getEntities()
                .stream()
                .sorted((o1, o2) -> o1.getLayer() > o2.getLayer() ? 1 : (o1.getPriority() > o1.getPriority() ? 1 : -1))
                .forEach(e -> {
                    // move to Camera viewport if object not stick to Camera
                    if (Optional.ofNullable(currentCamera).isPresent() && !e.isStickToCamera()) {
                        g.translate(-currentCamera.x, -currentCamera.y);
                    }
                    // draw object
                    drawEntity(g, e);
                    // move back from Camera viewport if object not stick to Camera
                    if (Optional.ofNullable(currentCamera).isPresent() && !e.isStickToCamera()) {
                        g.translate(-currentCamera.x, currentCamera.y);
                    }

                });
        // draw entity's display debug information
        if (game.getDebugMode() > 0) {
            game.getEntityManager().getEntities()
                    .stream()
                    .sorted((o1, o2) -> o1.getLayer() > o2.getLayer() ? 1 : (o1.getPriority() > o1.getPriority() ? 1 : -1))
                    .forEach(e -> {
                        // move to Camera viewport if object not stick to Camera
                        if (Optional.ofNullable(currentCamera).isPresent() && !e.isStickToCamera()) {
                            g.translate(-currentCamera.x, -currentCamera.y);
                        }
                        // draw Debug information for the Entity. 
                        drawDebugInformation(g, e);
                        // move back from Camera viewport if object not stick to Camera
                        if (Optional.ofNullable(currentCamera).isPresent() && !e.isStickToCamera()) {
                            g.translate(-currentCamera.x, currentCamera.y);
                        }
                    });
            // draw some debug information.
            drawDisplayDebugLine(g, attributes);
        }

        // release Graphics API
        g.dispose();
    }

    //...
    public void setCurrentCamera(Camera currentCamera) {
        this.currentCamera = currentCamera;
    }
}

Conclusion

With this new chapter, we implemented a Camera object that tracks a GameObject with a certain delay in the following moves.
According to our project, you will find this corresponding code with the tag create-camera in the Game101 GitHub repository

That’s all folk !

McG.