Collision Detection

Trying to get some pushing collision detection going on between all my objects to start with.

Right now, the following happens:
Bullets collide with wall
bullets collide with player (if I slow them down enough to move into them)
bullets collide with enemy (cookie)
player collides with enemy (cookie)
player collides with wall

The enemy doesn’t collide with the wall. This has been frustrating me for hours.

On a side question. Is there a way to define once like you can with C++ header files?

globals.py

#Imports
from pandac.PandaModules import *

# File Access

#collision globals
base.cTrav = CollisionTraverser()
base.pusher = CollisionHandlerPusher()
colHandler = CollisionHandlerEvent()
colHandler.addInPattern('%fn-into-%in')
base.collCount = 0
base.che = colHandler

#Level Spreads
SX = 500
SY = 500
SZ = 500

baseMovement.py

#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from pandac.PandaModules import Filename,Buffer,Shader
from pandac.PandaModules import PandaNode,NodePath
from pandac.PandaModules import AmbientLight,DirectionalLight
from pandac.PandaModules import TextNode,Point3,Vec3,Vec4
from pandac.PandaModules import TextureStage
from pandac.PandaModules import *

from direct.interval.MetaInterval import Sequence
from direct.interval.FunctionInterval import Wait,Func
from direct.interval.IntervalGlobal import *

from direct.filter.CommonFilters import CommonFilters
from direct.gui.OnscreenText import OnscreenText
from direct.actor.Actor import Actor
from direct.interval.IntervalGlobal import LerpFunc

from Obstacle import *
from Enemy import *
from resourceManager import *
from globals import *

import sys,os,random, cPickle
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#Game Constants
SHIP_SPEED = 400
BULLET_SPEED =  100
BULLET_DURATION = 1.25 # Time in seconds

# World Obstacles
NUM_SMALL = 100
NUM_MED = 20
NUM_LARGE = 5

# Enemies
#virus
NUM_VIRUS = 100
TYPE_VIRUS = "VIRUS"

#cookie
NUM_COOKIE = 100
TYPE_COOKIE = "Cookie"
TYPE_C_MONSTER = "C_Monster"

oman = ObstacleFactory()
eman = EnemyManager()
rman = ResourceManager()
 
#@@@@ >Start< FPS Class @@@@#
class FPS(object,DirectObject):
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    def __init__(self,omang,emang,rmang):
	self.loadLevel()
	self.initPlayer()
	oman = omang
	eman = emang
	rman = rmang
	oman.populate([rman.obstacle,rman.glitch], NUM_SMALL, NUM_MED, NUM_LARGE, SX, SY, SZ )
	self.gameLoop = taskMgr.add(self.updateBullets, "Game Loop")
	self.gameLoop.last = 0
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%       
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    def loadLevel(self):
	#load level
	self.level = loader.loadModel('Assets/Models/World/skybox')
	self.level.reparentTo(render)
	self.level.setPos(0,0,0)
	self.level.setTwoSided(True)
	self.level.setColor(VBase4(1.0,1.0,1.0,0.7))

	self.bullets = []

