Collision detection and many objects

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
User avatar
Ertain
Citizen
Posts: 55
Joined: Fri Nov 19, 2010 9:38 pm
Location: Texas, U.S.A.

Collision detection and many objects

Post by Ertain »

Hello again, LÖVErs.

In my little game I'm going to have many things flying across the screen. I have implemented a crude collision detection system but it is poor. I have looked into using the Hardon Collider, but what I need to do is go through a list of many objects (not software objects, but more like entries). So I need to check to see if two entries have hit, and if so, which ones. I shall show you in simple code.

Code: Select all

enemies = {
  enemy1 = {isHit = false, hp = 10},
  enemy2 = {isHit = false, hp = 10},
  enemy3 = {isHit = false, hp = 10}
}
-- This table would contain a ton of bullets.
bullets = {
 bullet1 = { hasHit = false, target = "player"},
 bullet2 = {hasBit = false, target = "enemy"},
 bullet3 = {hasHit = false, target = "player"}
}

function on_colliding(object_one, object_two)
  if hasHit(object_one, object_two) then
    if object_one.target == "player" and object_two == enemy1 then
       enemy1.isHit = true
    end
  end
end
This is, again, very simplified. The "enemies" table is large and has a number of entries to it. I'm trying to figure out if a bullet from the "bullets" table has collided with an enemy from the enemies table. If so I need to determine which bullet has hit which enemy. In the Hardon Collider I can only think of using shape:collidesWith() in many places. But I would need to first define which bullets are which (or just use points in space).

Jeez, I don't even know where to begin with this. :?
Booted, suited, and ready to get executed.
User avatar
thelinx
The Strongest
Posts: 857
Joined: Fri Sep 26, 2008 3:56 pm
Location: Sweden

Re: Collision detection and many objects

Post by thelinx »

Use shape groups and global callbacks.

This is what I currently have for my bullet hell game:

Code: Select all

-- bullet constructor, automatically creates a shape
  -- unrelated stuff removed
  table.insert(bullets, self) -- insert the bullet into the global bullets table
  self.id = #bullets
  hardoncollider.addToGroup("hazard", self.shape) -- this makes the bullet a "hazard" to the player.
  self.shape.bulletId = self.id
The player code looks similar, and the player shape is put in a "player" group.

This is the start-collide function I have:

Code: Select all

function(dt, a, b, x, y)
  if (a._groups.player and b._groups.hazard) or (b._groups.player and a._groups.hazard) then -- if the colliding objects are player and hazard
    player:kill() -- kill the global object player.
    return
  end
end
I hope this was of any use!
User avatar
Ertain
Citizen
Posts: 55
Joined: Fri Nov 19, 2010 9:38 pm
Location: Texas, U.S.A.

Re: Collision detection and many objects

Post by Ertain »

These shapes intrigue me. But I already have tables which contain the bullet data as well as the player's data. So I have to some how integrate the object data to those tables.

Code: Select all

player = {
  image = "playerImage.png",
  x = 120, -- The coordinates of the player's position during the game.
  y = 120,
  hp = 10
}
Could I add the shape object to the table? For example, could I try setting:

Code: Select all

player.shape = shapes.CircleShape(120, 120, 32)
-- This is for moving the shape along with the player.
function onPlayerMovement(move_x, move_y)
  player.shape:move(move_x, move_y)
end
In the init() function for the Hardon Collider could I set the starting collision function like this?

Code: Select all

hardoncollider.init(100, startColliding(dt,thing1, thing2))

enemy = {
 x = 230,
 y = 230,
 hasBeenHit = false
}

enemy.shape = shapes.CircleShape(230, 230, 32)
enemy.shape.enemyId = "enemy1"

function startColliding(changeInTime, thing1, thing2)
  if (thing1._group.enemy and thing2._group.bullet) or (thing1._group.bullet and thing2._group.enemy) then
    if thing1._group.enemy.enemyId == "enemy1" then
      enemy.hasBeenHit = true
    end
  end
end
Booted, suited, and ready to get executed.
User avatar
thelinx
The Strongest
Posts: 857
Joined: Fri Sep 26, 2008 3:56 pm
Location: Sweden

