Multiple types of collisions?

Hello yet again;

I’m trying to make a collision at the end of my game to let the player know they had won. Just a simple print on the screen when they hit it. However, my game is a maze, and I already have collisions set up for that. Ideally, the user would still be able to move past this collision at the end, but I’m not sure how to do it.
No matter how I mess with my code, I can’t get it to work the way I want it to. Does anyone have any sample code on having multiple different collisions that don’t have the same function? It would be very helpful.
Thank you!

-Ally

First of all, am I correct in presuming that you’re using Panda’s built-in collision system, and specifically a CollisionHandlerPusher (or CollisionHandlerFluidPusher)? If not, what are you using?

If so, however, then I believe that you should be able to achieve your goal by first making the collision solid for your “end object” intangible via CollisionSolid’s “setTangible” method, then registering an event for it with your collision handler, as described here (under “CollisionHandlerEvent”), and shown here. (Note: The previous two links refer to CollisionHandlerEvent–but as CollisionHandlerPusher (and -FluidPusher) inherit from CollisionHandlerEvent, the information given there applies to them, too, I believe.)

Note that, as described in the second-last link above, you can construct your “event string” such that it applies only to those objects to which you want it to apply. You can also use bitmasks to control which objects collide with which others, but my guess is that this isn’t quite what you’re looking for.

Ah, thank you so much! But, oddly enough, I have my program set up pretty much how the example does, and it’s still acting strange.
I have two collisions set up, one for regular collisions on walls and one for my end game, which, right now, I’m just testing by making it print “END”. Problem is, “END” will print even when I am not hitting the specified collision solid. It prints when I hit all the walls, and last time I ran it didn’t print anything for the collision I wanted it to. I’m really new to programming, so I think I’ve probably just got something set up wrong. Here is all my code, maybe you can see what I’m doing wrong?

from panda3d.core import loadPrcFileData
# Configure the parallax mapping settings (these are just the defaults)
loadPrcFileData("", "parallax-mapping-samples 3")
loadPrcFileData("", "parallax-mapping-scale 0.1")

from direct.gui.DirectGui import *
from panda3d.core import WindowProperties
from panda3d.core import Filename,Shader
from panda3d.core import AmbientLight,PointLight
from panda3d.core import TextNode
from panda3d.core import Point3,Vec3,Vec4
from pandac.PandaModules import *
from direct.showbase.ShowBase import ShowBase
from direct.task.Task import Task
from direct.actor.Actor import Actor
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
from direct.filter.CommonFilters import *
import sys,os

###
from panda3d.core import TransparencyAttrib
###

# Function to put instructions on the screen.
def addInstructions(pos, msg):
    return OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-1.3, pos), align=TextNode.ALeft, scale = .05)

# Function to put title on the screen.
def addTitle(text):
    return OnscreenText(text=text, style=1, fg=(1,1,1,1),
                        pos=(1.3,-0.95), align=TextNode.ARight, scale = .07)