#---------------------------------------------------------------------
#Level collision
	#The level Cube
	self.wallRight = CollisionPlane(Plane(Vec3(-1,0,0), Point3(248,0,0)))
	self.cnode = CollisionNode('cnWallRight')
	self.cnode.setCollideMask(BitMask32.bit(1))
	self.cnode.addSolid(self.wallRight)
	self.cn = self.level.attachNewNode(self.cnode)
	
	self.wallLeft = CollisionPlane(Plane(Vec3(1,0,0), Point3(-248,0,0)))
	self.cnode = CollisionNode('cnWallLeft')
	self.cnode.setCollideMask(BitMask32.bit(1))
	self.cnode.addSolid(self.wallLeft)
	self.cn = self.level.attachNewNode(self.cnode)
	
	self.wallFront = CollisionPlane(Plane(Vec3(0,-1,0), Point3(0,248,0)))
	self.cnode = CollisionNode('cnWallFront')
	self.cnode.setCollideMask(BitMask32.bit(1))
	self.cnode.addSolid(self.wallFront)
	self.cn = self.level.attachNewNode(self.cnode)
	
	self.wallBack = CollisionPlane(Plane(Vec3(0,1,0), Point3(0,-248,0)))
	self.cnode = CollisionNode('cnWallBack')
	self.cnode.setCollideMask(BitMask32.bit(1))
	self.cnode.addSolid(self.wallBack)
	self.cn = self.level.attachNewNode(self.cnode)
	
	self.wallTop = CollisionPlane(Plane(Vec3(0,0,-1), Point3(0,0,248)))
	self.cnode = CollisionNode('cnWallTop')
	self.cnode.setCollideMask(BitMask32.bit(1))
	self.cnode.addSolid(self.wallTop)
	self.cn = self.level.attachNewNode(self.cnode)
	
	self.wallBottom = CollisionPlane(Plane(Vec3(0,0,1), Point3(0,0,-248)))
	self.cnode = CollisionNode('cnWallBottom')
	self.cnode.setCollideMask(BitMask32.bit(1))
	self.cnode.addSolid(self.wallBottom)
	self.cn = self.level.attachNewNode(self.cnode)

	#--------------------------------------------------------------------
	self.pwR = CollisionPlane(Plane(Vec3(-1,0,0), Point3(248,0,0)))
	self.pnode = CollisionNode('pnWallRight')
	self.pnode.setCollideMask(BitMask32.bit(1))
	self.pn = self.level.attachNewNode(self.pnode)
	wallC = self.level.attachNewNode(self.pnode)
	base.cTrav.addCollider(wallC, base.pusher)
	base.pusher.addCollider(wallC, self.level, base.drive.node())
	
	self.pwL = CollisionPlane(Plane(Vec3(1,0,0), Point3(-248,0,0)))
	self.pnode = CollisionNode('pnWallLeft')
	self.pnode.setCollideMask(BitMask32.bit(1))
	self.pn = self.level.attachNewNode(self.pnode)
	wallC = self.level.attachNewNode(self.pnode)
	base.cTrav.addCollider(wallC, base.pusher)
	base.pusher.addCollider(wallC, self.level, base.drive.node())
	
	self.pwF = CollisionPlane(Plane(Vec3(0,-1,0), Point3(0,248,0)))
	self.pnode = CollisionNode('pnWallFront')
	self.pnode.setCollideMask(BitMask32.bit(1))
	self.pn = self.level.attachNewNode(self.pnode)
	wallC = self.level.attachNewNode(self.pnode)
	base.cTrav.addCollider(wallC, base.pusher)
	base.pusher.addCollider(wallC, self.level, base.drive.node())
	
	self.pwBz = CollisionPlane(Plane(Vec3(0,1,0), Point3(0,-248,0)))
	self.pnode = CollisionNode('pnWallBack')
	self.pnode.setCollideMask(BitMask32.bit(1))
	self.pn = self.level.attachNewNode(self.pnode)
	wallC = self.level.attachNewNode(self.pnode)
	base.cTrav.addCollider(wallC, base.pusher)
	base.pusher.addCollider(wallC, self.level, base.drive.node())
	
	self.pwT = CollisionPlane(Plane(Vec3(0,0,-1), Point3(0,0,248)))
	self.pnode = CollisionNode('pnWallTop')
	self.pnode.setCollideMask(BitMask32.bit(1))
	self.pn = self.level.attachNewNode(self.pnode)
	wallC = self.level.attachNewNode(self.pnode)
	base.cTrav.addCollider(wallC, base.pusher)
	base.pusher.addCollider(wallC, self.level, base.drive.node())
	
	self.pwBo = CollisionPlane(Plane(Vec3(0,0,1), Point3(0,0,-248)))
	self.pnode = CollisionNode('pnWallBottom')
	self.pnode.setCollideMask(BitMask32.bit(1))
	self.pn = self.level.attachNewNode(self.pnode)
	wallC = self.level.attachNewNode(self.pnode)
	base.cTrav.addCollider(wallC, base.pusher)
	base.pusher.addCollider(wallC, self.level, base.drive.node())
	
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#Virus generation
	#Generate enemies
	#enemyManager.createNewEnemy(rm.virus, TYPE_VIRUS, NUM_VIRUS, SX, SY, SZ)
	#eman.createNewEnemy(rman.cookie, TYPE_COOKIE, NUM_COOKIE, SX, SY,SZ)
	eman.createNewBoss(rman.cookie, TYPE_C_MONSTER, Vec3(20,20,0))
	
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%               
    def initPlayer(self):
       
	#load man
	self.man = loader.loadModel('teapot')
	self.man.reparentTo(render)
	self.man.setPos(0,0,2)
	self.man.setScale(.05)
	base.camera.reparentTo(self.man)
	base.camera.setPos(0,0,0)
	base.disableMouse()

	# Collision Pushing
	self.sphere = CollisionSphere(0,0,0,3)
	self.pnode = CollisionNode('pnCharacter')
	self.pnode.setCollideMask(BitMask32.bit(1))
	self.pnode.addSolid(self.sphere)
	self.pn = self.man.attachNewNode(self.pnode)
	manC = self.man.attachNewNode(self.pnode)
	base.cTrav.addCollider(manC,base.pusher)
	base.pusher.addCollider(manC,self.man, base.drive.node())
       
	md = base.win.getPointer(0)
	Forward = Vec3(0,SHIP_SPEED*2,0)
	Back = Vec3(0,-SHIP_SPEED,0)
	Left = Vec3(-SHIP_SPEED,0,0)
	Right = Vec3(SHIP_SPEED,0,0)
	Stop = Vec3(0)
	self.walk = Stop
	self.strife = Stop
	self.jump = 0
	taskMgr.add(self.move, 'move-task')
        
        #!!!!>Start<--Movement keys--!!!!#
	self.accept( "s" , self.__setattr__,["walk",Back] )
	self.accept( "w" , self.__setattr__,["walk",Forward])
	self.accept( "a" , self.__setattr__,["strife",Left])
	self.accept( "d" , self.__setattr__,["strife",Right] )
	self.accept( "mouse1" , self.fireHR)
	self.accept( "s-up" , self.__setattr__,["walk",Stop] )
	self.accept( "w-up" , self.__setattr__,["walk",Stop] )
	self.accept( "a-up" , self.__setattr__,["strife",Stop] )
	self.accept( "d-up" , self.__setattr__,["strife",Stop] )
        #!!!!>END<--Movement Keys--!!!!#
        
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%       
    def move(self,task):
	# mouse & look directions
	md = base.win.getPointer(0)
	x = md.getX()
	y = md.getY()
        
	# Mouse look code
	if base.win.movePointer(0, base.win.getXSize()/2, base.win.getYSize()/2):
		self.man.setH(self.man.getH() -  (x - base.win.getXSize()/2)*0.1)
		self.man.setP(self.man.getP() - (y - base.win.getYSize()/2)*0.1)
	# move where the keys set it
	self.man.setPos(self.man,self.walk*globalClock.getDt())
	self.man.setPos(self.man,self.strife*globalClock.getDt())

	return task.cont

