Logo

Braindead.bzh

Game Dev Hobbyist

A blog about my game dev hobby and various stuff.

Menu
Logo

Braindead.bzh

Game Dev Hobbyist

A blog about my game dev hobby and various stuff.

Godot Quick Tip #1 - Interactive Camera2D

A simple script to create an interactive camera for 2D games made with Godot Engine.

Introduction

You can find below a very simple script that you can attach to any Camera2D node within Godot Engine. It provides the following functionality:

  • Moving the camera using the mouse
  • Zoom centered on mouse cursor
  • Rebindable actions through Godot's Input Map
  • Signal emitting if you need to make other nodes react to camera movement or zoom

Additional instructions

In order to the script to work, you need to setup actions in the Input Map (Menu: Scene>Project Settings>Input Map). There is three actions to add:

  • cam_drag: typically you want to bind this action to a mouse button, try the right button so it does not interfere with the regular click.
  • cam_zoom_in: you can bind it to the Wheel Up mouse button, you could also a key binding the the '+' of the keypad
  • cam_zoom_out: you can bind it to the Wheel Down mouse button, you could also a key binding the the '-' of the keypad

Script

For Godot 2

extends Camera2D

const MAX_ZOOM_LEVEL = 0.5
const MIN_ZOOM_LEVEL = 4.0
const ZOOM_INCREMENT = 0.05

signal moved()
signal zoomed()

var _current_zoom_level = 1
var _drag = false

func _ready():
    set_process_input(true)

func _input(event):
    if event.is_action_pressed("cam_drag"):
        _drag = true
    elif event.is_action_released("cam_drag"):
        _drag = false
    elif event.is_action("cam_zoom_in"):
        _update_zoom(-ZOOM_INCREMENT, get_local_mouse_pos())
    elif event.is_action("cam_zoom_out"):
        _update_zoom(ZOOM_INCREMENT, get_local_mouse_pos())
    elif event.type == InputEvent.MOUSE_MOTION && _drag:
        set_offset(get_offset() - event.relative_pos*_current_zoom_level)
        emit_signal("moved")

func _update_zoom(incr, zoom_anchor):
    var old_zoom = _current_zoom_level
    _current_zoom_level += incr
    if _current_zoom_level < MAX_ZOOM_LEVEL:
        _current_zoom_level = MAX_ZOOM_LEVEL
    elif _current_zoom_level > MIN_ZOOM_LEVEL:
        _current_zoom_level = MIN_ZOOM_LEVEL
    if old_zoom == _current_zoom_level:
        return
    
    var zoom_center = zoom_anchor - get_offset()
    var ratio = 1-_current_zoom_level/old_zoom
    set_offset(get_offset() + zoom_center*ratio)
    
    set_zoom(Vector2(_current_zoom_level, _current_zoom_level))
    emit_signal("zoomed")

For Godot 3

extends Camera2D

const MAX_ZOOM_LEVEL = 0.5
const MIN_ZOOM_LEVEL = 4.0
const ZOOM_INCREMENT = 0.05

signal moved()
signal zoomed()

var _current_zoom_level = 1
var _drag = false

func _input(event):
    if event.is_action_pressed("cam_drag"):
        _drag = true
    elif event.is_action_released("cam_drag"):
        _drag = false
    elif event.is_action("cam_zoom_in"):
        _update_zoom(-ZOOM_INCREMENT, get_local_mouse_position())
    elif event.is_action("cam_zoom_out"):
        _update_zoom(ZOOM_INCREMENT, get_local_mouse_position())
    elif event is InputEventMouseMotion && _drag:
        set_offset(get_offset() - event.relative*_current_zoom_level)
        emit_signal("moved")

func _update_zoom(incr, zoom_anchor):
    var old_zoom = _current_zoom_level
    _current_zoom_level += incr
    if _current_zoom_level < MAX_ZOOM_LEVEL:
        _current_zoom_level = MAX_ZOOM_LEVEL
    elif _current_zoom_level > MIN_ZOOM_LEVEL:
        _current_zoom_level = MIN_ZOOM_LEVEL
    if old_zoom == _current_zoom_level:
        return
    
    var zoom_center = zoom_anchor - get_offset()
    var ratio = 1-_current_zoom_level/old_zoom
    set_offset(get_offset() + zoom_center*ratio)
    
    set_zoom(Vector2(_current_zoom_level, _current_zoom_level))
    emit_signal("zoomed")

Written by Olivier on Tuesday February 7, 2017

« Creating a game with Godot Engine - Ep.7 - The ball Creating a game with Godot Engine - Ep.8 - Levels »

comments powered by Disqus