InputEventMouseMotion in Godot – Complete Guide

Understanding the magic of motion tracking in games can be both exciting and a critical skill for aspiring developers. In the realm of Godot 4, the InputEventMouseMotion class is a powerful tool that allows us to detect and utilize detailed mouse movement within our games. Whether it’s creating a character that follows the cursor, painting in a drawing application, or navigating through a level, understanding how to work with this particular class is invaluable.

What is InputEventMouseMotion?

InputEventMouseMotion is a class in Godot 4 that inherits from InputEventMouse, which in turn is derived from a series of input-related classes. It represents mouse or pen movement and provides key information such as relative and absolute positions, velocity, and even the pressure of a stylus pen.

What is it for?

This class is instrumental for developers to create responsive and intuitive interactions within their games. It captures the nuances of mouse movements, allowing for high precision tasks like drawing, dragging, or custom mouse cursor effects.

Why Should I Learn It?

Learning to harness InputEventMouseMotion can elevate your game’s interactivity to new heights. It’s a cornerstone for certain genres like drawing applications, RTS games, or any interactive GUI. Grasping its concept will not only add to your skillset but also enable a wide array of possibilities for user input handling in your projects.

CTA Small Image
FREE COURSES AT ZENVA
LEARN GAME DEVELOPMENT, PYTHON AND MORE
ACCESS FOR FREE
AVAILABLE FOR A LIMITED TIME ONLY

Detecting Mouse Motion

To begin, detecting mouse motion in Godot 4 is essential. As players interact with your game using their mouse, it’s vital to respond accordingly.

Here’s a basic example of how to detect mouse motion in GDScript:

func _input(event):
    if event is InputEventMouseMotion:
        print("Mouse moved")

This snippet should be added to your script attached to the Godot node that requires mouse interaction. It will simply print a message to the console every time the mouse moves within the game window.

Let’s get the position where the mouse moved:

func _input(event):
    if event is InputEventMouseMotion:
        print("Mouse Position: ", event.position)

Now, with this information, you could make a sprite follow the cursor:

func _input(event):
    if event is InputEventMouseMotion:
        $Sprite.position = event.position

It’s important to remember that the “$” symbol is shorthand in Godot to reference a node’s path. In this case, “$Sprite” refers to the Sprite node that’s a child of the node the script is attached to.

Customizing the Response to Mouse Motion

We can customize the response based on the mouse’s velocity or speed of movement. This is particularly useful for brush strokes in a painting application or adding resistance to dragging movements in your game.

To use the mouse’s relative velocity:

func _input(event):
    if event is InputEventMouseMotion:
        var velocity = event.relative
        print("Mouse Velocity: ", velocity)

Maybe we’d like to add some camera panning like in a strategy game. For this purpose, we can map mouse movement to camera displacement:

func _input(event):
    if event is InputEventMouseMotion:
        $Camera2D.position += event.relative

This moves the 2D camera based on the mouse’s relative motion, giving the feeling of dragging the camera across the scene.

Enhancing Interactive Objects

If you’re developing a game where objects need to be moved around with the mouse, you can combine mouse buttons with motion to create a drag and drop functionality:

var dragging = false

func _input(event):
    if event is InputEventMouseButton and event.button_index == BUTTON_LEFT and event.pressed:
        dragging = true
    elif event is InputEventMouseButton and event.button_index == BUTTON_LEFT and not event.pressed:
        dragging = false
    
    if event is InputEventMouseMotion and dragging:
        $YourDraggableNode2D.position = event.position

In this example, $YourDraggableNode2D should be the path to your draggable node. When the left mouse button is pressed, we start dragging, and we stop dragging when it’s released.

Binding Mouse Motion to Character Movement

For a game where character movement is essential, like a top-down shooter or an action RPG, you’ll often want to bind mouse movement to character aiming or direction:

func _process(delta):
    var mouse_position = get_global_mouse_position()
    $Player.look_at(mouse_position)