#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    def fireHR(self):
	
	#bullet direction
	x = self.man.getH()
	y = self.man.getP()
	z = self.man.getR()
	
	bulVec = Vec3(0,BULLET_SPEED,0)

	# load the bullet in and scale it
	self.bullet = loader.loadModel('Assets/Models/Bullet/weapon')
	self.bullet.setScale(2,2,2)
	self.bullet.setPos(self.man.getPos())
	self.bullet.setH(x)
	self.bullet.setP(y)
	self.bullet.setR(z)
	self.bullet.reparentTo(render)
	
	# Collision
	self.bSphere = CollisionSphere(0,0,0,0.5)
	self.pnode = CollisionNode('pnBullet')
	self.pnode.setFromCollideMask(BitMask32.bit(1))
	self.pnode.addSolid(self.bSphere)
	self.pn = self.bullet.attachNewNode(self.pnode)
	bulC = self.bullet.attachNewNode(self.pnode)
	base.cTrav.addCollider(bulC,base.pusher)
	base.pusher.addCollider(bulC,self.bullet, base.drive.node()) 

	# Set the bullet in motion
	self.setVelocity(self.bullet, bulVec)
	# Set the bullet to expire
	self.setExpires(self.bullet, BULLET_DURATION)
	
	# add to list
	self.bullets.append(self.bullet)
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    def setVelocity(self, obj, val):
	list = [val[0], val[1], val[2]]
	obj.setTag("velocity", cPickle.dumps(list))

    def getExpires(self,obj):
	return float(obj.getTag("expires"))
    
    def setExpires(self, obj, val):
	obj.setTag("expires", str(val))

    def getVelocity(self, obj):
	list = cPickle.loads(obj.getTag("velocity"))
	return Vec3(list[0], list[1], list[2])

    def updatePos(self, obj, dt):
	vel = self.getVelocity(obj)
	newPos = (vel*dt)
	obj.setPos(obj,newPos)
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    def updateBullets(self, task):
		
	dt = task.time - task.last
	task.last =  task.time
	
	newBulletArray = []
	
	for obj in self.bullets:
		self.updatePos(obj, dt)         #Update the bullet
		#check if any bullets expire     
		if self.getExpires(obj) > dt: 
			newBulletArray.append(obj)
			self.setExpires(obj, self.getExpires(obj) - dt)
		else: 
			obj.remove()              #Otherwise remove it from the scene
	#Set the bullet array to be the newly updated array
	self.bullets = newBulletArray
	return task.cont

#@@@@ >End< FPS Class @@@@#

resourceManager.py

import direct.directbase.DirectStart

from direct.actor.Actor import Actor
from pandac.PandaModules import PandaNode,NodePath
from pandac.PandaModules import TextNode,Point3,Vec3,Vec4
from pandac.PandaModules import CollisionSphere, CollisionNode
from pandac.PandaModules import *

from globals import *

#MODEL LOCATIONS
VIRUS = "Assets/Models/virus"
COOKIE = "Assets/Models/cookie"
WORM = "Assets/Models/worm"
GLITCH = "Assets/Models/glitch"

class ResourceManager():
    def __init__ (self):
	
		#set and init the model loc
		self.virus = loader.loadModel(VIRUS)
		self.obstacle = loader.loadModel(WORM)
		self.glitch = loader.loadModel(GLITCH)
		
		#scale and rotation
		#virus
		self.virus.setScale(4,4,4)
		self.intervalVirus = self.virus.hprInterval(60,Point3(360,0,0))
		self.intervalVirus.loop()
		#-----------------------------------------------------------------------------
		#cookie
		# set up cookie collision
		self.cookie = loader.loadModel(COOKIE)
		
		self.cSphere = CollisionSphere(0,0,0,1.5)
		self.pnode = CollisionNode('pnCookie')
		self.pnode.setCollideMask(BitMask32.bit(1))
		self.pnode.addSolid(self.cSphere)
		self.pn = self.cookie.attachNewNode(self.pnode)
		cookC = self.cookie.attachNewNode(self.pnode)
		base.cTrav.addCollider(cookC,base.pusher)
		base.pusher.addCollider(cookC,self.cookie, base.drive.node())
		
		# event collision
		#self.csphere = CollisionSphere(0,0,0,1.5)
		#self.cnode = CollisionNode('cnCookie')
		#self.cnode.setIntoCollideMask(BitMask32.bit(1))
		#self.cnode.setFromCollideMask(BitMask32.bit(1))
		#self.cnode.addSolid(self.csphere)
		#self.cn = self.cookie.attachNewNode(self.cnode) 
		
		self.cookie.setScale(4,4,4)
		self.intervalCookie = self.cookie.hprInterval(30,Point3(360,0,0))
		self.intervalCookie.loop()
		#-----------------------------------------------------------------------------
		#obstacle
		self.obstacle.setScale(4,4,4)
		self.intervalObstacle = self.obstacle.hprInterval(20, Point3(360,0,0))
		self.intervalObstacle.loop()
		#glitch
		self.glitch.setScale(4,4,4)
		self.intervalGlitch = self.glitch.hprInterval(45, Point3(360,0,0))
		self.intervalGlitch.loop()

Enemy.py

#Created by Michael Pezek

import direct.directbase.DirectStart
from pandac.PandaModules import Filename,Buffer
from pandac.PandaModules import PandaNode,NodePath
from pandac.PandaModules import AmbientLight,DirectionalLight
from pandac.PandaModules import Vec3
from direct.showbase.DirectObject import DirectObject
from direct.actor.Actor import Actor
#from pandac.PandaModules import TextNode
import sys,os,random,cPickle

ENEMY_COOKIE_HEALTH = 40
ENEMY_COOKIE_STABLE_DELAY = 10
ENEMY_COOKIE_SHUFFLE_DELAY_1 = 400 #Duration of SHUFFLE
ENEMY_COOKIE_SHUFFLE_DELAY_2 = 400 #Change of direction interval
ENEMY_COOKIE_VELOCITY = 20
ENEMY_COOKIE_ERRATIC_DELAY = 10
ENEMY_COOKIE_ERRATIC_TURN = 5 

ENEMY_C_MONSTER_HEALTH = 80
ENEMY_C_MONSTER_RADIUS = 4
ENEMY_C_MONSTER_ROTATION_TIME = 20

ENEMY_VIRUS_HEALTH = 80 

def setHealth(obj,val):
	obj.setTag("health",str(val))
    
def getHealth(obj):
	return int(obj.getTag("health"))
	
def setMaxHealth(obj,val):
	obj.setTag("max_health",str(val))
	
def getMaxHealth(obj):
	return int(obj.getTag("max_health"))
    
def setType(obj,val):
	obj.setTag("type",val)
    
def getType(obj):
	return obj.getTag("type")
    
def setID(obj,val):
	obj.setTag("id",str(val))
    
def getID(obj):
	return int(obj.getTag("id"))
		
#def setVelocity(obj,val):
#	list = [val[0],val[1],val[2]]
#	obj.setTag("velocity",cPickle.dumps(list))
		
#def getVelocity(obj):
#	list = cPickle.loads(obj.getTag("velocity"))
#	return Vec3(list[0],list[1],list[2])
		
def setDelay(obj,index,val):
	obj.setTag("delay"+str(index),str(val))
		
def getDelay(obj,index):
	return float(obj.getTag("delay"+str(index)))
	
def setRot(obj,index,val):
	list = [val[0],val[1],val[2]]
	obj.setTag("rot"+str(index),cPickle.dumps(list))
	
def getRot(obj,index):
	list = cPickle.loads(obj.getTag("rot"+str(index)))
	return Vec3(list[0],list[1],list[2])
		
def setState(obj,val):
	obj.setTag("state",val)
		
def getState(obj):
	return obj.getTag("state")
		
def setTarget(obj,val):
	obj.setTag("target",val)
		
def getTarget(obj):
	return obj.getTag("target")

class Enemy():
	def __init__(self,model,id,pos,health,type,factoryNode):
		self.enemyNode = factoryNode.attachNewNode("Enemy-Node"+str(id))
		self.enemyNode.setPos(pos)
		
		setHealth(self.enemyNode,health)
		setMaxHealth(self.enemyNode,health)
		
		setType(self.enemyNode,type)
		setID(self.enemyNode,id)
		
		setState(self.enemyNode,"INITIAL")
		setTarget(self.enemyNode, "NONE")
		
		setRot(self.enemyNode,0,Vec3(0,0,0))
		setRot(self.enemyNode,1,Vec3(0,0,0))
		
		setDelay(self.enemyNode,0,0)
		
		model.instanceTo(self.enemyNode)

class EnemyFactory:
	def __init__(self):
		self.count = 0
		self.enemyFactoryNode = render.attachNewNode("EnemyFactory-Node")
		self.enemyCookieNode = self.enemyFactoryNode.attachNewNode("EnemyCookie-Node")
		self.enemyVirusNode = self.enemyFactoryNode.attachNewNode("EnemyVirus-Node")
		
	def createNewCookie(self,model,pos):
		newEnemy = Enemy(model,self.count,pos,ENEMY_COOKIE_HEALTH,"Cookie",self.enemyCookieNode)
		self.count+= 1
		
		return newEnemy.enemyNode		
		
	def createNewCookiePiece(self,model,pos,parent):
		newEnemy = Enemy(model,self.count,pos,ENEMY_C_MONSTER_HEALTH,"Cookie",parent)
		self.count+= 1
		
		return newEnemy.enemyNode
		
	def createNewVirus(self,model,pos):
		newEnemy = Enemy(model,self.count,pos,ENEMY_VIRUS_HEALTH,"Virus",self.enemyVirusNode)
		self.count+= 1
		
		return newEnemy.enemyNode
		
	def createNewMonster(self,model,pos):
		#maxCount = 43
		tempCount = 0
		tempCount2 = 0
		scaleTemp = model.getScale()

		listPos = [Vec3(0,ENEMY_C_MONSTER_RADIUS*scaleTemp[0],0),Vec3(0,-ENEMY_C_MONSTER_RADIUS*scaleTemp[0],0),
				Vec3(ENEMY_C_MONSTER_RADIUS*scaleTemp[0],0,0),Vec3(-ENEMY_C_MONSTER_RADIUS*scaleTemp[0],0,0),
				Vec3(0,0,ENEMY_C_MONSTER_RADIUS*scaleTemp[0]),Vec3(0,0,-ENEMY_C_MONSTER_RADIUS*scaleTemp[0])]
		
		mainNode = self.createNewCookiePiece(model,pos,self.enemyCookieNode)
		setState(mainNode,"ERRATIC")
		setDelay(mainNode,0,ENEMY_COOKIE_ERRATIC_DELAY)		
		
		for tempCount in range(6):
			layerNode = self.createNewCookiePiece(model,listPos[tempCount],mainNode)
			setTarget(layerNode,mainNode.getName())
			
			for tempCount2 in range(6):
				tempNode = self.createNewCookiePiece(model,Vec3(listPos[tempCount2]/2),layerNode)
				setTarget(tempNode,layerNode.getName())
			
	def spawnBoss(self,model,type,pos):
		if type == "C_Monster":
			self.createNewMonster(model,pos)
				
	def spawnType(self,model,type,num,spreadX,spreadY,spreadZ):
		maxCount = self.count + num
		tempCount = 0
		
		for tempCount in range(maxCount):
				
			tempScale = model.getScale()
	            
			spawnX = (spreadX - tempScale[0])/2
			spawnY = (spreadY - tempScale[1])/2
			spawnZ = (spreadZ - tempScale[2])/2
	            
	        #Sets the random position
			pos = Vec3(random.uniform(-spawnX,spawnX),
					random.uniform(-spawnY,spawnY),
					random.uniform(-spawnZ,spawnZ))
		
			if type == "Cookie":
				self.createNewCookie(model,pos)
			elif type == "Virus":
				self.createNewVirus(model,pos)
				
	def destroy(self,obj):
		obj.removeNode()
		#self.count-= 1
		
	def destroyAll(self):
		if self.count > 0:
			countTemp = 0
            
			enemyNodeList = self.enemyFactoryNode.findAllMatches("Enemy-Node*")
			
			for countTemp in range(enemyNodeList.getNumPaths()):
				enemyNodeList[countTemp].removeNode()
				
			self.count = 0
			
	def destroyAllofType(self,type):
		if self.count > 0:
			countTemp = 0
		
			enemyNodeList = self.enemyFactoryNode.findAllMatchs("Enemy"+type+"-Node/Enemy-Node*")
		
			#self.count-= enemyNodeList.getNumPaths()
			
			for countTemp in range(enemyNodeList.getNumPaths()):
		   		enemyNodeList[countTemp].removeNode()

class CookieAI:
	def update(self,obj,dt,refNode):
		tempState = getState(obj)
		
		if tempState == "INITIAL":
			if getTarget(obj) != "NONE":
				tempState = "TARGETING"
			
			else:
				tempState = "STABLE"
				setDelay(obj,0,ENEMY_COOKIE_STABLE_DELAY)
		
		setDelay(obj,0,getDelay(obj,0)-dt)		
		
		if tempState == "STABLE":
			if getDelay(obj,0) <= 0:
				tempState = "SHUFFLE"
				setDelay(obj,0,ENEMY_COOKIE_SHUFFLE_DELAY_1)
				setDelay(obj,1,0)
			
			if getHealth(obj) <= ENEMY_COOKIE_HEALTH / 4:
				tempState = "ERRATIC"
				setDelay(obj,0,ENEMY_COOKIE_ERRATIC_DELAY)
			
		elif tempState == "SHUFFLE":
			setDelay(obj,1,getDelay(obj,1)-dt)	
			
			if getDelay(obj,1) <= 0:
				newH = random.uniform(0,360)
				newP = random.uniform(0,360)
				newR = random.uniform(0,360)
				
				obj.setHpr(newH,newP,newR)
				
				setDelay(obj,1,ENEMY_COOKIE_SHUFFLE_DELAY_2)
				
			obj.setPos(obj,Vec3(0,ENEMY_COOKIE_VELOCITY*dt,0))
			
			if getDelay(obj,0) <= 0:
				tempState = "STABLE"
				setDelay(obj,0,ENEMY_COOKIE_STABLE_DELAY)
				
		elif tempState == "ERRATIC":
			if getDelay(obj,0) <= 0:
				newH = random.uniform(0,360)
				newP = random.uniform(0,360)
				newR = random.uniform(0,360)
				
				newRot = Vec3(newH,newP,newR)

				setRot(obj,0,newRot)
				
				setDelay(obj,0,ENEMY_COOKIE_ERRATIC_DELAY)
				
			obj.setPos(obj,Vec3(0,ENEMY_COOKIE_VELOCITY*dt,0))
			
			prevRot = obj.getHpr()
			finalRot = getRot(obj,0)
			checkRot = [prevRot[0]-finalRot[0],prevRot[1]-finalRot[1],prevRot[2]-finalRot[2]]
			
			if checkRot[0] > 1 or checkRot[0] < -1:
				obj.setH(obj,ENEMY_COOKIE_ERRATIC_TURN*dt)
			if checkRot[1] > 0.25 or checkRot[1] < -0.25:
				obj.setP(obj,ENEMY_COOKIE_ERRATIC_TURN*dt)
			if checkRot[2] > 0.25 or checkRot[2] < -0.25:
				obj.setR(obj,ENEMY_COOKIE_ERRATIC_TURN*dt)
						
		elif tempState == "TARGETING":
			tempTarget = refNode.find("**/"+getTarget(obj))
			
			if tempTarget.isEmpty():
				obj.wrtReparentTo(refNode)
				
				setState(obj,"ERRATIC")		
				setDelay(obj,0,ENEMY_COOKIE_ERRATIC_DELAY)
				
			obj.setHpr(obj,360*dt/ENEMY_C_MONSTER_ROTATION_TIME,
						360*dt/ENEMY_C_MONSTER_ROTATION_TIME,
						360*dt/ENEMY_C_MONSTER_ROTATION_TIME)
			
		setState(obj,tempState)				
		
class EnemyManager:
	def __init__(self):
		self.enemyFactory = EnemyFactory()
		self.cookieAI = CookieAI()
		self.updateTask = taskMgr.add(self.updateAllEnemies, 'enemy-update-task')
		self.updateTask.last = 0
				
	def createNewEnemy(self,model,type,num,spreadX,spreadY,spreadZ):
		self.enemyFactory.spawnType(model,type,num,spreadX,spreadY,spreadZ)
		
	def createNewBoss(self,model,type,pos):
		self.enemyFactory.spawnBoss(model,type,pos)
	
	def killEnemy(self,obj):
		self.enemyFactory.destroy(obj)
			
	def updateAllEnemies(self,task):
		enemyNodeList = self.enemyFactory.enemyFactoryNode.findAllMatches("**/Enemy-Node*")
		countTemp = 0
		
		dt = task.time - task.last
		task.last = task.time
		
		for countTemp in range(enemyNodeList.getNumPaths()): 
			tempType = getType(enemyNodeList[countTemp])
			
			if tempType == "Cookie":
				self.cookieAI.update(enemyNodeList[countTemp],dt,self.enemyFactory.enemyCookieNode)
				
		return task.cont	    

[/code]

Going to do a rewrite of the collision detection tonight. Wish me luck.

I’ll post the changes and let you guys know whether it worked or not. If it does, I’ll give my input as to why I think it fixed it.