Dragging an object/image, making it clickable
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
Dragging an object/image, making it clickable
hi there,
how do I tell love, that a certain callback responds only within a fixed field, like 160X160 of a certain picture ? For example if id like to drag an object along, how do I specify that I want the callback to work only if i click within the confines of a specific field, or .png res, and not anywhere on the screen ?
I kinda have an idea how to do it with rectangles for example, you set it with delta rect.width, and hight, etc. But with image, I dont know how to make that interval...
hope that makes sense
kind regards
gignat
how do I tell love, that a certain callback responds only within a fixed field, like 160X160 of a certain picture ? For example if id like to drag an object along, how do I specify that I want the callback to work only if i click within the confines of a specific field, or .png res, and not anywhere on the screen ?
I kinda have an idea how to do it with rectangles for example, you set it with delta rect.width, and hight, etc. But with image, I dont know how to make that interval...
hope that makes sense
kind regards
gignat
Re: Dragging an object/image, making it clickable
https://love2d.org/wiki/Image
You do it the exact same way. Since you are providing a callback with the image I assume you are making it an object already, so just add a rectangular bounding box with the linked functions.
You do it the exact same way. Since you are providing a callback with the image I assume you are making it an object already, so just add a rectangular bounding box with the linked functions.
Re: Dragging an object/image, making it clickable
greetings Marekk, thank you for your reply.
been trying the whole day, with no results. I ended up using this code (https://gist.github.com/1196228) and just pasted an image on top of that rectangle. Im a complete noob otherwise. This works though, but I cheated
why does he use tables ? Is there no other way to drag something around than to put it on top of a rectangle ? What if a certain shape cannot cover the triangle?
EDIT : I wanted to try changing the color of the rectangle, but with this, for some reason, it colors both the rect and the picture on top of it
thank you for your input !
gignat
been trying the whole day, with no results. I ended up using this code (https://gist.github.com/1196228) and just pasted an image on top of that rectangle. Im a complete noob otherwise. This works though, but I cheated
why does he use tables ? Is there no other way to drag something around than to put it on top of a rectangle ? What if a certain shape cannot cover the triangle?
EDIT : I wanted to try changing the color of the rectangle, but with this, for some reason, it colors both the rect and the picture on top of it
Code: Select all
function love.draw()
love.graphics.rectangle("fill", rect.x, rect.y, rect.width, rect.height)
love.graphics.setColor(0, 255, 0, 100)
love.graphics.draw(dexter, rect.x-45, rect.y-68)
end
thank you for your input !
gignat
Re: Dragging an object/image, making it clickable
That's kinda what you do, but you don't need to draw the rectangle. Your bounding box is a completely abstract structure. You could make a bounding box a circle, a hexagon, a donut, whatever. It's just data representing the clickable area of your image. The computer doesn't need a visual representation of it to decide if it is within the bounding box. Attached is a quick and dirty example of what you could do to make it a bit more extendable than your current process.
What I was getting at in my first post was something like this (taken from the attached example):
This simply couples the position of the image with the properties you could already get from your image.
As for your second problem, think of love.graphics.setColor as a global variable color, so when you do:
It's "kinda" like doing this:
Now every drawable object looks at this global variable and applies it. So let's walk through it:
The fix:
EDIT: changed the newDraggable so someone doesn't go "Hem, 'tis more efficient if thou werest to do it in such a way as this..."
What I was getting at in my first post was something like this (taken from the attached example):
Code: Select all
function newDraggable(x, y, img)
return {
x = x,
y = y,
img = img,
w = img:getWidth(),
h = img:getHeight()
}
end
As for your second problem, think of love.graphics.setColor as a global variable color, so when you do:
Code: Select all
love.graphics.setColor(255,0,0)
Code: Select all
color = {255,0,0}
Code: Select all
-- First iteration
function love.draw()
love.graphics.rectangle(...) -- reads the default color {255,255,255}
love.graphics.setColor(255,0,0) -- sets the "color" variable to {255,0,0}
love.graphics.draw(...) -- reads {255,0,0} for its color
end
-- Second iteration
function love.draw()
love.graphics.rectangle(...) -- reads {255,0,0} for its color
-- etc
end
Code: Select all
function love.draw()
love.graphics.setColor(255,255,255) -- always sets the color back to default at the start of the draw loop
love.graphics.rectangle(...)
love.graphics.setColor(255,0,0)
love.graphics.draw(...)
end
- Attachments
-
- draggin.love
- (4.56 KiB) Downloaded 241 times
Re: Dragging an object/image, making it clickable
Here's a demo that does what MarekkPie's does, except that the icon doesn't center on the mouse whenever clicked. It does this by keeping track of the mouse's offset from the icon upon being clicked. It uses love.mousepressed() and love.mousereleased() to change the "being dragged" state, rather than checking the mouse button's state during love.update(). (I suppose this method could have its own drawbacks in a real application.)
Please check the code and let me know if there is a smarter way to do this. This is my first time sharing original code with people if I recall.
Please check the code and let me know if there is a smarter way to do this. This is my first time sharing original code with people if I recall.
- Attachments
-
- drag-n-drop.love
- Click-to-drag demo
- (1.46 KiB) Downloaded 265 times
Re: Dragging an object/image, making it clickable
wow guys, youre the best
@Marekk : thank you so much for taking the time and writing the example, it has helped my understanding alot. I have a question though, well I have lots, but ill focus on one )
why do you halve the graphics getiWidth and getHeight at the beggining ?
also, the within function makes my brain cook
why do we need it ? doesnt the clause in love update, cover our condition of checking mouse click, and if that click was made in the confines of the pie area ?? Btw I LOLed when I saw the pie loaded up first time
@hryx : thank you very much also man. You have a different version, which is kind of similar to what I initially started with, checking only the presses, and releases.
2 things bother me.
a)Why do you need to do icon.img = img_default ? Cant you simply check the properties with the img_default ??
b) again the half fraction...you divide the screen width and length with 2 but subtract our objects properties also
thanks very, very much. This community is becoming the greatest thing ive come across lately.
gignat
@Marekk : thank you so much for taking the time and writing the example, it has helped my understanding alot. I have a question though, well I have lots, but ill focus on one )
why do you halve the graphics getiWidth and getHeight at the beggining ?
Code: Select all
pie = newDraggable(
love.graphics.getWidth() / 2,
love.graphics.getHeight() / 2,
love.graphics.newImage("cherrypie_obey.jpg"))
grabbed = false
Code: Select all
function within(x,l,u)
if x < l then return -1
elseif x > u then return 1
else return 0 end
end
@hryx : thank you very much also man. You have a different version, which is kind of similar to what I initially started with, checking only the presses, and releases.
Code: Select all
icon = {}
icon.img = img_default
icon.w = icon.img:getWidth()
icon.h = icon.img:getHeight()
icon.x = love.graphics.getWidth() / 2 - icon.w / 2
icon.y = love.graphics.getHeight() / 2 - icon.h / 2
a)Why do you need to do icon.img = img_default ? Cant you simply check the properties with the img_default ??
b) again the half fraction...you divide the screen width and length with 2 but subtract our objects properties also
thanks very, very much. This community is becoming the greatest thing ive come across lately.
gignat
Re: Dragging an object/image, making it clickable
I used two images in the demo just for fun. love.draw() will always draw whatever is referenced in icon.img. When you click on the icon it changes that value to the image img_clicked, and when you release the mouse it returns to img_default.gignat wrote:a)Why do you need to do icon.img = img_default ? Cant you simply check the properties with the img_default ??
A different way of doing it:
Code: Select all
...
love.draw()
if icon.is_being_dragged then
love.graphics.draw(img_clicked, icon.x, icon.y)
else
love.graphics.draw(img_default, icon.x, icon.y)
end
end
...
If you're talking about this:gignat wrote:b) again the half fraction...you divide the screen width and length with 2 but subtract our objects properties also
Code: Select all
icon.x = love.graphics.getWidth() / 2 - icon.w / 2
icon.y = love.graphics.getHeight() / 2 - icon.h / 2
Re: Dragging an object/image, making it clickable
The width/height is just the x,y coordinates of my image at the start of the demo.
The "within" is my little way of making n-dimensional containment easier. The normal containment function (for 2 dimensions, assuming axis-alignment (fancy way of saying "not at an angle")) would be:
...which I find both terribly annoying and hard to read. What are you really doing here? You are saying "Is x within the left of the rectangle and the right of the rectangle, and is y within the top of the rectangle and the bottom of the rectangle?"
So I made "within", which is just containment in one dimension. I also made it give you three response, -1 if you are less than the lower bound, 0 is you are within the bounds, and 1 if you are greater than the upper bound. So now, if I ever need to check positioning, I have a function for that already.
Example:
A "visual example" of why hryx subtracted half of his image. I'd rather not draw at the moment, so ASCII it is:
We have a rectangle of size 6x4. We want the image in the center of our screen. If we just put it at (windowWidth/2,windowHeight/2), then it places the top-left corner of the image at that position, which is not exactly the center. We are trying to put the center of the picture in the center of the screen, but we have overshot by (3,2) (half the width of our rectangle, half the height of our rectangle).
(I didn't bother on mine, because...it's a demo, who really cares?)
The "within" is my little way of making n-dimensional containment easier. The normal containment function (for 2 dimensions, assuming axis-alignment (fancy way of saying "not at an angle")) would be:
Code: Select all
function contains(x,y,rect)
if x > rect.x and x < rect.x+rect.w and y > rect.y and y < rect.y+rect.h then
return true
end
return false
end
So I made "within", which is just containment in one dimension. I also made it give you three response, -1 if you are less than the lower bound, 0 is you are within the bounds, and 1 if you are greater than the upper bound. So now, if I ever need to check positioning, I have a function for that already.
Example:
Code: Select all
function getRelativePosition(x,y,rect)
return within(x,rect.x,rect.x+rect.w), within(y,rect.y,rect.y+rect.h) -- <= returns 9 possible positions relative to the rect
end
Code: Select all
======
= =
= =
======
(I didn't bother on mine, because...it's a demo, who really cares?)
Re: Dragging an object/image, making it clickable
Well nice work with the small demo because if both of you didn't notice if you add a mouse over state and a table for multiple clickable objects to your demos you actually have a valuable and complete drag and drop mouse library. You should add it to wiki snippets.
Re: Dragging an object/image, making it clickable
I could probably build it out a bit more, make it more generalized, but I guess you're right.
I also just noticed that getRelativePosition is a superset of containment. So you could just go:
I also just noticed that getRelativePosition is a superset of containment. So you could just go:
Code: Select all
function contains(x,y,rect)
local xVal, yVal = getRelativePosition(x,y,rect)
if xVal == 0 and yVal == 0 then return true end
return false
end
Who is online
Users browsing this forum: Bing [Bot], Google [Bot] and 1 guest