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:
I hope this helps.