[Solved] Mouse click weirdness

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
Vmpwraith
Prole
Posts: 9
Joined: Thu Jan 15, 2015 12:00 am

[Solved] Mouse click weirdness

Post by Vmpwraith »

hi
I made a little game out of what I've been learning in Love2d but I have a weird issue happening with the mouse clicks. If you start the game and click the circles they disappear fine, but if you let a couple spawn sometimes the one you are clicking will become immune and a random circle will disappear, then it will start working again, on and off. Anyone have any ideas about this, maybe its not updating mouse position or miss reading it.
cheers for taking a look.

Code: Select all

--[[
Rings Game
Digitalrecline
Auckland(NZ)
Practice exersie with Lua and Love2D August 2017
]]

-- Declcare Variables
spawntimer = 1 -- time to spawn

rings ={} -- table to hold the rings we create

ringWidth = 20 -- line width for our rings

ringColour = {} -- our colour palete
ringColour[1] = {col='green',r=70,g=140,b=38,a=255,vel=0.15,score= 15}
ringColour[2] = {col='pink',r=163,g=73,b=115,a=255,vel=0.16,score= 16}
ringColour[3] = {col='blue',r=93,g=132,b=166,a=255,vel=0.14,score= 14}
ringColour[4] = {col='yellow',r=242,g=222,b=160,a=255,vel=0.2,score= 20}
ringColour[5] = {col='tan',r=242,g=220,b=201,a=255,vel=0.13,score= 13}

ringToBig = 250 -- ring explodes as got to big - points from player score
playerScore = 0

--[[
Our functions
]]

function randomCircle() -- randomCircle() creates our randomCircle variables
  rR = love.math.random(20, 100) -- random radius
  rX = love.math.random(0+rR, love.graphics.getWidth() - (rR + ringWidth) - ringToBig) --random x
  rY = love.math.random(0+rR, love.graphics.getHeight()- (rR + ringWidth) - ringToBig) -- random y
  rColour = love.math.random(1, #ringColour) --sets random colour and velocity
end

--[[newRing() creates our rings and test to see if the collide on creation.
1st ring created before it starts seeing if they subsequent ones overlap.]]
local function newRing()
    if (#rings) == 0 then -- makes first ring if no exist
        randomCircle()
        myNewRing = {
          r= rR,x= rX,y =rY, colr=ringColour[rColour].r,
          colg=ringColour[rColour].g,colb=ringColour[rColour].b,
          cola=ringColour[rColour].a,vel=ringColour[rColour].vel,
          score=ringColour[rColour].score
          }
        table.insert(rings, myNewRing) -- adds new ring to our table
        spawntimer = 1 -- sets the time before next ring is spawned
    else
        while true do -- infinate loop to create new rings
          randomCircle()
          local collides = false
            for i, v in ipairs(rings) do
              --[[ collison calculations on all rings in table until a collison
                  is detected using pythagoras to calculate distance]]
                local dx = rX - v.x
                local dy = rY - v.y
                local distCalc = dx * dx + dy * dy
                if distCalc <= ((v.r + ringWidth) + (rR + ringWidth))^2 then
                    collides = true
                    break -- restarts while loop once one collision is found
                end -- end if distCalc block
            end -- i,v block
          if not collides then -- adds to rings table if no collisions
            myNewRing = {
              r= rR,x= rX,y =rY, colr=ringColour[rColour].r,
              colg=ringColour[rColour].g,colb=ringColour[rColour].b,
              cola=ringColour[rColour].a,vel=ringColour[rColour].vel,
              score=ringColour[rColour].score
              }
            table.insert(rings, myNewRing)
            spawntimer = 1
            break
          end -- end if not collides block
        end -- end while loop
      end
end

function collision()

-- remove all collided rings
  for k = #rings, 1, -1 do
     local rX = rings[k].x
     local rY = rings[k].y
     local rR = rings[k].r
     local collides
     for j = k + 1, #rings do
        local dx = rX - rings[j].x
        local dy = rY - rings[j].y
        sj = rings[j].score
        sk = rings[k].score

        local distCalc = dx * dx + dy * dy
        if distCalc <= ((rings[j].r + ringWidth) + (rR ))^2 then
           collides = true
           break
        end
     end
     if collides then
        -- do something here (erase ring[k] from the screen, etc.)
        table.remove(rings, k)
        table.remove(rings, j)
        playerScore = playerScore - (sj + sk)
     end
  end
end

-- remove ring if radius greater than 150
function ringsRemove()
  if (#rings) > 1 then
        for i, v in ipairs(rings) do
          if rings[i].r > 150 then
            playerScore = playerScore - rings[i].score
            table.remove(rings, i)
          end -- end if
        end -- i,v block
      end -- end while loop
  end

function mouseRemove(R)
      local collides = false
      for i, v in ipairs(rings) do
        --[[ collison calculations on all rings in table until a collison
            is detected using pythagoras to calculate distance between
            mouse x,y + a little radius around pointer (rR) and
            circle x,y (centre) + radius]]
          local dx = mX - v.x
          local dy = mY - v.y
          local distCalc = dx * dx + dy * dy
          if distCalc <= (v.r + R)^2 + ringWidth then
              collides = true
              playerScore = playerScore + rings[i].score
          end -- end if distCalc block
      end -- i,v block
    if collides then -- removes ring from table if mouse clicks it
          table.remove(rings, i)

    end -- end if not collides block
  end -- end

-- remove ring if radius greater than ringToBig
function ringsRemove()
if (#rings) > 1 then
  for i, v in ipairs(rings) do
    if rings[i].r + ringWidth > ringToBig then
      playerScore = playerScore - rings[i].score
      table.remove(rings, i)
    end -- end if
  end -- i,v block
end -- end while loop
end

--[[***************************************************************************
******************************************************************************]]
--  local collides = false
function love.load(arg)
    -- body...
  mX = 0 -- set mouse x to 0
  mY = 0 --set mouse y to 0
  --font40 = love.graphics.newFont("BAUHS93.TTf", 40)
  --font18 = love.graphics.newFont("BAUHS93.TTf", 18)
end

function love.draw()
    love.graphics.setBackgroundColor(252, 251, 227, 255) -- sets background colour

    --[[Scoreboard]]
    love.graphics.setColor(0, 0, 0, 255)
  --  love.graphics.setFont(font40)
    love.graphics.print(playerScore, 100,50)

      --[[Debugging]]
--    love.graphics.setFont(font18)
--    love.graphics.print(mX .. " " .. mY, mX, mY) -- mouse position
--    love.graphics.setColor(0, 0, 0, 255) -- temp graphics colour ** Black
--    love.graphics.print(spawntimer) -- prits spawntimer to screen for debugging
      --[[Draw my rings]]
  for i,v in ipairs(rings) do -- draws our rings and changes the colour
      love.graphics.setLineWidth(ringWidth) -- sets ring linewidth
      love.graphics.setColor(rings[i].colr, rings[i].colg, rings[i].colb, rings[i].cola)
      love.graphics.circle('line', v.x, v.y, v.r, 64)
  end

end

function love.update(dt)

  --mouse clicked position
  function love.mousepressed(x, y, button, istouch)
    if button == 1 then
    mX = x
    mY = y
      mouseRemove(10) -- removes circle if clicked mouseRemove(mousePointerRadius)
    end
  end

  if #rings >= 2 then
    collision() -- removes rings that grow and collide
  end

  for i,v in ipairs(rings) do
    --[[grows our rings via the vel set in ringColour then added to rings table when
    the ring is created ]]
    rings[i].r = rings[i].r + rings[i].vel
  end

  ringsRemove() -- rings get to big remove it

  if spawntimer > 0 then  -- countdown to spawn rings if time remaining greater than 0
      spawntimer = spawntimer - dt
      else
      newRing() -- creates new ring if spawntimer runs out
  end

end
regards
Attachments
cClicker.love
(2.34 KiB) Downloaded 138 times
Last edited by Vmpwraith on Tue Aug 08, 2017 8:27 pm, edited 1 time in total.
User avatar
0x72
Citizen
Posts: 55
Joined: Thu Jun 18, 2015 9:02 am

Re: Mouse click weirdness

Post by 0x72 »

In mouseRemove function in line table.remove(rings, i): i variable is always nil because it's not set in this scope. The i variable form the for loop is scoped to the for loop.

table.remove(a, nil) is the same as table.remove(a) is the same as table.remove(a, #a) (docs)

Instead of setting colides = true you can (for example) have col_id = nil and set it to whatever i is during the collision test.

Code: Select all

function mouseRemove(R)
  local col_id = nil  -- change
  for i, v in ipairs(rings) do
    local dx = mX - v.x
    local dy = mY - v.y
    local distCalc = dx * dx + dy * dy
    if distCalc <= (v.r + R)^2 + ringWidth then
      col_id = i  -- change
      playerScore = playerScore + rings[i].score
    end
  end
  if col_id then
    table.remove(rings, col_id) -- change
  end
end
User avatar
ivan
Party member
Posts: 1915
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Mouse click weirdness

Post by ivan »

Furthermore, when you want to remove elements DURING iteration, make sure you are going in reverse:

Code: Select all

-- remove ring if radius greater than ringToBig
function ringsRemove()
  for i = #rings, 1, -1 do
    local v = rings[i]
    if v.r + ringWidth > ringToBig then
      playerScore = playerScore - v.score
      table.remove(rings, i)
    end 
  end
end
Vmpwraith
Prole
Posts: 9
Joined: Thu Jan 15, 2015 12:00 am

Re: Mouse click weirdness

Post by Vmpwraith »

Awsome thankyou 0x72 and Ivan. Cheers for the Doc's link I hadn't realized I wasn't sending it the "i" and just amused it was getting the correct information. Also cheers Ivan it makes sense to go in reverse.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 2 guests