InputEventPanGesture in Godot – Complete Guide

Navigating through the digital realms of game development, we often encounter the need to implement intuitive controls that resonate with user expectations. Gestures, particularly on touch-enabled devices, form an essential part of this interaction. Understanding how gestures work, and how to handle them, is crucial for any game developer committed to crafting an engaging player experience. Today, we delve into the world of touch gestures in Godot 4, focusing on the InputEventPanGesture.

What is InputEventPanGesture?

The InputEventPanGesture is a class in Godot’s robust input event system. It specifically handles information about pan gestures, which typically involve a user swiping the touch screen with two fingers. Events like these are a staple in mobile games and applications, adept at providing a native feel to content scrolling and object maneuvering.

What is it for?

The primary purpose of the InputEventPanGesture is to facilitate the interpretation of panning touch gestures in a Godot project. This event is integral for adding interactive canvas navigation, map movement, or even character controls within a two-dimensional space, where touch is an input form.

Why Should I Learn It?

With the ever-growing market of mobile gaming and applications, mastering gesture inputs is more relevant than ever. Learning how to utilize the InputEventPanGesture can provide your games with:

  • A natural and intuitive control scheme for touch devices.
  • Enhanced interaction, allowing users to feel directly connected with the game’s virtual world.
  • An essential skill in a developer’s toolset for multi-platform development.

Immersive controls are pivotal in keeping players engaged, and through this tutorial, we hope to equip you with the knowledge to implement such features effectively. Join us as we explore the intricate world of gesture-based interactions within Godot 4.

CTA Small Image

Handling InputEventPanGesture in Godot

To handle the InputEventPanGesture in Godot, we need to set up a basic scene with touch input enabled. For our example, we’ll create a simple 2D scene with a sprite that you can pan around.

First, ensure that you have a Node (such as Node2D) as the root of your scene. As a child of this Node, add a Sprite node and assign it a texture.

extends Node2D

func _ready():

func _input(event):
    if event is InputEventPanGesture:

In this example, we’ve set up the `_input(event)` function to listen to input events. When a pan gesture occurs, we call `handle_pan_gesture(event)`.

Implementing The Pan Gesture Handler

Now, let’s define the `handle_pan_gesture(event)` function. The event object contains a `delta` property, which represents the movement of the fingers in screen coordinates.

func handle_pan_gesture(event: InputEventPanGesture):
    var delta =
    print("Pan gesture detected with delta: ", delta)

This code will simply print the direction and magnitude of the pan gesture. It’s meant as a starting point for you to see how gestures are captured.

Moving a Sprite with Pan Gestures

Let’s make the aforementioned sprite move with the gesture. We’ll add some further logic to the just created handler:

func handle_pan_gesture(event: InputEventPanGesture):
    var sprite = $Sprite
    sprite.position +=

With the above code, when you pan on the device, the sprite should now follow the direction of your fingers. This implementation moves the sprite instantly, which might not be what you want for smooth gameplay.

Smoothing the Gesture Movement

To make the movement smoother, you could interpolate the sprite’s position or use a velocity and friction system. Here’s a simple example using interpolation:

var velocity = Vector2.ZERO

func handle_pan_gesture(event: InputEventPanGesture):
    velocity +=

func _process(delta):
    var sprite = $Sprite
    sprite.position += velocity * delta
    velocity = velocity.linear_interpolate(Vector2.ZERO, 0.1)

Now the sprite will move smoothly in the direction of the pan gesture and gradually slow down.

Limiting the Gesture Movement Within the Screen

To prevent the sprite from moving off the screen, we can clamp its position:

func _process(delta):
    var sprite = $Sprite
    sprite.position += velocity * delta

    # Ensure the sprite stays within the screen bounds.
    var screen_size = get_viewport_rect().size
    sprite.position.x = clamp(sprite.position.x, 0, screen_size.x - sprite.texture.get_size().x)
    sprite.position.y = clamp(sprite.position.y, 0, screen_size.y - sprite.texture.get_size().y)

    velocity = velocity.linear_interpolate(Vector2.ZERO, 0.1)

With this added piece of code, the sprite is neatly contained within the screen’s boundaries.

Zooming with Pinch Gestures

While not directly related to panning, let’s touch on a similar gesture mechanic – pinch to zoom. Pinch gestures can be handled with the `InputEventMagnifyGesture` class. Here’s how you can implement a rudimentary pinch-to-zoom:

func _input(event):
    if event is InputEventMagnifyGesture:

func handle_pinch_gesture(event: InputEventMagnifyGesture):
    var sprite = $Sprite
    sprite.scale *= event.factor