class BumpMapDemo(ShowBase):

    def __init__(self):
		
        ShowBase.__init__(self)
        base.cTrav = CollisionTraverser()
        base.cTrav.setRespectPrevTransform(True)
        collisionHandler = CollisionHandlerPusher()
        polygonMask = BitMask32.bit(1)
        sphereMask = BitMask32.bit(1)
        
        collisionHandler.addInPattern('%fn-into-%in')
        collisionHandler.addOutPattern('%fn-out-%in')
        
        self.filters = CommonFilters(base.win, base.cam)
        filterok = self.filters.setBloom(blend=(0,0,0,1), desat=-0.5, intensity=5.0, size="small")
        if (filterok == False):
            addTitle("Toon Shader: Video card not powerful enough to do image postprocessing")
            return
        self.glowSize=1

        # Check video card capabilities.

        if (base.win.getGsg().getSupportsBasicShaders() == 0):
            addTitle("Bump Mapping: Video driver reports that shaders are not supported.")
            return
            
        self.keyMap = {"camera-forward":0}
        
        # Menu Screen
        self.myImage=OnscreenImage(image = 'menuscreen.png', pos = (0, 0, 0))
        self.myImage.setTransparency(TransparencyAttrib.MAlpha)
        self.myImage.reparentTo(render2d)
        
        maps = loader.loadModel('start_button.egg')
        self.startbutton = DirectButton(geom = (maps.find('**/startbutton'),
                         maps.find('**/startbutton_click'),
                         maps.find('**/startbutton_hover')),command = self.startbuttonevent)
        self.startbutton["frameColor"] = (0,0,0,0)
        self.startbutton.setScale(0.2,0.2,0.2)
        self.startbutton.setPos(0.7,0,0.6)
        
        maps = loader.loadModel('quit_button.egg')
        self.quitbutton = DirectButton(geom = (maps.find('**/quitbutton'),
                         maps.find('**/quitbutton_click'),
                         maps.find('**/quitbutton_hover')),command = self.quitbuttonevent)
        self.quitbutton["frameColor"] = (0,0,0,0)
        self.quitbutton.setScale(0.2,0.2,0.2)
        self.quitbutton.setPos(0.7,0,0.4)
        
        # Dragon Story Pop-up
        #self.myImage=OnscreenImage(image = 'Ryujin Back Story.png', pos = (0, 0, 0))
        #self.myImage.setTransparency(TransparencyAttrib.MAlpha)
        ###imageObject.destroy()

        # Post the instructions
        self.title = addTitle("shitty labyrinth")
        self.inst1 = addInstructions(0.95, "Press ESC to exit")
        self.inst2 = addInstructions(0.90, "Move mouse to rotate camera")
        self.inst3 = addInstructions(0.85, "Left mouse button: Move forwards")
        self.inst4 = addInstructions(0.80, "Right mouse button: Move backwards")
        
        self.sky = loader.loadModel("models/leafplant2_color")
        self.sky.reparentTo(render)
        self.sky.setHpr(0, 0, 0)
        self.sky.setPos(20,-62,0)
        
        
        self.sky = loader.loadModel("models/sky")
        self.sky.reparentTo(render)
        self.sky.setHpr(0, 0, 0)
        self.sky.setPos(-300,0,70)
        
        
        self.crystal = loader.loadModel("models/crystals")
        self.crystal.reparentTo(render)
        self.crystal.setScale(0.5,0.5,0.5)
        self.crystal.setHpr(0,-30,30)
        self.crystal.setPos(-11,-68,1)
        
        self.mushroom = loader.loadModel("models/mushroom")
        self.mushroom.reparentTo(render)
        self.mushroom.setScale(0.3,0.3,0.3)
        self.mushroom.setPos(80,-62,5)

        self.room = loader.loadModel("models/texturemesh")
        #texture = loader.loadTexture("models/fieldstone-c.jpg")
        #self.room.setTexture(texture)
        #texture.setWrapU(Texture.WM_mirror)
        #texture.setWrapV(Texture.WM_mirror)
        self.room.setHpr(0,0,0)
        self.room.setScale(3.0,3.0,3.0)
        self.room.reparentTo(render)
        roomCollider = self.room.find("**/polygons")
        roomCollider.node().setIntoCollideMask(sphereMask)
        
        
        
        self.ball = loader.loadModel("models/ball")
        ballCollider = self.camera.attachNewNode(CollisionNode('cnode'))
        ballCollider.node().addSolid(CollisionSphere(0, 0, 0, 2))
        ballCollider.node().setFromCollideMask(sphereMask)
        base.cTrav.addCollider(ballCollider, collisionHandler)
        collisionHandler.addCollider(ballCollider, self.camera, base.drive.node())
        
        DO = DirectObject()
        DO.accept('cnode-into-polygons', self.collideEventIn)

        
        #Collision that ends the game
        quad = CollisionPolygon( Point3(0,10,0),Point3(0,10,10),Point3(0,0,10),Point3(0,0,0))
        quadPath = self.room.attachNewNode(CollisionNode('qnode'))
        quadPath.node().addSolid(quad)
        quadPath.node().setIntoCollideMask(polygonMask)
        quadPath.node().setFromCollideMask(polygonMask)
        base.cTrav.addCollider(quadPath, collisionHandler)
        collisionHandler.addCollider(quadPath, self.camera, base.drive.node())
        quadPath.setPos(-30, -3, 0)
        quadPath.show()
        
        DIR = DirectObject()
        DIR.accept('cnode-into-polygons', self.endGameCollision)
        
        mySound = base.loader.loadSfx("cavesound.ogg")
        mySound.play()
        mySound.setVolume(0.5)
        mySound.setLoop(1)
        mySound.setLoopCount(0)

        #Add a light to the scene.
        self.light = render.attachNewNode("lightpivot")
        self.light.setPos(-50,-25,75)
        #self.light.hprInterval(10,Point3(360,0,0)).loop()
        plight = PointLight('plight')
        plight.setColor(Vec4(1, 1, 1, 1))
        plight.setAttenuation(Vec3(0.7,0.05,0))
        plnp = self.light.attachNewNode(plight)
        plnp.setPos(45, 0, 0)
        self.room.setLight(plnp)
        
        # Add an ambient light
        alight = AmbientLight('alight')
        alight.setColor(Vec4(0.2, 0.2, 0.2, 1))
        alnp = render.attachNewNode(alight)
        self.room.setLight(alnp)

        # create a sphere to denote the light
        sphere = loader.loadModel("models/sphere")
        sphere.reparentTo(plnp)

        # load and apply the shader.  This is using panda's
        # built-in shader generation capabilities to create the
        # shader for you.  However, if desired, you can supply
        # the shader manually.  Change this line of code to:
        #   self.room.setShaderInput("light", plnp)
        #   self.room.setShader(Shader.load("bumpMapper.sha"))
        self.room.setShaderAuto()

        self.shaderenable = 1
        
    def startbuttonevent(self):
        self.myImage.detachNode()
        self.startbutton.detachNode()
        self.quitbutton.detachNode()
        
		# Make the mouse invisible, turn off normal mouse controls
        base.disableMouse()
        props = WindowProperties()
        props.setCursorHidden(True)
        base.win.requestProperties(props)

        # Set the current viewing target
        self.focus = Vec3(80,-62,10)
        self.heading = 180
        self.pitch = 0
        self.mousex = 0
        self.mousey = 0
        self.last = 0
        self.mousebtn = [0,0,0]
        
        # Start the camera control task:
        sound = self.loader.loadSfx("running.ogg")
        taskMgr.add(self.controlCamera, "camera-task")
        self.accept("escape", sys.exit, [0])
        self.accept("mouse1", self.setMouseBtn, [0, 1])
        self.accept("mouse1-up", self.setMouseBtn, [0, 0])   
        self.accept("mouse2", self.setMouseBtn, [1, 1])
        self.accept("mouse2-up", self.setMouseBtn, [1, 0])
        self.accept("mouse3", self.setMouseBtn, [2, 1])
        self.accept("mouse3-up", self.setMouseBtn, [2, 0])
        self.accept("enter", self.toggleShader)
        self.accept("j", self.rotateLight, [-1])
        self.accept("k", self.rotateLight, [1])
		
    def quitbuttonevent(self):
		sys.exit(0)
		
    def collideEventIn(self,entry):
		colliderINTO = entry.getIntoNodePath().getParent()
		colliderFROM = entry.getFromNodePath().getParent()
		print "hit!"
			
    def endGameCollision(self,entry):
		#Find some way to get the screen to fade out and quit, while displaying "END" or something
		colliderINTO = entry.getIntoNodePath().getParent()
		colliderFROM = entry.getFromNodePath().getParent()
		print "END"
        
    def setKey(self, key, value):
		self.keyMap[key] = value
        
    def setMouseBtn(self, btn, value):
        self.mousebtn[btn] = value
        

    def rotateLight(self, offset):
        self.lightpivot.setH(self.lightpivot.getH()+offset*0)

    #def rotateCam(self, offset):
        #self.heading = self.heading - offset*10
        
    def toggleGlow(self):
        self.glowSize = self.glowSize + 1
        if (self.glowSize == 4): self.glowSize = 0
        self.filters.setBloom(blend=(0,0,0,1), desat=-0.5, intensity=8.0, size=self.glowSize)

    def toggleShader(self):
        self.inst5.destroy()
        if (self.shaderenable):
            self.inst5 = addInstructions(0.75, "Enter: Turn bump maps On")
            self.shaderenable = 0
            self.room.setShaderOff()
        else:
            self.inst5 = addInstructions(0.75, "Enter: Turn bump maps Off")
            self.shaderenable = 1
            self.room.setShaderAuto()

    def controlCamera(self, task):
        
        md = base.win.getPointer(0)
        x = md.getX()
        y = md.getY()
        if base.win.movePointer(0, 100, 100):
            self.heading = self.heading - (x - 100) * 0.2
            self.pitch = self.pitch - (y - 100) * 0.2
            
        if (self.pitch < -45): self.pitch = -45
        if (self.pitch >  45): self.pitch =  45
        self.camera.setHpr(self.heading,self.pitch,0)
        dir = self.camera.getMat().getRow3(1)
        elapsed = task.time - self.last
        if (self.last == 0): elapsed = 0
        if (self.mousebtn[0]):
            self.focus = self.focus + dir * elapsed*30
            
        if (self.mousebtn[1]) or (self.mousebtn[2]):
            self.focus = self.focus - dir * elapsed*30
            
        self.camera.setFluidPos(self.focus - (dir*5))
        if (base.camera.getZ() <   8.0): base.camera.setZ(  8)
        if (base.camera.getZ() >  400.0): base.camera.setZ( 400)
        
        if (self.keyMap["camera-forward"]!=0):
			self.camera.setFluidPos(self.camera.getPos + 100)
        
        self.focus = self.camera.getPos() + (dir*5)
        self.last = task.time
        
        return Task.cont
        
        


