onTrigger Collision

I was wondering how to set positions for a collision box for code so if you walk between the position you put it will trigger and you could put code when you walk into the box it will lets say take you back to spawn. Please Help :cry:

Your question is a little unclear to me, I’m afraid. I’ll answer as best I understand it. :confused:

First of all, which collision system are you using? For the moment I’m going to presume that you’re using Panda’s built-in collision system; if not, some of the below might not apply.

You set the position of a collision object in the same manner as any other NodePath, I believe: “myNodePath.setPos(position)”.

In essence, you would seem to want a collision object with an event registered to it, handled via a CollisionHandlerEvent object.

If you’re already using a CollisionHandlerPusher (or one of its descendants) to prevent objects from intersecting, you can use this in place of a separate CollisionHandlerEvent (CollisionHandlerPusher inherits from CollisionHandlerEvent), I believe. In this case, presuming that you want the trigger to be “non-solid” (that is, you don’t want objects to stop when they hit it), you would additionally call the “setTangible” method of the solid, passing in “False” to indicate that it be intangible.

That done, you add an appropriate event-pattern to your CollisionHandlerEvent/CollisionHandlerPusher–that is, register one or more of “in”, “out”, and “again” patterns–and have your Direct/ShowBase object “accept” your events, allowing you to link them to methods of your choosing. (See the link attached to the word “CollisionHandlerEvent”, above.)

I believe that the manual gives a fuller description, including examples, starting here.

How you use Panda’s built-in collision system can you please give me a code or something because right now i’m a little confused. Like put it all in code.

There are two examples in the manual that do exactly that, I believe–one for CollisionHandlerPusher, and one for CollisionHandlerEvent. o_0

Otherwise, what, specifically, is confusing you? Perhaps I can help. :slight_smile:

I Need CollisionHandlerEvent because the CollisionHandlerPusher is like if you don’t want to run into walls so if you go to a wall it will not let you go through the model. If I use CollisionHandlerEvent it will allow me to go through
the model and active it. I look at the code and I don’t get it I read what it says for CollisionHandlerEvent I kinda get it here’s the code:

class MyObject(DirectObject.DirectObject):
    def __init__(self):
      self.accept('car-into-rail', handleRailCollision)
 
    def handleRailCollision(self, entry):
      print entry

So do I take it then that you won’t have walls or obstacles that the object should be stopped by, or that you’re handling that sort of collision in some way other than CollisionHandlerPusher? If so, then fair enough; if not, then I’ll point out that CollisionHandlerPusher can produce events just as a CollisionHandlerEvent can, and collision objects can be made “intangible”, and thus produce events without preventing objects from moving through them, I believe.

Okay, fair enough. Perhaps it would help to go through the process one step at a time.

The code that you posted looks like a decent start: you have a descendant of DirectObject that accepts an event, and a method which that event should call. There is one issue that I see: in the call to “accept”, the method that you’re telling it to call appears to be declared in the same class (“handleRailCollision”), but you aren’t specifying this when you refer to the method in your call to “accept”: in short, you’re missing “self.” before “handleRailCollision”, I believe.

Moving on from there, let’s start by finding out where you’re getting lost:

  • Do you know how to create collision solids, and add them to your scene?
  • Do you know how to create a traverser?
  • Do you know how to create a collision handler?
  • Do you know how to tell the handler and traverser about your objects?

I was wondering there’s a way like this /

if localAvatar.getY() < place and localAvatar.getX() < place1 and localAvatar.getX() > place2 and localAvatar.getX() > place3

so the places I can make like a box with the places with x & y I was wondering if I can do that?

Depending on what a “place” is, yes, that seems reasonable.

You’d presumably define your own regions (that is, you have some class or tuple storing this information), each with a position (or a NodePath defining a position) and a size. You then compare the position of your “localAvatar” to the position of the region, plus- and minus- its size.

