Complete Platformer Game Camera Setup

Sandro Maglione

Sandro Maglione

Games

Camera movement is key when implementing a platformer game. No matter how awesome your gameplay and mechanics, if the camera becomes an obstacle no one will play the game.

A platformer is a fast and dynamic genre where the player is constantly moving and sprinting around the level to reach the next area. Camera movements can be a problem when the player is moving fast in all directions.

In this post we go over some common strategies used to manage camera movements in platformer games, how they work, and their limitations.

I will then present a solution that aims to solve all the problems and provided an ideal camera movement for all platformer games πŸ‘‡

Simplest solution: Follow the player

The easiest strategy for camera movement is following directly the position of the player.

The camera will always have the same position as the player as it moves in the game

You quickly realize that this strategy does not work for most platformer games.

The player movements are expected to be fast and responsive. As the player jumps, double jumps, dashes, falls, the camera is doing the same movements. This makes the gameplay confusing: the user gets disoriented by all these fast movements to the point of making the game unplayable.

While this strategy may work for a side-scroller with slow speed, for most platformer games this is not enough.

Fixed camera

The opposite strategy consists of no movement at all. The camera says fixed on the center of a room as the player jumps and sprints around without limitations.

When the player reaches the end of the current room, a quick transition moves the camera to the center of the next room.

This strategy is used in the game Celeste: when you enter a section the camera stays fixed at the center while you dash around. When you reach the end of the section the camera moves to the center of the next areaThis strategy is used in the game Celeste: when you enter a section the camera stays fixed at the center while you dash around. When you reach the end of the section the camera moves to the center of the next area

While this strategy works great, it comes with a cost: Every room must be small enough to fit inside the camera viewport

Fitting the camera to the viewport can be achieved in 2 ways.

The first solution is to make each section as big as needed and adjust the zoom of the camera to fit the entire area.

However, changing the zoom level for every section causes the player to have a different scale in every room, which is usually an undesired effect. Furthermore, while this may work for small rooms, when the size starts to increase, zooming out too much makes the player too small.

The second solution is having a fixed size for each section equal to the viewport size.

While this works, it imposes a significant constraint when designing the game. Each level is now required to fit a predefined dimension, which makes it way more difficult to create interesting and unique levels.

This strategy requires to have a small character size, to avoid it taking too much of the already limited space available on the screen

There is more.

Every week I build a new open source project, with a new language or library, and teach you how I did it, what I learned, and how you can do the same. Join me and other 600+ readers.

Camera movement strategies

In between the previous 2 strategies, there are some other clever solutions to mitigate the constraints we discussed before:

  • Camera shifting
  • Position smoothing
  • Drag
  • Limits
  • Zoom

Camera shifting

In most platformers is not ideal for the player to be placed exactly in the center of the screen.

Depending on how the level progresses, the camera should allow the player to look ahead to have a clear picture of how to overcome the next challenge or puzzle.

For example, if the level requires the player to climb up a series of vertical platforms, the camera should move accordingly to show more of the top section of the level, leaving the player more toward the bottom of the screen.

The camera shifts toward the top section of the level, indicating to the player that she should move up to continue. Moving the camera upwards causes the character to be located more toward the bottom of the screen.The camera shifts toward the top section of the level, indicating to the player that she should move up to continue. Moving the camera upwards causes the character to be located more toward the bottom of the screen.

The same principle applies to horizontal movements: the player should always be aware of what is coming ahead, so she can plan the next move accordingly.

Camera shifting consists in changing the position of the camera in the four directions.

In practice, this effect can be achieved by specifying a horizontal and vertical shifting percentage: how much the camera should move up, down, left, right compared to the size of the screen.

Position smoothing

If following 1-1 the player is too chaotic, the solution is to smooth the movement of the camera as it follows the character.

Position smoothing consists of a small delay between the movement of the player and the camera. The camera is still attached to the player's position, but it will move with a soft transition instead of following the player's position immediately.

This approach brings some improvements, but alone it is still not enough. When the player moves too fast, the delay introduced by the slow movement of the camera can cause the upcoming areas of the level to become hidden, since the camera is dragging behind.

Furthermore, in some cases, the confusing movement of the camera can still be perceived by the user. The camera is still a hindrance to the gameplay.

Drag

Small and precise movements require the camera to stay fixed. The camera doesn't need to move if the player makes a quick adjustment of its position on the screen.

Drag consists of a rectangular window around the player where she is free to move without causing any camera movement.

This mechanism was used in the original Super Mario games: if you moved by a small amount left or right the camera would not move at all

When the player reaches the limit of the window the camera will drag behind, usually with a smoothing transition, and it will reposition itself when the player stops.