This code captures pinch gestures and applies the pinch factor to the sprite’s scale. It’s a common technique used in touch-based games and apps for zooming in and out on an object or scene!

In this part of the tutorial, we structured the basics of handling pan gestures in Godot and manipulating a sprite in response. Take these examples as starting points – there’s much more you can do with these gestures to make your mobile games and applications feel interactive and responsive!

Advanced Gesture Handling

Building upon our foundational knowledge of touch gestures, let’s add more complex functionalities. Here is how we can refine our gesture-based controls for greater precision and a better user experience.

Combining Panning with Other Gestures

Combining pan with other gestures allows us to create more sophisticated controls. For instance, let’s integrate a rotation gesture with our pan gesture:

var initial_angle = 0.0

func _input(event):
    if event is InputEventPanGesture:
    elif event is InputEventScreenDrag:

func handle_rotation_gesture(event: InputEventScreenDrag):
    # Assuming the user has started a rotation
    # You would have more complex logic to determine this condition
    var sprite = $Sprite
    var angle = event.relative_angle_to_last
    initial_angle += angle
    sprite.rotation = initial_angle

In the example above, `InputEventScreenDrag` could be used to determine rotation. The `relative_angle_to_last` property gives us the change in angle, which we add to an `initial_angle` variable to keep track of the sprite’s rotation.

Implementing Kinetic Scrolling

Kinetic scrolling, or inertial scrolling, can be achieved by using the velocity with which the pan gesture ended. Here’s how you can implement this:

var friction = 0.9
var end_velocity = Vector2()

func _input(event):
    if event is InputEventPanGesture:
    # Detect when the panning has ended
    elif event is InputEventScreenTouch and not event.pressed:
        end_velocity = velocity

func _process(delta):
    if end_velocity != Vector2.ZERO:
        var sprite = $Sprite
        sprite.position += end_velocity * delta
        end_velocity = end_velocity.linear_interpolate(Vector2.ZERO, friction * delta)

When the pan gesture ends (`event.pressed` is false), we store the last velocity and use it to continue the movement. We interpolate the `end_velocity` towards zero to simulate friction and slow the sprite down.

Handling Multi-Touch Gestures

Handling multi-touch often requires keeping track of individual touch points. Here’s how you might handle two touch points for a custom gesture:

var touch_points = {}

func _input(event):
    if event is InputEventScreenTouch:
        if event.pressed:
            touch_points[event.index] = event.position

func _process(delta):
    if touch_points.size() == 2:
        # Handle gesture with the two touch points
        var point_1 = touch_points[0]
        var point_2 = touch_points[1]
        # Apply your gesture logic here

We keep a dictionary of touch points, adding them when touched and removing when released. When we have exactly two points, we can apply our multi-touch logic.

Adding Gesture Recognition Logic

Sometimes we need to determine what kind of gesture is being performed:

var last_event_time = 0.0

func _input(event):
    if event is InputEventPanGesture:
        var current_time = OS.get_ticks_msec()
        if current_time - last_event_time > 100:
            print("New gesture detected")
            print("Continued gesture")
        last_event_time = current_time

Here, we detect new gestures by checking the time between pan events. If more than 100 milliseconds have passed, we treat it as a new gesture. Otherwise, it’s a continuation of the last gesture.

Debouncing Rapid Gestures

If you want to limit how quickly gestures can be recognized, you can debounce them:

var debounce_time = 200  # milliseconds
var last_gesture_time = 0.0

func _input(event):
    if event is InputEventPanGesture:
        var current_time = OS.get_ticks_msec()
        if current_time - last_gesture_time > debounce_time:
            last_gesture_time = current_time

By storing the time of the last recognized gesture, you can ignore gestures that happen too soon after. This can prevent erratic behavior from rapid inputs.

Through these code examples, we’re digging deeper into the fine-tuning aspect of touch gestures, bringing your game controls to a professional level. Experiment with these techniques, mix and match them to suit your game’s unique mechanics and remember that a polished user experience often lies in the subtleties of good control systems. Happy coding!Let’s further enhance our touch input handling by adding some advanced features specific to game mechanics.

Gesture-Based Character Movement

For character movement, we can interpret a pan gesture as a directive to move in a certain direction:

func _input(event):
    if event is InputEventPanGesture:

func move_character(direction: Vector2):
    var character = $Character
    character.position += direction.normalized() * speed

This allows for the character to move in the direction of the swipe. Adjust the `speed` variable to control how fast the character moves.

Gesture Interrupts for Improved Control

You might want to provide the player with the ability to interrupt a gesture for a quick response. Here’s how you can detect a tap to halt the current gesture movement:

var is_gesture_active = false

func _input(event):
    if event is InputEventPanGesture:
        is_gesture_active = true
        # Gesture handling logic
    elif event is InputEventScreenTouch and not event.is_echo():
        if is_gesture_active and event.pressed:
            is_gesture_active = false
            # Additional logic to interrupt the gesture

We thus introduce a flag `is_gesture_active` to track the gesture’s state. A new touch event will interrupt the gesture, allowing the player to stop the action immediately.

Implementing Gesture Cooldowns

Sometimes, we want to limit how often a gesture can be used. Here’s an example of implementing a simple cooldown system:

var gesture_cooldown = 1.0  # In seconds
var last_gesture_time = -gesture_cooldown

func _input(event):
    if event is InputEventPanGesture:
        var current_time = OS.get_ticks_msec() / 1000.0
        if current_time - last_gesture_time > gesture_cooldown:
            last_gesture_time = current_time

By timing the last gesture and checking against the cooldown, we ensure the gesture can only happen once every second.

Creating Custom Gesture Patterns

For games where gestures represent spells or special moves, we can define custom gesture patterns. Here’s how you might start implementing such a system:

var gesture_paths = []
const GESTURE_THRESHOLD = 100  # Minimum distance to record a new point

func _input(event):
    if event is InputEventScreenTouch and event.pressed:

    elif event is InputEventScreenDrag:
        var last_position = gesture_paths[-1]
        if last_position.distance_to(event.position) > GESTURE_THRESHOLD:

    elif event is InputEventScreenTouch and not event.pressed:

func analyze_gesture(paths: Array):
    # Logic for analyzing the pattern of gesture_paths
    # Compare against predefined patterns for spells or moves

Here we record points of a drag gesture only when the distance traveled exceeds a certain threshold. When the touch ends, we analyze the gesture.

Adding Gesture Strength

In some games, the strength or speed of a gesture may affect the outcome. Here’s how we might measure the strength of a pan gesture:

func handle_pan_gesture(event: InputEventPanGesture):
    var strength =
    # Use the strength variable for in-game effects

By taking the length of the delta, we get a simple measure of how powerful or quick the panning motion was.

Responsive Gesture-Based Camera Control

Camera control is another important application of gestures. Here’s how you can implement panning and zoom for a 2D camera:

var camera_zoom_speed = 0.05

func _input(event):
    if event is InputEventPanGesture:
        var camera = $Camera2D
        camera.position -=

    elif event is InputEventMagnifyGesture:
        var camera = $Camera2D
        camera.zoom *= (1.0 + event.factor * camera_zoom_speed)

This example provides the player with a way to pan and zoom the camera, perfect for strategy or simulation games, adding a touch of interactivity to the viewing experience.

With each of these gestures, the key to creating an engaging and non-frustrating user experience is to ensure the game responds to them reliably, accurately, and in a fun way! Remember to test and refine your gesture controls based on player feedback.

Continue Your Game Development Journey

Mastering touch gestures in Godot is just the beginning. If you’re eager to continue enhancing your game development skills and create your own stunning cross-platform games, we’ve got just the pathway for you. Check out our Godot Game Development Mini-Degree, a complete learning suite designed to take you from beginner to pro using the powerful and easy-to-learn Godot engine.

Our project-based courses will guide you through everything from the fundamentals of coding with GDScript to the intricacies of building complex game mechanics for different game genres. This comprehensive collection equips you with the knowledge to bring your creative visions to life, step by manageable step. Whether you’re starting your development journey or looking to upskill, our Mini-Degree offers versatile projects and plenty of opportunities to build a strong portfolio.

Beyond that, our broad collection of Godot courses at Zenva Academy awaits learners at all levels. Dive into new challenges, earn certificates, and keep your coding skills razor-sharp. Embark on your next exciting game development adventure with us today!


As we wrap up this exploration of touch gestures within the Godot 4 engine, it’s evident that mastering such interactions is essential for any game developer aiming to thrive in the modern gaming landscape. The skills you’ve picked up today will not only enhance the user experience in your games but also distinguish your creations with professional finesse. And remember, this is just a fragment of the vast capabilities that Godot has to offer.

Don’t stop here; take the next step with our comprehensive Godot Game Development Mini-Degree and transform your passion into tangible, interactive art. From concept to execution, our courses are designed to empower you to craft the games you’ve always dreamed of. So why wait? Join us at Zenva Academy and let’s create game-changing experiences together!

Python Blog Image

FINAL DAYS: Unlock coding courses in Unity, Godot, Unreal, Python and more.