###########################################################
# CollisionDetection - Railshooter Module
# Defines the Collision Detection Handlers
###########################################################

# DESCRIPTION:
# This Class sets up a large majority of the Collision Detection
# used in this program.  It defines the Collision Handlers, which 
# are the parts that respond to the Collisions.  In this program,
# CollisionHandlerEvent() is used.  This Collision Handler broadcasts
# Collision Events equal that can then be handled elsewhere in the 
# code.  This allows me to send messages to other parts of the program,
# indicating which objects collided into each other.  The results of these
# collisions are determined elsewhere.  

# BITMASKS:
# Bitmasks are defined to control the Collision Detection by only allowing 
# certain objects to collide into each other.  In this game, the collision
# works as follows:
# 	- Player can Collide with Enemies
# 	- Player can Collide with Enemy Bullets
# 	- Enemies can Collide with Player
# 	- Enemies can Collide with Player Bullets
#	- Enemy Bullets can Collide with Player Bullets
#	- Player Bullets can Collide with Enemy Bullets
 
# BITMASK KEY:
# 1 = Player's Bullets / Anything Crashing into Enemies
# 0 = Anything into Player (Enemies, Bullets, Ground)

# MULTIPLE COLLISION TRAVERSERS:
# Each Collision Traverser can only handle a maximum of 32
# collision objects at once.  This means that if you have more than
# 32 Colliders in the world at any given time, the Collision Detection 
# will stall or quit all together.  To get around this, I will be 
# defining multiple Collision Traversers in order to get around this
# problem.


from direct.showbase.ShowBaseGlobal import *
from direct.showbase import DirectObject

########################################
# Collision Detection Classes
########################################
class collisionDetection:
    def __init__(self):

    	########################################
    	# Setup Collision Detection Event Handler
    	########################################

    	# Set up a Event Collision Handler
    	self.collisionEvent = CollisionHandlerEvent()
    	self.collisionEvent.setInPattern("enter%in")
    	self.collisionEvent.setOutPattern("exit%in")

    	# Create a Collision Traverser for the Player 
	# and the Player's Bullets
    	self.playerTraverser = CollisionTraverser()

    	# Create a Collision Traverser for Enemy Bullets
    	self.enemyBulletTraverser = CollisionTraverser()

    	# Create a Collision Traverser for Enemy Homing Missiles
    	self.enemyMissileTraverser = CollisionTraverser()

    	# Create a Collision Traverser for Enemies
    	self.enemyTraverser = CollisionTraverser()

    	# Create a Collision Traverser for Powerups and 
	# the Player's Homing Laser Projectiles
    	self.laserTraverser = CollisionTraverser()

    	# DEBUG: Print all Events - Can be used to Monitor
	# the Collision Detection as it occurs
    	# messenger.toggleVerbose()

	# Traverses All Colliders
	taskMgr.add(self.traverseAll, 'traverseAll')


    ########################################
    # Task to Traverse all Collision Traversers
    ########################################

    # This traverses each Traverser to check for collisions.  
    # Without this Task, none of the collisions would register. 
    def traverseAll(self, task):

	# Traverse each Traverser every Frame
	self.playerTraverser.traverse(render)
	self.enemyBulletTraverser.traverse(render)
	self.enemyMissileTraverser.traverse(render)
	self.enemyTraverser.traverse(render)
	self.laserTraverser.traverse(render)

	return Task.cont