Another step forward with a few drawbacks.

If the drag window is too big, the user will not be able to have a full view of what's laying ahead in her path. That's because, as the player moves, the camera will still stay fixed behind, without showing what's coming ahead (for both horizontal and vertical directions).

On the other hand, when the drag window is too small we fall back to the problems with following the player and position smoothing described above.

Limit

Imagine you are reaching a vertical wall. The level expects you to move up. If the camera is fixed on the player's position, half of the screen will contain a big slice of the wall.

Notice how all the left side of the level consists of a big chunk of the wall. This happens because the camera simply puts the player in the center, without any other adjustment. Why do we need to display such a large unplayable area of the game?Notice how all the left side of the level consists of a big chunk of the wall. This happens because the camera simply puts the player in the center, without any other adjustment. Why do we need to display such a large unplayable area of the game?

In these cases, we can add a Limit to the camera to make it stop when it reaches a certain threshold. Instead of showing the wall, the camera will stop when reaching the limit and become fixed.

Same example as before but with a limit of the left. The camera will not move any further when hitting the limit. In this way, we avoid showing a big unplayable area, while instead staying focused on the direction the player is expected to moveSame example as before but with a limit of the left. The camera will not move any further when hitting the limit. In this way, we avoid showing a big unplayable area, while instead staying focused on the direction the player is expected to move

This strategy solves a specific issue, but it does not address the main problem with camera movement.

Zoom

Another adjustment consists in changing the zoom of the camera (scale).

Some levels may contain more details, which may require reducing the zoom to fit everything inside the screen.

There is more.

Every week I build a new open source project, with a new language or library, and teach you how I did it, what I learned, and how you can do the same. Join me and other 600+ readers.

Mixing strategies

The ideal solution for most platformer games consists in using together all the previous strategies:

  • Apply shifting to focus the player's attention on the path forward
  • Apply smoothing to avoid quick camera movements while following the player
  • Add some drag to leave a window for the player to move without the camera
  • Add limits in certain areas and rooms to avoid showing big unplayable zones
  • Vary the zoom based on the current section of the game

The key insight is the following:

We want to apply these principles depending on the area the player is currently in

It is not enough to use these strategies with the same parameters in all areas of the level. Some rooms may require a limit, some may be vertical, and others may need less zooming.

Implementation example

What we need to implement this strategy is the following:

  • The current player's position to know in which section of the level the character is located
  • A marker that contains the parameters to apply for each section of the level

We then check if the player reached a new marker and we update the camera configuration accordingly.

For example, we can add an area around the player used to check collisions with the markers placed in various positions in the game.

Each marker contains the values to update the configuration of the camera. These parameters are:

  • Shifting percentage: horizontal and vertical percentages using a Vector2
  • Top, bottom, left, right limits: 4 float numbers
  • Top, bottom, left, right drag: 4 float numbers representing the drag margin in each direction
  • Smoothing pixels: a single float number representing the smoothing delay in pixels applied to the camera movement
  • Zoom: a single float number

Note: Not all of them are required for all games and all areas ☝️

When the area around the player collides with a marker we extract each of these values from the marker and we update the camera accordingly.

Example configuration: the player has a circle collision area attached that checks for collisions with the markers throughout the level. When the area collides with a marker a script extracts the marker parameters and applies them to the cameraExample configuration: the player has a circle collision area attached that checks for collisions with the markers throughout the level. When the area collides with a marker a script extracts the marker parameters and applies them to the camera

In Godot a Camera2D note provides some of the parameters out of the box: A Camera2D in Godot allows to change the zoom, limit, drag, and smoothingA Camera2D in Godot allows to change the zoom, limit, drag, and smoothing

For shifting you can change the position inside Node2D based on the size of the viewport:

var viewport_width = ProjectSettings.get_setting("display/window/size/viewport_width")
var viewport_height = ProjectSettings.get_setting("display/window/size/viewport_height")
 
var new_position_x = viewport_width * marker.percentage_camera_position.x
var new_position_y = viewport_height * marker.percentage_camera_position.y
 
camera.position = Vector2(new_position_x, new_position_y)

That's it!

I have been researching and experimenting a lot to find an ideal setup:

After exploring various solutions from different games I finally came up with this implementation.

This requires some preliminary work to add the markers in the game level, but then everything will work great in all sections and areas.

You can subscribe to the newsletter here below for more updates on game design and game development, as well as exclusive updates, tips, and tutorials πŸ‘‡

Thanks for reading

πŸ‘‹γƒ»Interested in learning more, every week?

Every week I build a new open source project, with a new language or library, and teach you how I did it, what I learned, and how you can do the same. Join me and other 600+ readers.