Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
Tags
(1 edit)

Setting up the camera behavior

On the first gif I posted, at the end of the previous post, you can see that the camera doesn't move. It doesn't follow the hero, and at the end of the animation, the hero leaves the screen. We need to make the camera follow the hero. For exemple, we could center the camera on the hero. Thus the hero woul always appears exactly at the center of the screen. But that's not always the most eye pleasing choice. What I prefer is to determine a zone, at the center of the screen. If the hero is in this zone, the camera doesn't move, if the hero leaves this zone, the camera follows the hero. Plus, I don't want the camera to go outside of the map limit. Therefore, if the hero is in a corner, for example bottom left corner of the map, the camera won't go over the map limit in order to respect the condition "The hero must stay in the define zone". In this case, the hero will appear at the bottom left corner of the camera.

Here is an illustration :

For that, in the GameScreen.java, I'll replace the OrthographicCamera by a camera that I'll call MyCamera, that extends OrthographicCamera.

Here is the code for MyCamera.java :

public class MyCamera extends  OrthographicCamera{
    
    float posX, posY;
    
    public MyCamera(){
        super();
    }
 
    public void displacement(Hero hero, TiledMap tiledMap){
        //Positioning relative to the hero
        if(this.position.x < hero.getX() - Gdx.graphics.getWidth() * GameConstants.MPP/10)
            posX = hero.getX() - Gdx.graphics.getWidth() * GameConstants.MPP/10;
        else if(this.position.x > hero.getX() + Gdx.graphics.getWidth() * GameConstants.MPP/10)
            posX = hero.getX() + Gdx.graphics.getWidth() * GameConstants.MPP/10;
        if(this.position.y < hero.getY() - Gdx.graphics.getHeight() * GameConstants.MPP/10)
            posY = hero.getY() - Gdx.graphics.getHeight() * GameConstants.MPP/10;
        else if(this.position.y > hero.getY() + Gdx.graphics.getHeight() * GameConstants.MPP/10)
            posY = hero.getY() + Gdx.graphics.getHeight() * GameConstants.MPP/10;
        
        //Camera smooth motion
        this.position.interpolate(new Vector3(posX,posY,0), 0.45f, Interpolation.fade);
        
        //Positioning relative to the level map limits
        if(this.position.x + this.viewportWidth/2 > ((float)(tiledMap.getProperties().get("width", Integer.class)*GameConstants.PPT))*GameConstants.MPP)
            this.position.set(((float)(tiledMap.getProperties().get("width", Integer.class)*GameConstants.PPT))*GameConstants.MPP - this.viewportWidth/2, this.position.y, 0);
        else if(this.position.x - this.viewportWidth/2 < 0)
            this.position.set(this.viewportWidth/2, this.position.y, 0);
        if(this.position.y + this.viewportHeight/2 > ((float)(tiledMap.getProperties().get("height", Integer.class)*GameConstants.PPT))*GameConstants.MPP)
            this.position.set(this.position.x, ((float)(tiledMap.getProperties().get("height", Integer.class)*GameConstants.PPT))*GameConstants.MPP - this.viewportHeight/2, 0);
        else if(this.position.y - this.viewportHeight/2 < 0)
            this.position.set(this.position.x, this.viewportHeight/2, 0);    
    }
}

What is important in MyCamera, is the displacement() method :

  1. I check if the camera position (this.position.x and this.position.y) is inside a rectangle centered on the hero, of width 20% of the screen width (Gdx.graphics.getWidth() * GameConstants.MPP/10) and of height 20% of the screen height. If the camera is not in this rectangle, I update variables posX and posY in order to make the hero appear exactly at the border of this rectangle, not in the center, otherwise the camera would have a jerky motion.
  2. I interpolate the position of the camera, so transition is smooth. You can modify the speed of this interpolation by the second parameter (that is 0.45f in my case). The higher this parameter, the quicker the camera motion.
  3. Finally, I check if after moving the camera, the camera went over the map limit. If yes, I move back the camera in order to exactly fit the border of the map with the border of the screen.

Here is the result :

Notice that in my exemple, the map is 50 tiles wide, and the I setted up the camera in order to display 50 tiles on the width. Thus, the camera doesn't move on the side, in order to don't go over the map border.