t = BumpMapDemo()

run()

Okay, that’s a fair bit of code to comb through, so I may well be missing something. I might be better able to help if you were to just show me the sections related to collision. ^^;

At a glance, however, I think that you may be overcomplicating things; in particular, why do you create two DirectObjects? For one thing, if I’m not much mistaken, your “BumpMapDemo” class inherits form ShowBase, which in turn inherits from DirectObject, so you already have one DirectObject instance that can accept events in your “BumpMapDemo” class itself…

Another question: you seem to be treating your “end” object as a “from”/“active” object–an object that collides with things, rather than something that is collided with–why is this?

Finally, I think that I may have found the root of the current problem in this line:

        DIR.accept('cnode-into-polygons', self.endGameCollision)

Form what I see in your code, “polygons” is the name given to your walls, “cnode” is the name given to your camera collider, and “qnode” is the name given to your “end” object. The above line specifies that an event be fired when your camera collides with a wall–what you presumably want is an event that fires when your camera collides with your “end” object…

Sorry, I’m really new to all this. haha
I had help from my TA (this videogame is for a college course) with the collisions, and he didn’t really explain anything to me. So I don’t completely know how to fix the things you’re talking about. Could you show me? Here are the parts for collisions I think are important…


class BumpMapDemo(ShowBase):

    def __init__(self):
		
        ShowBase.__init__(self)
        base.cTrav = CollisionTraverser()
        base.cTrav.setRespectPrevTransform(True)
        collisionHandler = CollisionHandlerPusher()
        polygonMask = BitMask32.bit(1)
        sphereMask = BitMask32.bit(1)
        
        collisionHandler.addInPattern('%fn-into-%in')
        collisionHandler.addOutPattern('%fn-out-%in')

        self.room = loader.loadModel("models/texturemesh")
        self.room.setHpr(0,0,0)
        self.room.setScale(3.0,3.0,3.0)
        self.room.reparentTo(render)
        roomCollider = self.room.find("**/polygons")
        roomCollider.node().setIntoCollideMask(sphereMask)
        
        
        
        self.ball = loader.loadModel("models/ball")
        ballCollider = self.camera.attachNewNode(CollisionNode('cnode'))
        ballCollider.node().addSolid(CollisionSphere(0, 0, 0, 2))
        ballCollider.node().setFromCollideMask(sphereMask)
        base.cTrav.addCollider(ballCollider, collisionHandler)
        collisionHandler.addCollider(ballCollider, self.camera, base.drive.node())
        
        DO = DirectObject()
        DO.accept('cnode-into-polygons', self.collideEventIn)

        
        #Collision that ends the game
        quad = CollisionPolygon( Point3(0,10,0),Point3(0,10,10),Point3(0,0,10),Point3(0,0,0))
        quadPath = self.room.attachNewNode(CollisionNode('qnode'))
        quadPath.node().addSolid(quad)
        quadPath.node().setIntoCollideMask(polygonMask)
        quadPath.node().setFromCollideMask(polygonMask)
        base.cTrav.addCollider(quadPath, collisionHandler)
        collisionHandler.addCollider(quadPath, self.camera, base.drive.node())
        quadPath.setPos(-30, -3, 0)
        quadPath.show()
        
        DIR = DirectObject()
        DIR.accept('cnode-into-polygons', self.endGameCollision)
        
    def collideEventIn(self,entry):
		colliderINTO = entry.getIntoNodePath().getParent()
		colliderFROM = entry.getFromNodePath().getParent()
		print "hit!"
			
    def endGameCollision(self,entry):
		#Find some way to get the screen to fade out and quit, while displaying "END" or something
		colliderINTO = entry.getIntoNodePath().getParent()
		colliderFROM = entry.getFromNodePath().getParent()
		print "END"
