+2 votes

How can i drag my camera2d with mouse?

in Engine by (47 points)

2 Answers

+6 votes
Best answer

Your question is a bit vague, I'd recommend adding a bit more context to get a better answer, however, making some assumptions about your question, here is my advice.

  1. Create a root node Node2D in the 2D scene.
  2. Create a KinematicBody2D as a child of the root.
  3. Create a CollisionShape2D as a child of that.
  4. Create a Sprite, also as a child of the KinematicBody2D, and assign a texture.
  5. Add a shape to the CollisionShape2D and adjust it to fit your sprite.
  6. Create a Camera2D, also as a child of the KinematicBody2D.
  7. Create some background assets under the root Node2D as appropriate.
  8. Add the following code to the KinematicBody2D...

    extends KinematicBody2D
    var dragging = false
    
    func _ready():
        set_process_input(true)
    
    func _input(event):
        if event is InputEventMouseButton:
            if event.is_pressed():
                dragging = true
            else:
                dragging = false
        elif event is InputEventMouseMotion and dragging:
            position = get_global_mouse_position()
    
  9. Make the Camera2D current by selecting the flag, and optionally enable or disable the Drag Margin flags, depending on how you want it to move.

That should do it, if you drag the sprite around now, the camera should follow. You may find it a bit difficult to control, so it might be wise to add some speed control or something, depending on the effect you're after.

For reference, I've put a simple sample project here that shows what I've just described.

by (325 points)
selected by

pgregory

This seems way over complicated for such a simple thing. I'm still learning Godot and but I was able to get a camera to pan with this code:

extends Camera2D
class_name MainCamera

var _previousPosition: Vector2 = Vector2(0, 0);
var _moveCamera: bool = false;

func _unhandled_input(event: InputEvent):
if event is InputEventMouseButton && event.button_index == BUTTON_LEFT:
    get_tree().set_input_as_handled();
    if event.is_pressed():
        _previousPosition = event.position;
        _moveCamera = true;
    else:
        _moveCamera = false;
elif event is InputEventMouseMotion && _moveCamera:
    get_tree().set_input_as_handled();
    position += (_previousPosition - event.position);
    _previousPosition = event.position;

Why not recommend something like this to people?

I haven't tried your code out, but from an initial scan it looks like your code would move the camera irrespective of where the mouse had been clicked. As I mentioned in my solution, the question is a bit vague, I was basing my answer on the specifics of "drag", meaning to me, dragging a particular 'thing' around in the scene to move the view. If the required solution is to just move the camera in response to any mouse movement, anywhere, then yes, your solution would probably do the right thing.

This worked perfectly. Thanks

+6 votes

This is based party on pgregory's code.

I simply attached this script to active Camera:

extends Camera2D

var mouse_start_pos
var screen_start_position

var dragging = false


func _input(event):
    if event.is_action("drag"):
        if event.is_pressed():
            mouse_start_pos = event.position
            screen_start_position = position
            dragging = true
        else:
            dragging = false
    elif event is InputEventMouseMotion and dragging:
        position = zoom * (mouse_start_pos - event.position) + screen_start_position

The zoom * is there so that if the camera is zoomed in or out, the scroll will be relative to the zoom.

I also added a "drag" event on the "input Map" in project settings, which for me is the middle mouse button. However just putting event is InputEventMouseButton: instead should work for the left click.

by (42 points)

Very late answer but exactly what I needed, thanks a lot :D

Any idea on how to make it go to the inverse direction?

change

(mouse_start_pos - event.position)

to

-(mouse_start_pos - event.position)

Hey everyone!

Any idea how to make it so that the camera can not go to infinity?

I actually needed to divide by the zoom instead of multiplying by it for it to work correctly, maybe this will save someone some time.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.