If I’m not much mistaken, note that a point is within a rectangle when the point’s x-value lies between the rectangle’s left- and right- edges, and the point’s y-value lies between the rectangle’s bottom- and top- edges. The left edge of a rectangle can be defined as the x-value of rectangle’s centre-point minus half of the rectangle’s width, and its right edge can be defined as the x-value of the rectangle’s centre-point plus half of the rectangle’s width. Much the same can be done for the top- and bottom- edges of the rectangle, but using the y-value of its centre-point and its length.

In short, something like this:

# I'll store a few values in local variables so that the "if-statement" doesn't get too messy...
avatarX = localAvatar.getX()
avatarY = localAvatar.getX()
regionX = someRegion.nodePath.getX()
regionY = someRegion.nodePath.getY()
halfRegionWidth = someRegion.width/2.0
halfRegionLength = someRegion.length/2.0

if avatarX > regionX - halfRegionWidth and avatarX < regionX + halfRegionWidth and avatarY > regionY - halfRegionLength and avatarY < regionY + halfRegionLength:
    # Do something...

for

is it the position because the problem there is it’s a full town so how would I do it
like the model is all in one model so theres no like multiple models to make the town.

The “regions” (of which “someRegion” would be just one) are things that you define, most likely a class of your own creation. There are a number of means by which you could specify their positions, depending on what works best for you and for your project–offhand, three approaches come to mind (although there may be more):

  • You could use place-holder objects in your level-model, which you search for and replace when the level is loaded
  • You could have a separate text-file describing their locations, hand-written by you
  • You could put together some sort of level-editor in which you place them, and which allows you to save them out to a file

Let me explain why i’m here in the first place. I was on youtube, and I would type like Panda3d tutorials Toontown I like Toontown and stuff then there’s this guy who did like a collision, but he’s not there anymore when I type his name and still on there on YouTube and i’m trying to do it his way I remember some of his code so this is what I got so far, but doesn’t seem to work.

if localAvatar.getX() > 22 and localAvatar.getY() > -149 and localAvatar.getX() < 24 and localAvatar.getY() < -151:
 toontowncentral.detachNode()
 loader.unloadModel('toontown.bam')

Quesion: is x the first or second, and is y the first or second?

I’m afraid that I have no real idea: I’ve never played Toontown, nor taken part in one of the attempts that I believe that I’ve seen to re-create it.

[edit] But why is it important to use the approach that this other person did? Why not develop something that works for you?

True true but that was the easiest way for me to understand.

Here is what I used in an old project

def updateTunnel(task): #done
	global loadedArea
	global toontowncentral
	global dg
	
	x = Actor.getPos().get_x()
	y = Actor.getPos().get_y()
	
	
	#Toontown Central to DG
	if x >= 23.8046 and x <= 37.7877 and y <= -149.988 and y >= -158.263 and loadedArea == 'toontowncentral':
		
		toontowncentral.remove()
		toontowncentral = loader.unloadModel('phase_4/models/neighborhoods/toontown_central_full.bam')
		dg = loader.loadModel('daisys_garden_sz.bam')
		dg.reparentTo(render)
		Actor.setPosHpr(72.0447, 183.742, 10.208, -209.71, 0, 0)

		loadedArea = 'dg'
		
		#DG To Toontown Central
	if x >= 74.2401 and x <= 83.6807 and y >= 180.808 and y <= 194.032 and loadedArea == 'dg':
		dg.remove()
		dg = loader.unloadModel('street_daisys_garden_sz.bam')
	
		loadedArea = 'toontowncentral'
		toontowncentral = loader.loadModel('phase_4/models/neighborhoods/toontown_central_full.bam')
		toontowncentral.reparentTo(render)
		Actor.setPosHpr(34.8669, -147.037, 2.525, 687.063, 0, 0)
		
		
			
	
	return Task.cont

base.taskMgr.add(updateTunnel, 'UpdateTunnel')

Hope this helps