Re: Collision detection and many objects

Post by thelinx »

Ertain wrote:

Code: Select all

function startColliding(changeInTime, thing1, thing2)
  if (thing1._group.enemy and thing2._group.bullet) or (thing1._group.bullet and thing2._group.enemy) then
    if thing1._group.enemy.enemyId == "enemy1" then
      enemy.hasBeenHit = true
    end
  end
end
First: It's ._groups, not ._group.
Next:

Code: Select all

function startColliding(changeInTime, thing1, thing2)
  if (thing1._groups.enemy and thing2._groups.bullet) or (thing1._groups.bullet and thing2._groups.enemy) then -- we know know that it is a bullet and an enemy colliding... but which one is the enemy?
    local enemy = thing1._groups.enemy and thing1 or thing2 -- ternary operations!
    enemy.hasBeenHit = true
  end
end
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: Collision detection and many objects

Post by vrld »

Ertain wrote:Could I add the shape object to the table?
Yes, you could. But if you want to use the collision callbacks, you will have to use hardoncollider.addCircle() instead of Shapes.CircleShape.
Ertain wrote:In the init() function for the Hardon Collider could I set the starting collision function like this?

Code: Select all

hardoncollider.init(100, startColliding(dt,thing1, thing2))
No. startColliding(dt, thing1, thing2) just invokes the function startColliding. That is not what you want. This is:

Code: Select all

hardoncollider.init(100, startColliding)
Just to be clear: The collision callbacks will only work, if you use the add* function of the main module. Using the shape constructors of the Shapes submodule will not register them with the collision detection system.
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine
User avatar
Ertain
Citizen
Posts: 55
Joined: Fri Nov 19, 2010 9:38 pm
Location: Texas, U.S.A.

Re: Collision detection and many objects

Post by Ertain »

Ah crap. I've run into an error in the hardon collider code.

When I tried to run my test code (after a generous amount of debugging) I get the error "attempt to perform arithmetic on field '_radius' (a nil value)". I know for darn sure I went through my code with a fine tooth comb.
Booted, suited, and ready to get executed.
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: Collision detection and many objects

Post by vrld »

Could you show the traceback and code that fails? This looks like an error in HardonCollider (which i would like to fix)
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine
User avatar
Ertain
Citizen
Posts: 55
Joined: Fri Nov 19, 2010 9:38 pm
Location: Texas, U.S.A.

Re: Collision detection and many objects

Post by Ertain »

Here's the full traceback.

Code: Select all

Error: [string "libs/hardoncollider/shapes.lua"]:209: attempt to perform arithmetic on field '_radius' (a nil value)
stack traceback:
        [string "libs/hardoncollider/shapes.lua"]:209: in function 'collidesWith'
        [string "libs/hardoncollider/init.lua"]:233: in function 'update'
        [string "libs/hardoncollider/init.lua"]:194: in function 'combined_update'
        [string "libs/hardoncollider/init.lua"]:211: in function 'update'
        [string "boot.lua"]:314: in function <[string "boot.lua"]:302>
        [C]: in function 'xpcall'
As for the code that fails it's a bit messy. Because this was before the class libraries were fully mature I had to come up with my own OO stuff. So I tried as best I can to write the classes. The scope of them may not be the case, but you never know. In the love.load() function I load the collider as normal:

Code: Select all

   -- Load the collider.
   lhc.init(100, start_colliding)
   -- Load the enemy shapes.
   horde.loadEnemyShapes()  
   -- Add the enemy shapes to the proper group.
   horde.addEnemiesToCollisionGroup()
   -- Auto update the Hardon Collider.
   lhc.setAutoUpdate(30)
The "loadEnemyShapes()" function uses the addCircle() method to attach a circle to the enemy tables. The "addEnemiesToCollisionGroup()" function associates the enemies with the "enemy" group (using the addToGroup() function). In the "loadEnemyShapes()" function the radius of the circles is defined, so I can't figure out where exactly the error is coming from.
Booted, suited, and ready to get executed.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 3 guests