run()

Ah, that’s easier to look through–thank you. :slight_smile:

As to showing you, I’ll try, but I’d rather not just give you a fully-functional example–I think that doing so would help you less than teaching you enough that you can make the changes yourself.

First, you’ve said that you’re new to programming–do you know about inheritance?

Second, I’m going to re-iterate one of my previous questions: why did you create two DirectObject instances (“DO” and “DIR”, I believe that you’ve called them)–I presume that you had some reason for doing so, and that reason might help me to determine what to tell you.

Third, I mentioned “from” objects; in case you’re not familiar with the concept, let me explain that a little further: Panda separates collision objects into two types: “from” objects and “into” objects–that is, objects that collide and objects that are collided with, or actively-colliding objects and passive objects. For performance reasons, it can be a good idea to limit the number of active/“from” objects that you use, and certain types of collision shape don’t work at all as “from” objects, or only work with certain other types. (See the bottom of this page for information on which object types may collide as “from” objects with which others.)

If I recall correctly, “into” objects don’t have to be registered with the collision traverser or handler–only “from” objects should be added.

Finally, did you look at what I said about the line that I quoted?

I do not know about inheritance, what is it?

I didn’t have a reason for creating a second DirectObject, I was just trying to create a second collider from what my TA had written, and I don’t know how anything works so I thought I needed it. Haha

