How to indentify the into object in a collision?


In my project i have an array of Ring objects, that the actor can collide with (to “collect” them).

I’ve managed to collide the actor with the rings and that collision adds an entry to the CollisionHandlerQueue.

But now i must identify the ring so i can delete it when the actor “collects it”.

So, i tried adding a task like this:

   for i in range(self.queue.getNumEntries()):
      entry = self.queue.getEntry(i)
      # i have 5 rings at the moment
      # this will become dynamic later
      for i in range (0, 5):
         if self.ring[i].colNode == entry.getIntoNode():
            print "Collided with ring " + self.ring[i].index
            print "Collided, cant identify"

But all it prints is “Collided, cant identify” when i enter the ring’s collision sphere.

So comparing self.ring[i].colNode with entry.getIntoNode() is wrong.

What should i be comparing?
Thank you in advance.

This is my Ring class:

from direct.showbase.Loader import Loader
from pandac.PandaModules import *

class Ring():
    def __init__(self, x, y, index):
        self.model = loader.loadModel("assets/models/ring/torus")
        self.model.setHpr(90, 0, 90)
        self.model.setColor(255, 255, 0)
        self.model.setScale(1, 1, 1)

        self.index = index

        self.colSphere = CollisionSphere(0, 0, 0, 1)
        self.colNode = self.model.attachNewNode(CollisionNode("ring_" + str(index)))

What you are calling colNode is actually the NodePath. So you could compare against getIntoNodePath() and you should get a match.

Most people use the tag system, though, instead of running a loop.

At setup, do:

self.ring[i].colNode.setTag('ring', str(i))

Then on collision, do:

i = int(entry.getIntoNodePath().getNetTag('ring'))


That’s exactly what i need. I will try it soon.

Thank you very much.

Yeah, that works flawlessly. I’m now trying to understand the tag approach, as you suggested.

Ok, here you set the tag for the first ring as ‘ring0’.

And now here you are looking for the ‘ring’ tag. Shouldn’t it be ‘ring0’? How does it work?

Since you’re already helping me with this part, i would like to ask you another thing:

Now that i’ve identified the ring i collided into, how can i “remove” it from the game?
I was thinking that i should just remove the collision from it (so it becomes a ghost) and taking it off from render (so it doesn’t even show up).

What do you think?

Thank you very much!

self.ring[i].colNode.setTag('ring', str(i))

That sets a tag called “ring” to the value “0” (assuming i == 0). It does not create a tag called “ring0”.

When you later call getTag/getNetTag(“ring”), it’ll return “0”.

Oh, i got it. It’s a tag with associated with a value.
Can you help me with my other question?

Thank you very much, you are being really helpful.

By the way, sometimes when the character is colliding, because the character moves really fast, the collision is not even detected (at least not printed in the console).

My collision test:

def collisionTest(self, task):
        for i in range(self.queue.getNumEntries()):
            entry = self.queue.getEntry(i)
            # Rings
            if tagStr != "":
                print "Collided with ring " + tagStr
                # todo: code to delete the ring
                # todo: score++
        return task.cont

I even tried setting priority of the task to 1:

taskMgr.add(self.collisionTest, "collisionTest", priority = 1)

So i have 5 rings in a row, i walk through them, and it prints something like:

Collided with ring 0
Collided with ring 0
Collided with ring 1
Collided with ring 3
Collided with ring 3
Collided with ring 4
Collided with ring 4

In this example, it was so fast that it didn’t have time to detect the collision.

Do you know any solution for this? Once again, thank you very much.

See “rapidly-moving objects” in the manual.