Godot Engine: Custom 2D camera Monday, October 30, 2017
programming godot

For one of the projects I'm working on (A remake of my Unreal sidescroller) I needed a camera that would follow my player. Godot has a Camera2D node that gives you that functionality but not exactly like I needed.

I needed my camera to just follow the player horizontally and even though there isa drag margins setting I was not able to get it to work. If you happen to know how to setup the drag margins so that it works that way please leave a comment below.

So instead of using the Camera2D node I decided to make my own. It turns out that it is rather easy and someone has already done most of the work :)

GDQuest has a video about it and sample code. My code is based pretty much of that plus some changes. Here is my code:

extends Node2D

export(NodePath) var player_path

onready var screen_size = Vector2(Globals.get("display/width"), Globals.get("display/height"))
onready var player = get_node(player_path)

const HORIZONTAL_OFFSET = 200

var new_position = Vector2()
var player_pos = Vector2()


func _ready():
    set_fixed_process(true)
    update_camera()

func _fixed_process(delta):
    update_camera()

func update_camera():
    if player:
        var canvas_transform = get_viewport().get_canvas_transform()
        player_pos = player.get_pos()
        new_position = -player_pos + screen_size / 2
        new_position.x -= HORIZONTAL_OFFSET 
        new_position.y = canvas_transform[2].y
        canvas_transform[2] = new_position
        get_viewport().set_canvas_transform(canvas_transform)

I want to point out that I use Vector2(Globals.get("display/width"), Globals.get("display/height")) because that would give me the size defined under Display settings and NOT the physical display size that OS.get_window_size() would give you. Depending on how you have designed your game and the kind of scaling you are doing this matters. Also, I have setup an offset so the player is a little more to the left so it is easier to see what's coming from the right sooner. Since I don't want to follow the players Y position I ignore it as well.

Another change I made is that I don't rely in signals to update the camera, instead I do it on my my _fixed_process method. Also the camera node is a child of the player.

Here is the Player scene:

Godot Player Camera

I hope this helps.