Skip to content

Mouse Dragging in Love2D

Posted on:September 6, 2011

In this tutorial, I’ll be taking you through my method of enabling objects to dragged by the mouse (in LÖVE of course). You can view the completed code for this tutorial at gist #1196228.

So, say you have an object with x/y coordinates, width, and height, and you want this object to be draggable by the mouse. For this tutorial, I’m just going to construct a table and put in the global, rect:

function love.load()
  rect = {
    x = 100,
    y = 100,
    width = 100,
    height = 100,
    dragging = { active = false, diffX = 0, diffY = 0 }
  }
end

The next thing we need to do is define love.draw to draw the rectangle. (We’ll see what rect.dragging is all about soon.)

function love.draw()
  love.graphics.rectangle("fill", rect.x, rect.y, rect.width, rect.height)
end

Now here’s where the good stuff begins:

function love.mousepressed(x, y, button)
  if button == "l"
  and x > rect.x and x < rect.x + rect.width
  and y > rect.y and y < rect.y + rect.height
  then
    rect.dragging.active = true
    rect.dragging.diffX = x - rect.x
    rect.dragging.diffY = y - rect.y
  end
end

The if statement checks for whether the left mouse button was pressed, and does a simple collision check to see if the mouse button was pressed while inside the bounds of the rectangle. If so, we update the variables inside rect.dragging.

rect.dragging is where we store persistent information about the current dragging action. active is used to tell whether a dragging action is taking place at all. The other two, diffX and diffY, are used to store the difference between the top-left corner of the rectangle and the mouse’s position when the mouse button was initially clicked. To find out why these variables are important, we need to define love.update:

function love.update(dt)
  if rect.dragging.active then
    rect.x = love.mouse.getX() - rect.dragging.diffX
    rect.y = love.mouse.getY() - rect.dragging.diffY
  end
end

If the mouse is currently dragging, we update the rectangle’s x/y coordinates. Instead of just setting the rectangles coordinates to the mouse’s respective coordinates, we subtract diffX and diffY, respectively. Why is this? If we were to not do this, the rectangle’s top-left corner would jump to the mouse’s position whenever the rectangle is dragged, and that doesn’t look good at all. Subtracting the initial difference in positions will fix this problem.

Finally, to make sure that dragging is turned off properly:

function love.mousereleased(x, y, button)
  if button == "l" then rect.dragging.active = false end
end

And that’s it. As stated, you can view the complete code at gist #1196228. Of course, this code is just one implementation of the method I use; you will most likely implement it differently depending on what you use it for.

Anyway, thanks for reading!