This simple code snippet will make the player character, represented by the node $Player, always face towards the mouse cursor. This is often used to direct the character’s weapon or field of view towards the pointer’s location.Complex actions can require more detailed mouse movement tracking. For example, in an application where we want a character to move toward the mouse position while considering obstacles, we would need to implement pathfinding logic. This involves not just responding to InputEventMouseMotion, but also to mouse clicks that define the target location.

func _input(event):
    if event is InputEventMouseButton and event.button_index == BUTTON_LEFT and event.pressed:
        var target_position = event.position
        move_character_to(target_position)

In this scenario, the move_character_to function would handle pathfinding logic to move the character to the clicked position.

For a real-time strategy game, you might want to implement box selection of units with mouse drag motion:

var start_drag_position
var currently_dragging = false

func _input(event):
    if event is InputEventMouseButton and event.button_index == BUTTON_LEFT and event.pressed:
        start_drag_position = event.position
        currently_dragging = true
    elif event is InputEventMouseButton and event.button_index == BUTTON_LEFT and not event.pressed:
        currently_dragging = false
        select_units_in_box(start_drag_position, event.position)

    if currently_dragging and event is InputEventMouseMotion:
        update_selection_box_visual(event.position)

This example introduces a function select_units_in_box to handle unit selection logic and update_selection_box_visual to update a visual representation of the selection area on the screen.

For games or applications that require drawing or painting, we can track the mouse to draw lines on the canvas. The following could be a function that gets executed whilst the mouse moves:

func draw_line_to(event: InputEventMouseMotion):
    var line = Line2D.new()
    line.add_point(last_mouse_position)
    line.add_point(event.position)
    add_child(line)
    last_mouse_position = event.position

This code creates a Line2D object between the last known mouse position and the current one whenever the mouse is moved, effectively drawing a line. It assumes a variable `last_mouse_position` is being updated elsewhere in the script.

Now, consider adding an undo function for our drawing tool:

var line_history = []

func _input(event):
    if event is InputEventMouseMotion and mouse_is_drawing:
        draw_line_to(event)
    if event is InputEventKey and event.pressed and event.scancode == KEY_Z:
        undo_last_line()

func undo_last_line():
    if line_history.size() > 0:
        var last_line = line_history.pop_back()
        remove_child(last_line)
        last_line.queue_free()

In this script, each line is stored in a history array, and pressing the Z key will remove the last line drawn. Of course, you should also include logic to add lines to `line_history` as they are created.

Lastly, mouse motion can be tracked to rotate objects in our game world smoothly:

var rotation_speed = 0.05 # Adjustable rotation speed

func _input(event):
    if event is InputEventMouseMotion:
        $RotatableNode2D.rotation += event.relative.x * rotation_speed

Adjusting the rotation_speed variable allows us to control how fast the node, in this case `$RotatableNode2D`, rotates in response to mouse movement. This could be used for rotating parts of machinery, steering wheels, or even for puzzle elements in the game.

Through these examples, it becomes apparent that InputEventMouseMotion is exceptionally versatile, which is why understanding and applying its use effectively can greatly enhance the level of interactiveness in your Godot 4 projects. As you journey through game development with us at Zenva, harnessing these skills will no doubt lead to creating more dynamic, responsive and enjoyable game experiences for your players.Tracking the mouse’s position is not limited to just movement. It can be used alongside other input events for complex interactions. Consider a scenario where mouse motion is used to control the tilt of an in-game object, such as an airplane:

var tilt_intensity = 0.1 # Adjust tilt intensity

func _input(event):
    if event is InputEventMouseMotion:
        $Airplane.rotate_y(event.relative.x * tilt_intensity)

In this code, the airplane’s y-axis rotation (tilt) changes according to the mouse’s horizontal motion. By modifying the `tilt_intensity` variable, we can control how sensitive the airplane is to the mouse movement.

Combining mouse motion with key presses can enable special modes, like a precise aim in a shooter game when holding down a key:

var aim_mode_active = false

func _input(event):
    if event is InputEventKey and event.scancode == KEY_SHIFT and event.pressed:
        aim_mode_active = true
    elif event is InputEventKey and event.scancode == KEY_SHIFT and not event.pressed:
        aim_mode_active = false
        
    if event is InputEventMouseMotion and aim_mode_active:
        $Crosshair.position = event.position

