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.
Table of contents
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.
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
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.
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.
FINAL DAYS: Unlock coding courses in Unity, Godot, Unreal, Python and more.