Collision detection problem

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
chingydongy
Prole
Posts: 5
Joined: Sat Jan 20, 2018 4:56 pm

Collision detection problem

Post by chingydongy » Wed Feb 21, 2018 8:52 pm

Hello everyone, I have been on this code for the past few months, since I never have the time to work on it, I mostly left it as it is, with only small improvements anytime I can get my hands on it. My question here is, why in all hell isn't the collision detection working with the player/enemy as it is with bullet/enemy? Does it have to do with the fact that both the enemies and bullets are inserted into a table, and the player isn't?
Anyway, here's the code, everything else works fine, but it's just the collcheck(dt) parts that are making me bash my head on a wall.

Code: Select all

require("player")
enemy = {}
enemySpeed = 80
math.randomseed(os.time())
score = 0
enemyNumber = 5
killTimeStart = 10 -- time limit/ level
killTime = killTimeStart
maxw, maxh = love.window.getDesktopDimensions(display)
timer = 0
spawnTime = 5 -- delay of spawn in seconds
round = 4 -- this is the amount of time that is multiplied by delta time (1s) to add to time allowed for the next round
function enemySpawn(x,y,w,h)
   for i = 1, enemyNumber do
      enemy[#enemy + 1] = {x = math.random(0 and player.x - 320, player.x + 300 and maxw - 64), y = math.random(0 and player.y - 320, player.y + 300 and maxh - 64), w = 64, h = 64}
   end
    if #enemy <= enemyNumber then
      enemyNumber = enemyNumber + math.random(1,3)
   end
   angery = love.graphics.newImage("enemy.png")
end
function collcheck(dt)
   for i,v in ipairs(enemy) do      --collision check for bullet vs enemy and player vs enemy
    for a,b in ipairs(bullet) do
      if b.x < v.x+64 and b.y < v.y+64 and b.x > v.x-8 and b.y > v.y-8 then
         table.remove(enemy, i)
         table.remove(bullet, a)
         doink:play()
         score = score + 1
      end
   end
 end
 for i,v in ipairs(player) do      --collision check for bullet vs enemy and player vs enemy
    for a,b in ipairs(enemy) do
      if v.x < b.x+64 and v.y < b.y+64 and v.x > b.x-20 and v.y > b.y-20 then
         table.remove(enemy,i)
         love.event.quit()
      end
   end
 end
end
function enemy:update(dt)
   killTime = killTime - dt
   		if killTime < 0 and #enemy > 0 then
      		killTime = killTimeStart
      	end
      	if killTime >=0 and #enemy == 0 then -- if there's remaining kill time and there are no enemies on the screen, increase the round time by Xs
         	killTime = killTime + round*dt -- done
   		end
   if #enemy == 0 then -- if all enemies are dead, start the timer for the next round (5s)
      timer = timer + dt
      if timer > spawnTime then
         enemySpawn()
         timer = 0
      end
   end
   collcheck()
end
function enemy:draw()
	for i,v in ipairs(enemy) do
		love.graphics.draw(angery, v.x, v.y)
	end
end
function enemymove(dt)
   for i,v in ipairs(enemy) do
       enemyDirectionX = player.x - v.x
       enemyDirectionY = player.y - v.y
       distance = math.sqrt(enemyDirectionX * enemyDirectionX + enemyDirectionY * enemyDirectionY)
   end
  
   if distance ~= 0 then
     for i,v in ipairs(enemy) do
        v.x = v.x + enemyDirectionX / distance * enemySpeed * dt
        v.y = v.y + enemyDirectionY / distance * enemySpeed * dt
     end
   end
end

The important part is:

Code: Select all

function collcheck(dt)
   for i,v in ipairs(enemy) do      --collision check for bullet vs enemy and player vs enemy
    for a,b in ipairs(bullet) do
      if b.x < v.x+64 and b.y < v.y+64 and b.x > v.x-8 and b.y > v.y-8 then
         table.remove(enemy, i)
         table.remove(bullet, a)
         doink:play()
         score = score + 1
      end
   end
 end
 for i,v in ipairs(player) do      --collision check for bullet vs enemy and player vs enemy
    for a,b in ipairs(enemy) do
      if v.x < b.x+64 and v.y < b.y+64 and v.x > b.x-20 and v.y > b.y-20 then
         table.remove(enemy,i)
         love.event.quit()
      end
   end
 end
end
I don't know what to do at this point, as everything else works fine. Thanks in advance.

lachlaan
Prole
Posts: 30
Joined: Sun Jun 30, 2013 7:23 pm

Re: Collision detection problem

Post by lachlaan » Thu Feb 22, 2018 2:30 am

What's not working about it specifically? As far as I can see you're removing the enemy at position i in the table instead of position a, which could be problematic. It should still quit though if it triggers. The question is does it throw an error at all, and also how is the player position saved, and is the player info saved in a table with the format the ipairs iterator expects? The table thing could helped, making the player a variable in a table you iterate through. As well as deleting the right enemy if you care about that.

User avatar
ivan
Party member
Posts: 1291
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Collision detection problem

Post by ivan » Thu Feb 22, 2018 7:28 am

If you want to remove elements from a table during iteration, you have to iterate in reverse:

Code: Select all

for i = #list, 1, -1 do
  if some condition then
    table.remove(list, i)
  end
end

PGUp
Citizen
Posts: 66
Joined: Fri Apr 21, 2017 9:17 am

Re: Collision detection problem

Post by PGUp » Thu Feb 22, 2018 7:50 am

Spot it! Look at your code again.. it should be table.remove(enemy, a) instead of table.remove(enemy, i) in collision check between player and enemy, since the variable for the index is a, Also iterate backward so you won't see the glitchy enemy movement
really want to post on code doodles thread :/

chingydongy
Prole
Posts: 5
Joined: Sat Jan 20, 2018 4:56 pm

Re: Collision detection problem

Post by chingydongy » Thu Feb 22, 2018 4:01 pm

Well, after going through all of your guys advice, I looked at my player.lua, where the player table isn't inserted in the same way as the bullets and the enemies are through said tables (the player was declared as a player = {x,y,w,h}, not as player = {} with a table.insert() afterwards). Of course, this meant that I would have to make the whole for i,v in ipairs(player) thing go all around the code where the player.x or player.y was and replace with v. Now there's proper collision detection and the game shuts off when I hit one. Thanks again everyone :D

Post Reply

Who is online

Users browsing this forum: Google [Bot] and 9 guests