Here, the crosshair’s position only updates to the mouse position while the shift key is held down, signifying a precision mode commonly seen in shooting games.

Mouse motion can also be incredibly useful in menu navigation and UI interactions. For example, highlighting buttons as the mouse hovers over them:

func _unhandled_input(event):
    if event is InputEventMouseMotion:
        for button in get_tree().get_nodes_in_group("menu_buttons"):
            if button.get_rect().has_point(event.position):
                button.hovered = true
            else:
                button.hovered = false

This will iterate through all nodes in the “menu_buttons” group and set a `hovered` state depending on whether the mouse is currently over them. This requires that these buttons have a `hovered` property that handles the change in appearance.

Additionally, in some applications, you may want to enable mouse motion-based scrolling. For instance, in a map or document viewer, implementing a hand tool similar to those found in graphic design software can greatly enhance user experience:

var hand_tool_active = false
var last_hand_position = Vector2()

func _input(event):
    if event is InputEventKey and event.pressed and event.scancode == KEY_H:
        hand_tool_active = !hand_tool_active # Toggle hand tool
        
    if event is InputEventMouseMotion and hand_tool_active:
        $ViewportContainer.scroll_horizontal += event.relative.x
        $ViewportContainer.scroll_vertical += event.relative.y

Pressing the ‘H’ key toggles the hand tool mode on and off, while dragging the mouse pans the view within a viewport container.

For a creative touch, we could implement a mouse gesture system that executes commands when certain patterns are drawn:

var mouse_path = []
var GESTURE_TOLERANCE = 10.0 # Pixels of tolerance for gesture recognition

func _input(event):
    if event is InputEventMouseMotion:
        mouse_path.append(event.position)
    
    if event is InputEventMouseButton and not event.pressed and mouse_path.size() > 0:
        if recognize_gesture(mouse_path):
            execute_gesture_command()
        mouse_path.clear()
        
# Imagine recognize_gesture and execute_gesture_command are existing functions

In this hypothetical example, mouse path points are collected, and once the mouse button is released, a `recognize_gesture` function analyzes the path to determine if it matches a predefined pattern within a certain tolerance. If it does, a corresponding command is executed through `execute_gesture_command`.

These examples demonstrate the extensive applications of InputEventMouseMotion in Godot 4 and reflect our commitment at Zenva to equip learners with the practical know-how to create polished and engaging gameplay experiences. Through leveraging the power of mouse motion, the user experience can be greatly enriched, offering players a more immersive and intuitive interaction with your game world.

Continue Your Game Development Journey

By unearthing the potential of InputEventMouseMotion in Godot 4, you’ve taken a significant step in your game development journey. Your road doesn’t end here; continue to build on your skills and delve deeper into the world of game creation with us at Zenva. We welcome you to explore our Godot Game Development Mini-Degree. Here, you’ll learn to construct cross-platform games from scratch, get comfortable with GDScript, and create a bounty of projects that will enhance your portfolio and knowledge base.

Whether you’re just starting out or you’re looking to polish your skills, this comprehensive collection of project-based courses caters to all levels of experience. Besides, for an even broader selection, check out our full array of Godot courses. The world of game development is vast and always evolving; by learning with Zenva, you can ensure that your abilities grow with it, keeping you adaptable, proficient, and ready to seize the boundless opportunities that await in the game industry.

Conclusion

In closing, mastering InputEventMouseMotion and other Godot 4 intricacies paves the way to truly interactive and immersive game experiences. As game developers, our aspiration is not just to make games, but to craft worlds that players can feel deeply connected with, through each click and drag of the mouse. Your dedication to learning and improving has the potential to translate into unforgettable gaming moments and innovative mechanics in your projects. We at Zenva are passionate about providing the keys to unlock that potential.

Stay ahead in your game development journey by diving further into our Godot Game Development Mini-Degree, where each lesson is a step towards realizing your dream games. Embrace the challenge, seize the knowledge, and let’s create amazing gaming experiences together – one line of code at a time.

FREE COURSES
Python Blog Image

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