Page 1 of 1

Can't detect when mouse hovers over an object?

Posted: Tue Jul 06, 2021 8:52 pm
by JacobFM
Beginner question alert.
I can't seem to detect when the mouse hovers over a pawn.
I have a similar class called button that works the same way, and functions just fine.

The problematic code:

Code: Select all

Pawn = Class{}

pawns = {}
function pawns:init(x1, y1, x2, y2, x3, y3, type, controller, name, inplay)
    local newPawn = {
    x1 = x1,
    y1 = y1,
    x2 = x2,
    y2 = y2,
    x3 = x3,
    y3 = y3,
    controller = controller,
    type = type,
    inplay = inplay,
    place = "none",
    hot = false
    }
    table.insert(pawns, newPawn)
end

function pawns:update(dt)
    local mx, my = love.mouse.getPosition()
    for i,v in ipairs(pawns) do
        if mx > pawns[i].x1 and mx < pawns[i].x2 then
            if my > pawns[i].y1 and my < pawns[i].y3 then
                pawns[i].hot = true
                currentlyFocused = self
                print("a pawn is hot")
            else
                pawns[i].hot = false
            end
        else
            pawns[i].hot = false
        end
    end
end


function pawns:render()
    pawns:flash()

    for i,v in ipairs(pawns) do
        -- defining a table with the coordinates
        local vertices = {pawns[i].x1, pawns[i].y1, 
        pawns[i].x2, pawns[i].y2, pawns[i].x3, pawns[i].y3}

        if pawns[i].inplay == true then
            -- passing the table to the function as a second argument
            love.graphics.polygon('fill', vertices)
        end
    end
end

-- flash if hot function
function pawns:flash()
    for i,v in ipairs(pawns) do
        if pawns[i].hot == true then
            love.graphics.setColor(0.5, 1, 0.5, 1)
        else
            love.graphics.setColor(0, 0, 0, 1)
        end
    end
end
The working code:

Code: Select all

Button = Class{}

function Button:init(x, y, width, height, name, red, green, blue, action)
    self.x = x
    self.y = y
    self.width = width
    self.height = height
    self.name = name
    self.red = red
    self.green = green
    self.blue = blue
    self.action = action
    self.hot = false
end

function Button:update(dt)
    local mx, my = love.mouse.getPosition()
    if mx > self.x and mx < self.x + self.width then
        if my > self.y and my < self.y + self.height then
            self.hot = true
            currentlyFocused = self
            print("a ui button is hot")
        else
            self.hot = false
        end
    else
        self.hot = false
    end
end

function Button:click()
    if self.hot == true then
        self.action()
    end
end

function Button:render()
    -- set rect color and print
    -- if hot then flash
    self:flash()
    love.graphics.rectangle("fill", self.x, self.y, self.width, self.height)

    -- set text color and print
    love.graphics.setColor(1, 1, 1, 1)
    love.graphics.setFont(mainFont)
    love.graphics.printf(tostring(self.name), self.x, self.y, self.width, "center")
end

-- next turn function
function nextTurn()
    if pTurn == playerNum then
        pTurn = 1
    else
        pTurn = pTurn + 1
    end
end

-- flash if hot function
function Button:flash()
    if self.hot == true then
        love.graphics.setColor(self.red, 1, self.blue, 1)
    else
        love.graphics.setColor(self.red, self.green, self.blue, 1)
    end
end

Re: Can't detect when mouse hovers over an object?

Posted: Tue Jul 06, 2021 9:17 pm
by Gunroar:Cannon()
y3? Should that be y2? Or is x2 maybe supposed to be x3?

Re: Can't detect when mouse hovers over an object?

Posted: Tue Jul 06, 2021 9:36 pm
by idbrii
You could try refactoring your working code into a Hoverable class that you can use in both cases:

Code: Select all

Hoverable = Class{}

function Hoverable:init(x, y, width, height)
    self.x = x
    self.y = y
    self.width = width
    self.height = height
    self.hot = false
end

function Hoverable:update(dt)
    local mx, my = love.mouse.getPosition()
    if mx > self.x and mx < self.x + self.width then
        if my > self.y and my < self.y + self.height then
            self.hot = true
            -- Instead of this single global, you could pass each hoverable a group
            -- key they can use to set themselves (currentlyFocused[self.group] = self).
            -- Then your buttons and pawns can be different groups where each
            -- can only have one hovered but both a button and pawn could be
            -- hovered.
            currentlyFocused = self
            print("a ui button is hot")
        else
            self.hot = false
        end
    else
        self.hot = false
    end
end


Button = Class{}

function Button:init(x, y, width, height, name, red, green, blue, action)
    self.x = x
    self.y = y
    self.width = width
    self.height = height
    self.hover = Hoverable.new(x,y,width,height)
    self.name = name
    self.red = red
    self.green = green
    self.blue = blue
    self.action = action
end

function Button:click()
    if self.hover.hot == true then
        self.action()
    end
end

function Button:update(dt)
    self.hover:update(dt)
end

function Button:render()
    -- set rect color and print
    -- if hot then flash
    self:flash()
    love.graphics.rectangle("fill", self.x, self.y, self.width, self.height)

    -- set text color and print
    love.graphics.setColor(1, 1, 1, 1)
    love.graphics.setFont(mainFont)
    love.graphics.printf(tostring(self.name), self.x, self.y, self.width, "center")
end

-- next turn function
function nextTurn()
    if pTurn == playerNum then
        pTurn = 1
    else
        pTurn = pTurn + 1
    end
end

-- flash if hot function
function Button:flash()
    if self.hover.hot == true then
        love.graphics.setColor(self.red, 1, self.blue, 1)
    else
        love.graphics.setColor(self.red, self.green, self.blue, 1)
    end
end
(Entirely untested.)

Then your Pawn can have one of those hoverables too.

Re: Can't detect when mouse hovers over an object?

Posted: Tue Jul 06, 2021 9:37 pm
by JacobFM
Gunroar:Cannon() wrote: Tue Jul 06, 2021 9:17 pm y3? Should that be y2? Or is x2 maybe supposed to be x3?
No, I think that's correct as it is. An example of one of the pawns initialized:

Code: Select all

pawns:init(1000, 70, 1030, 70, 1015, 35, don, "player" .. tostring(pTurn), "don", true)
Although I did realize that my y1 and y3 were out of order, but fixing that did not fix the issue.

Re: Can't detect when mouse hovers over an object?

Posted: Tue Jul 06, 2021 9:39 pm
by ReFreezed
One issue is the relation between pawns:render() and pawns:flash(). The flash function goes through all pawns and updates the current color with love.graphics.setColor() for every pawn, but the outcome of the function is that the current color will depend on the last pawn. So after the render function has called flash() the current color will depend on whether the *last* pawn was "hot" or not, and then you draw all polygons (which will have the same color). You'll need to call setColor() right before drawing each separate polygon.

Edit: Also, about the coordinates. You may want to remove the assumption that x1/x2/x3 are in a certain order.

Code: Select all

-- Maybe change this
if mx > pawns[i].x1
-- into this
if mx > math.min(pawns[i].x1, pawns[i].x2, pawns[i].x3)
-- etc.

Re: Can't detect when mouse hovers over an object?

Posted: Tue Jul 06, 2021 10:09 pm
by JacobFM
I'm a moron, I just wasn't calling the function. Thanks everyone for your help anyway!

Re: Can't detect when mouse hovers over an object?

Posted: Wed Jul 07, 2021 12:56 pm
by Gunroar:Cannon()
:o :o :o :o :| :rofl: :ultrahappy: