Collision detection between bullets [SOLVED]

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
test
Prole
Posts: 28
Joined: Sun Apr 14, 2019 2:36 pm

Collision detection between bullets [SOLVED]

Post by test » Tue Apr 23, 2019 6:14 pm

I have this code

Code: Select all

for i, v in ipairs(listOfBullets) do v:update(dt) end
how can I check collision between two v's.
Last edited by test on Tue May 07, 2019 7:15 pm, edited 1 time in total.

User avatar
raidho36
Party member
Posts: 1804
Joined: Mon Jun 17, 2013 12:00 pm

Re: Collision detection between bullets

Post by raidho36 » Wed Apr 24, 2019 2:45 am

Code: Select all

for i, v in ipairs(listOfBullets) do 
  v:update(dt)
  for ii, vv in ipairs(listOfBullets) do 
    if vv ~= v and checkCollison(v,vv) then
      resolveCollision(v,vv)
    end
  end
end

test
Prole
Posts: 28
Joined: Sun Apr 14, 2019 2:36 pm

Re: Collision detection between bullets

Post by test » Wed Apr 24, 2019 5:11 pm

Thanks raidho36. It works now but SOMETIMES one bullet is not be destroyed after collision of two bullets. I want both to be destroyed.

Code: Select all

for i, v in ipairs(projectiles) do
		v.x = v.x + v.speed * dt

		for ii = 1, 2 do
			if CheckCollision(v.x, v.y, v.w, v.h, p[ii].x, p[ii].y, p[ii].w, p[ii].h) then
				if ii == v.id then
				else
					table.remove(projectiles, i)
				end
			end
		end

		for ii, vv in ipairs(projectiles) do 
			if vv ~= v and CheckCollision(v.x, v.y, v.w, v.h, vv.x, vv.y, vv.w,vv.h) then
				table.remove(projectiles, i)
				table.remove(projectiles, ii)
			end
		end
	end

User avatar
pgimeno
Party member
Posts: 1690
Joined: Sun Oct 18, 2015 2:58 pm

Re: Collision detection between bullets

Post by pgimeno » Wed Apr 24, 2019 6:49 pm

Removal of two projectiles while looping is a bit more complicated. Best is to defer deletion, so you don't skip any checks. Logically, everything happens after the update; otherwise you might detect a collision between a projectile that is not yet updated and one that is, and that collision would be bogus.

Also, you don't need to loop over the players just to check if the bullet hits the right player. If your player IDs are 1 and 2, then the formula (3 - player_id) will give you the other player.

Code: Select all

-- Update all projectiles at once
for i = 1, #projectiles do
  local v = projectiles[i]
  v.x = v.x + v.speed * dt
end

local deleted = {}
local player_collision = false

-- Check collisions
for i = 1, #projectiles do
  local v = projectiles[i]
  local other_player_id = 3 - v.id
  if CheckCollision(v, p[other_player_id]) then
    deleted[i] = true
    -- insert here the action to inflict damage to the player
  end

  for j = i + 1, #projectiles do
    local vv = projectiles[j]
    if CheckCollision(v, vv) then
      deleted[i] = true
      deleted[j] = true
    end
  end
end

-- Remove obsolete bullets
for i = #projectiles, 1, -1 do
  if deleted[i] then
    table.remove(projectiles, i)
  end
end

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

Re: Collision detection between bullets

Post by ivan » Thu Apr 25, 2019 4:53 am

pgimeno is right, you could remove the elements during iteration, as long as you iterate in reverse:

Code: Select all

for i = #list, 1, -1 do
  for j = i - 1, 1, -1 do
    if checkCollisions(list[i], list[j]) then
       table.remove(list, i)
       table.remove(list, j)
       break
    end
  end
end

User avatar
pgimeno
Party member
Posts: 1690
Joined: Sun Oct 18, 2015 2:58 pm

Re: Collision detection between bullets

Post by pgimeno » Thu Apr 25, 2019 9:40 am

My concern with not deferring removal is this:

Imagine you have three bullets colliding. To me, logically all three should be removed. But if they are removed in pairs, one of them could survive.

Example in ASCII art:

Code: Select all

    +--------+
    |   3    |
    |        |
+---+---+  +-+-----+
|   |   |  | |     |
|   +---+--+-+     |
| 1     |  |    2  |
|       |  |       |
+-------+  +-------+
In that situation, if you loop backwards and find that 2 and 3 are colliding, and you remove them, you won't find the collision between 1 and 3, therefore 1 will not be removed. Also, the one that won't be removed will depend on the insertion order of bullets, which feels wrong to me.

The only solution I can imagine for that problem, as I said, is deferring the deletion until all checks are finished.

Post Reply

Who is online

Users browsing this forum: Exabot [Bot], Google [Bot] and 8 guests