Yes, I read a little about from and into objects, and that’s about the extent to which I understand collisions. But that does make it a bit more clear, I’ll try to look through and see what I can change in terms of that.

And yes, that was helpful! That was just something I overlooked when I was copy and pasting to make my second collision. It stopped printing “END” when I hit walls, but now it doesn’t say anything at all when I hit my collider at the end. I don’t think I changed it to the right thing, I was sort of just messing around with it. Is that line correct now, or no?

Heh, I think that these may be the root cause of your problem. :stuck_out_tongue:

More seriously, however, “inheritance” in this context is part of “object-oriented” programming. I’m hesitant to attempt a full description here–it’s a topic that may call for a better lesson than this brief post, and I don’t want to unintentionally mislead you with a description that doesn’t do the subject justice, or that fails to account for what you have and haven’t yet been taught. In short, however, “inheritance” describes a relationship between two classes: if class A inherits from class B, that means that class A can be considered to be a variant or more specific version of class B. Any individual object of class A is also an object of class B. For example:

  • Presume that we have a class “Animal”.
  • Further presume that we also have a class “Cat” that inherits from the class “Animal”.
  • Finally, let’s say that we have two individual objects (“instances”); the first is an instance of class “Animal” named “rover”, while the second is an instance of class “Cat”, named “tiddles”.
  • In Python this might look something like this:
    [list]
    [*] class Animal():

    code here…

  • class Cat(Animal): # <— “Cat” inherits from “Animal”

    code here…

  • rover = Animal()
  • tiddles = Cat()
    [/:m]
    [
    ] We can now say that “rover” is an “Animal”, but not a “Cat”; “tiddles”, on the other hand, is both a “Cat” and, since “Cat” inherits from “Animal”, an “Animal”.[/*:m][/list:u]

Erm… I’m not seeing the change. Did you forget to post the new code, or am I just missing it? ^^;

Heh, now I’m wondering why your TA included it in the first place. :stuck_out_tongue:

In all fairness, there may well be a good reason that I’m simply missing, but as far as I’m aware you should be able to simply use the class in which this all takes place–as is done in the method “startbuttonevent”, when the controls are set (as in this line, for example: ‘self.accept(“escape”, sys.exit, [0])’).

Oooooohhhhh, okay, I see what you’re saying now!!! I tried that out, it works exactly the same without the DirectObject. Haha Thanks for taking the time to type all that out, that makes complete sense now.

Maybe I didn’t recopy it haha here’s the part where the DirectObjects were. I completely guessed on that last line. It runs, but the collision it’s assigned to doesn’t respond. It DOES act as a collision, but it does not print “END”, or “hit!” for that matter. Can you see what I’m doing wrong? haha that was the only thing I could think of to type.

self.ball = loader.loadModel("models/ball")
        ballCollider = self.camera.attachNewNode(CollisionNode('cnode'))
        ballCollider.node().addSolid(CollisionSphere(0, 0, 0, 2))
        ballCollider.node().setFromCollideMask(sphereMask)
        base.cTrav.addCollider(ballCollider, collisionHandler)
        collisionHandler.addCollider(ballCollider, self.camera, base.drive.node())
        
        self.accept('cnode-into-polygons', self.collideEventIn)

        
        #Collision that ends the game
        quad = CollisionPolygon( Point3(0,10,0),Point3(0,10,10),Point3(0,0,10),Point3(0,0,0))
        quadPath = self.room.attachNewNode(CollisionNode('qnode'))
        quadPath.node().addSolid(quad)
        quadPath.node().setIntoCollideMask(polygonMask)
        base.cTrav.addCollider(quadPath, collisionHandler)
        collisionHandler.addCollider(quadPath, self.camera, base.drive.node())
        quadPath.setPos(-30, -3, 0)
        quadPath.show()
        
        ############################################
        #qnode into what?
        self.accept('qnode-into-quad', self.endGameCollision)
        #############################################
        

Ah, I’m glad that it helped! :slight_smile:

As to the problem, you’re on the right track, I believe (I still think that the “end collider” needn’t be a “from” collider, but that’s not a major issue).

Well, what do you want to test for a collision with? I presume that it’s the “player”/“camera” object, and your event pattern (“collisionHandler.addInPattern(‘%fn-into-%in’)”) indicates that your events are of the form “-into-”, so look for the name that you assigned to the collision node of your “player”/“camera” object.

[edit] A quick note: your most recent code-snippet doesn’t include the “addInPattern” line–I presume that you omitted it for the sake of brevity. If not, then that’s probably at least in part the reason that you’re not getting your events called.

I think you might be right about that, I think it’s actually giving me an error for that…

“:collide(error): Invalid attempt to detect collision from CollisionPolygon!
This means that a CollisionPolygon object was added to a CollisionTraverser as if it were a colliding object. However, no implementation for this object has yet been defined to collide with other objects.”

I also sort of have no idea how I would change it from a “from” collider to an “into” collider… >.< What exactly defines it as either of those?

Edit: and yes, I just omitted the pattern stuff

Ah yes, I forgot about that–sorry! Simply put, Panda’s collision system doesn’t implement every possible pairing of “from” and “into” collision-solid types. This is especially true on the “from” side: only a few types of collision solid may be used as “from” objects. At the end of this page is a grid showing what pairs of “from” and “into” object-types are allowed. As shown on that page, CollisionPolygon may not be used as a “from” object at all.

In this case I think that it would probably be simplest to make your “end object” an “into” object. (Note that this incurs a change to the event that’s generated (in the line “self.accept …”).) This segues nicely into the next point:

As I recall, all colliders can be “into” colliders (unless you prevent them from acting so). On the other hand, a collider is only a “from” collider if you nominate it as such, by adding it to the collision traverser (and the collision handler, if called for) via “addCollider”. Simply put, only those colliders that you add via “addCollider” are “from” objects, while all colliders are by default “into” objects.

Ahh, okay, that’s an easy fix then. This is what I have now… It doesn’t come up with that error anymore, but it still won’t print “END” :confused:
I’m assuming it’s the “self.accept(‘quad-into-controlCamera’, self.endGameCollision)” line. I’m pretty sure that should work though… Oh, programming, when will you makes sense to me? haha

self.room = loader.loadModel("models/texturemesh")
        self.room.setHpr(0,0,0)
        self.room.setScale(3.0,3.0,3.0)
        self.room.reparentTo(render)
        roomCollider = self.room.find("**/polygons")
        roomCollider.node().setIntoCollideMask(sphereMask)
        
        
        
        self.ball = loader.loadModel("models/ball")
        ballCollider = self.camera.attachNewNode(CollisionNode('cnode'))
        ballCollider.node().addSolid(CollisionSphere(0, 0, 0, 2))
        ballCollider.node().setFromCollideMask(sphereMask)
        base.cTrav.addCollider(ballCollider, collisionHandler)
        collisionHandler.addCollider(ballCollider, self.camera, base.drive.node())
        
        self.accept('cnode-into-polygons', self.collideEventIn)

        
        #Collision that ends the game
        quad = CollisionPolygon( Point3(0,10,0),Point3(0,10,10),Point3(0,0,10),Point3(0,0,0))
        quadPath = self.room.attachNewNode(CollisionNode('qnode'))
        quadPath.node().addSolid(quad)
        quadPath.node().setIntoCollideMask(polygonMask)
        quadPath.setPos(-30, -3, 0)
        quadPath.show()
        
        self.accept('qnode-into-controlCamera', self.endGameCollision)
        
        collisionHandler.addInPattern('%fn-into-%in')
        collisionHandler.addOutPattern('%fn-out-%in')def collideEventIn(self,entry):
		colliderINTO = entry.getIntoNodePath().getParent()
		colliderFROM = entry.getFromNodePath().getParent()
		print "hit!"
			
    def endGameCollision(self,entry):
		#Find some way to get the screen to fade out and quit, while displaying "END" or something
		colliderINTO = entry.getIntoNodePath().getParent()
		colliderFROM = entry.getFromNodePath().getParent()
		print "END"

Ah, I think that you’re right about that line being the problem–specifically, I see two issues:

[edit] Bleh, disregard the first paragraph below (which starts with “First”)–I think that I ended up reading code frm the wrong post! I’m sorry about that! XD;

However, it does at least inform the matter in the next paragraph: look for the name that you passed in for the CollisionNode of your camera object.
[/edit]

First, it looks as though you’re using the wrong name for your “end of level” object. Instead of the names that you’ve given to the variable in your code (“quad”), it expects the name that you passed as a parameter to the CollisionNode (“qnode”), I believe.

As to “controlCamera”, that appears to be the name of a method, unless you’ve changed something that I’m not seeing…? o_0

Second, while I see that the “end of level” object appears to no longer be a “from” object, your event is still set up as though it were: your “in-pattern” reads “%fn-into-%in”–“-into-”, indicating that the name of the “from” object should appear first in the event, followed by the string “-into-”, and finally the name of “into” object.

(I thought that I saw a third issue, but it’s evading me now. :/)

Heh, I hope that your study of it works out however is best for you. :slight_smile:

Oops, yeah, I was testing out different options to see what would happen and I forgot to change it back. haha it’s fixed now!

But yes, controlCamera is a name of a method I have… Is that what I’m supposed to put there? Or something else?

def controlCamera(self, task):
        
        md = base.win.getPointer(0)
        x = md.getX()
        y = md.getY()
        if base.win.movePointer(0, 100, 100):
            self.heading = self.heading - (x - 100) * 0.2
            self.pitch = self.pitch - (y - 100) * 0.2
            
        if (self.pitch < -45): self.pitch = -45
        if (self.pitch >  45): self.pitch =  45
        self.camera.setHpr(self.heading,self.pitch,0)
        dir = self.camera.getMat().getRow3(1)
        elapsed = task.time - self.last
        if (self.last == 0): elapsed = 0
        if (self.mousebtn[0]):
            self.focus = self.focus + dir * elapsed*30
            
        if (self.mousebtn[1]) or (self.mousebtn[2]):
            self.focus = self.focus - dir * elapsed*30
            
        self.camera.setFluidPos(self.focus - (dir*5))
        if (base.camera.getZ() <   8.0): base.camera.setZ(  8)
        if (base.camera.getZ() >  400.0): base.camera.setZ( 400)
        
        if (self.keyMap["camera-forward"]!=0):
			self.camera.setFluidPos(self.camera.getPos + 100)
        
        self.focus = self.camera.getPos() + (dir*5)
        self.last = task.time
        
        return Task.cont

That’s the method… Right? hahah

Hmm, so do you mean I should switch “collisionHandler.addInPattern(’%in-out-%fn’)” to “collisionHandler.addInPattern(’%fn-into-%in’)”? I just now did that, it didn’t really change anything… If you remember that third issue let me know xD Haha

Heh, no, your pattern is fine. (More specifically, the pattern is somewhat arbitrary–use what makes sense to you.) What I’m saying is that your event (“qnode-into-controlCamera”, in the line that begins with “self.accept”) doesn’t respect that pattern, since “qnode” is no longer the “from” collider: you’re now colliding into “qnode”.

Yep!

Nope! :stuck_out_tongue:

The first node should be your “from” node–the CollisionNode (identified by the name that you gave to it when you created it) of your “from” object, and the second should be your “into” node (again identified by name).

OOOOOHHHHHHHHHH!!! Okay, so then I think it should be " cnode-into-qnode ", yeah? The cnode is the “from” object, and the qnode is the “into” object, so that should woorrkkk?

And yep, it totally works! That makes so much sense. Haha I think everything is working just as I need it to now!

Thank you SOOOO much for your help, this has been the most helpful response I’ve ever gotten on these forums. Normally people give up after a few responses… hahah so thank you SO much for your help, you have no idea how much I appreciate this. I’ve officially learned more from you than I have from my professor and the TA this semester. haha
But I really appreciate you taking the time to type all this out and explain it to a noob like me. I was really worried that I wouldn’t be able to finish this project in time, but thanks to you, I definitely can now, I have a much better grasp of collisions now :smiley: You’re the best, and thank you so much!

bows I’m glad to have been of service. :slight_smile:

Honestly, I feel that one reason that I continued to respond is that, while you’re inexperienced, you do seem to be willing to learn. You didn’t insist that I simply post the solution, you responded to questions and pasted a reduced version of your code when asked, you didn’t become impatient, and–importantly–you kept making attempts on your side. Being willing to learn can encourage others to teach.