Entity Collision Tutorial CS381 Liesl Wigand [email protected] John Johnson [email protected] Paul Olson [email protected] This guide will explain how to add entity collision detection to your game. We started with Dr. Louis’ latest code posted on the class webpage, and we will show the changes we had to make from that code. We used the bounding boxes for detection. This works pretty well, but the collision is sometimes detected before the boats visually collide. It is evident when a ship is turning since the bounding box grows as the ship turns. You can download a copy of our project from our repository download page: http://code.google.com/p/area6-cs381/downloads/list Changes from original code: A new module named collisionManager.py was added: #Collision Manager #assume boats destroyed if collide? #boats can't collide with sinking ships (maybe change later) #import collisionManager in state #init collisionManager in state and gfx #tick it in state tick and gfx tick #have gfx use getCollisions to decide what to animate(sinking ships, smoke) #may need to add a list in gfx that keeps track of what is colliding # so that it can animate: maybe pitch or roll, and sink with smoke? #loop: while bounding box of boat intersects water plane, lower its position #by 1 or so each round, then destroy and stop smoke ####################### #check to see that references correct: # - check that ent.name is the unique name used by sceneManager/nodes # - make sure that deleteEntity works ####Deselect boat when collides: not done yet###### import random class collisionManager: def __init__(self, entities): self.entities = entities #this is a dictionary, not list self.colliders = []#what happens if more then two collide? self.colliderPairs = [] self.toggle =0 self.y = 0.3 #default rate of check def tick(self, time, dtime): #limit collision checking to be less frequent #random may be bad: starvation possible, also overunning; maybe use toggle like var? random.seed() x = random.random()#get float between 0 and 1 #if self.toggle >= 0: # self.toggle -= dtime #if self.toggle <0: #print "past toggle" # self.toggle = 0.1 if x < self.y: #iterate through list to check for collisions for name, ent in self.entities.iteritems(): ent1 = ent.gfxNode.getAttachedObject(ent.name)#this might work, check box1 = ent1.getWorldBoundingBox() #second loop to compare each ent to each other ent for names, ents in self.entities.iteritems(): if ent.name is not ents.name: #don't compare ent to itself, that's a collision, but shouldn't be ent2 = ents.gfxNode.getAttachedObject(ents.name) box2 = ent2.getWorldBoundingBox() collide = box1.intersects(box2) #add colliding bodies to the collidePairs list if collide is True: dist = ((ent.position[0]-ents.position[0])*(ent.position[0]-ents.position[0])) + ((ent.position[2]-ents.position[2])*(ent.position[2]-ents.position[2])) self.colliders.append(ent) self.colliders.append(ents) self.colliderPairs.append((ent, ents, dist)) #remove from state entities list (assume destroyed if collide) #if not destroyed, be sure to check for multiples of ents in list (or avoid) #detach aspects (so they don't keep moving with arrow keys etc.) #have to remove after iteration for ent in self.colliders: if ent.name in self.entities: ent.detachAllAspects() del self.entities[ent.name] if self.colliders: self.colliders.sort() last = self.colliders[-1] for i in range(len(self.colliders)-2, -1, -1): if last == self.colliders[i]: del self.colliders[i] else: last = self.colliders[i] #Problem: storage of colliders: -If more than one is colliding # -if boat collides with sinking ship # Need a list of colliders: when to add? When to remove from ent list? # If we want to not have multiple adds of same pairs: remove from ent list. #But if we want to have collisions of more then two: need to keep and keep checking... #check not only ent list but colliders list? def getCollisions(self): return self.colliders def getCollisionPairs(self): return self.colliderPairs CollisionManager is imported in coreSimple, and initialized in gfx and engine. It is ticked in coreSimple and guiManager (as gfx.collisionManager). There are two buttons available to increase or decrease the frequency of the collision detection. Detection can significantly slow the framerate, so it needs to be adjusted so the framerate is acceptable. Collidecheckbutton.py: #collisionButtons from ex import ePanel from ex import eLabel import ogre.io.OIS as OIS class collideCheckButton(ePanel.EPanel): def __init__(self, context): self.toggle = 0.0 self.state = context.state self.gfx = context.gfx self.mouse = context.mouse self.dim1 = (140, 20) self.pos1 = (context.gfx.renderWindow.getWidth()-140, context.gfx.renderWindow.getHeight()-20) ePanel.EPanel.__init__(self, context, name="collisionButtons", pos = self.pos1, dim = self.dim1) self.panelPlus = ePanel.EPanel(context, name = "panelPlus", pos = (1, 1), dim = (68, 18)) self.labelPlus = eLabel.ELabel(context, caption = "Rate +") self.panelPlus.addElement(self.labelPlus) self.addElement(self.panelPlus, 1) self.labelPlus.show() self.panelMinus = ePanel.EPanel(context, name = "panelMinus", pos = (70, 1), dim = (68, 18)) self.labelMinus = eLabel.ELabel(context, caption = "Rate -") self.panelMinus.addElement(self.labelMinus) self.addElement(self.panelMinus, 1) self.labelMinus.show() def tick(self, time, dtime): if self.toggle >= 0: self.toggle -= dtime if self.toggle<0: self.toggle =0.1 self.mouse.capture() cMouse = self.mouse.getMouseState() if(cMouse.buttonDown(OIS.MB_Left) and cMouse.X.abs< self.dim1[0]+self.pos1[0] and cMouse.Y.abs < self.dim1[1]+self.pos1[1] and cMouse.Y.abs > self.pos1[1] and cMouse.X.abs > self.pos1[0]): #mouse in panel area if(cMouse.X.abs<69+self.pos1[0]):#left button area = self.labelPlus.getTextArea() area.setColour((1.0, 1.0, 1.0)) self.plus() area.setColour((1.0, 1.0, 0.7)) else: area = self.labelMinus.getTextArea() area.setColour((1.0, 1.0, 1.0)) self.minus() area.setColour((1.0, 1.0, 0.7)) def plus(self): if self.gfx.collisionManager.y<0.9: self.gfx.collisionManager.y += 0.1 print "New rate: ", self.gfx.collisionManager.y def minus(self): if self.gfx.collisionManager.y>0.1: self.gfx.collisionManager.y -= 0.1 print "New rate: ", self.gfx.collisionManager.y
© Copyright 2026 Paperzz