## Layered mouse collision

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
10c8
Prole
Posts: 6
Joined: Wed Apr 25, 2018 4:53 pm
Contact:

### Layered mouse collision

Hey, I'm currently working on a card game. On the screen, each player's hand is drawn as a fan of cards (image below), where cards may slightly overlap each other, this means that by simply checking if the mouse is within each card's rectangle sometimes returns more than one card. I figured I could check which one of them has the bigger index and make this one the "hovered" card, but I thought there might be a better way of doing this?

The cards are all kept on a table, each one has x and y coordinates and a rotation. They're drawn in order (from 1 to ...).
img.png (125.07 KiB) Viewed 2414 times
ivan
Party member
Posts: 1719
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

### Re: Layered mouse collision

I figured I could check which one of them has the bigger index and make this one the "hovered" card
You are correct, this is by far the simplest technique.
Suppose you have a numerically indexed table of cards - you are drawing them in order so cards with a higher index are drawn on top.
Next, you want something to "query" those cards:

Code: Select all

cards = {}

function query(cards, x, y)
-- NOTE: iterate in reverse so that the top card is selected first
for i = #cards, 1, -1 do
if testCard(cards[i], x, y) then
return cards[i], i
end
end
end

function testCard(card, x, y)
-- WARNING: assumes the top left corner of the card is the origin (0, 0)
-- convert to local coords
local lx, ly = x - card.x, y - card.y
-- rotate so that we are axis aligned
local c = math.cos(card.angle)
local s = math.sin(card.angle)
local rx = c*lx - s*ly
local ry = s*lx + c*ly
-- axis aligned test
return rx >= 0 and rx <= card.width and ry >= 0 and ry <= card.height
end
That's all you need, really. Note that my example assumes that 0, 0 is the top-left corner of the card.
It's easier if you rotate cards around their center but then your "axis aligned test" needs to be modified slightly.
Good luck!
10c8
Prole
Posts: 6
Joined: Wed Apr 25, 2018 4:53 pm
Contact:

### Re: Layered mouse collision

Thanks! By the way, how would I go about doing those calculations when the origin is the bottom-center (0.5, 1)?
ivan
Party member
Posts: 1719
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

### Re: Layered mouse collision

Believe me, the math is much simpler and more scalable if use the "center" option and it makes drawing easier too.
You only need to change the last line:
Top left corner:

Code: Select all

return rx >= 0 and rx <= w and ry >= 0 and ry <= h
Center:

Code: Select all

return rx >= -w/2 and rx <= w/2 and ry >= h/2 and ry <= h/2
Bottom-center:

Code: Select all

return rx >= -w/2 and rx <= w/2 and ry >= -h and ry <= 0
Assuming that:
0,0 is the to-left corner of the window
card.x, card.y = origin point of the card (window coordinates)
card.angle = angle of the card in radians (objects rotate counter-clockwise as this value increases)
edit: the rotation might be reversed if your y-axis increases down (or South) which is customary when drawing with Love2d
Personally I take it one step further and program my games with the Y axis increasing up (North) and I assume that 0,0 is the center of the window - it makes the trigonometry calculations even simpler.
Last edited by ivan on Wed Apr 25, 2018 8:03 pm, edited 4 times in total.
10c8
Prole
Posts: 6
Joined: Wed Apr 25, 2018 4:53 pm
Contact:

### Re: Layered mouse collision

I tried your code and this happens:
Captura de tela de 2018-04-25 16-42-35.png (91.79 KiB) Viewed 2380 times
It only seems to detect a collision correctly when there's a single card (with almost no rotation):
Captura de tela de 2018-04-25 16-44-09.png (22.75 KiB) Viewed 2380 times
Captura de tela de 2018-04-25 16-44-26.png (15.57 KiB) Viewed 2380 times
It seems to depend on the angle of the card.
10c8
Prole
Posts: 6
Joined: Wed Apr 25, 2018 4:53 pm
Contact:

### Re: Layered mouse collision

10c8 wrote: Wed Apr 25, 2018 7:47 pm I tried your code and this happens:

It only seems to detect a collision correctly when there's a single card (with almost no rotation):

It seems to depend on the angle of the card.
Nevermind, your code assumes that the card rotates counter-clockwise with the angle, but they rotate clockwise. So I just changed the instances of rotation to -rotation!
ivan
Party member
Posts: 1719
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

### Re: Layered mouse collision

I'm pretty sure that the technique I posted works...
It might not work using copy/paste - additional work may be required, depending on how you draw the cards.
You need to include a .love file if you expect me to help you any further.
ivan
Party member
Posts: 1719
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

### Re: Layered mouse collision

10c8 wrote: Wed Apr 25, 2018 7:51 pm your code assumes that the card rotates counter-clockwise with the angle
That's a standard assumption in trigonometry (math.cos/math.sin) it's just a question of how you decide to draw the cards.
Again, it's very important to distinguish between your logic/math code and your rendering/drawing code.

PS. Actually, if your Y-axis increases down like in love2d, that might flip the angle.

### Who is online

Users browsing this forum: No registered users and 17 guests