def box2box_collision(collider_a, collider_b): # offset the collision boxes relative to their transform positions get_relative_rect_pos(collider_a.entity.transform.position, collider_a) get_relative_rect_pos(collider_b.entity.transform.position, collider_b) # check for collision if collider_a.box.colliderect(collider_b.box): return True return False
def debug(self, e): transform = e.transform # if we have nothing to draw on then return if transform is None: return display = self.world.engine.display # ------- Debug info -------- # x_origin = self.world.origin.x y_origin = self.world.origin.y x = transform.position.x y = transform.position.y # adjust for the camera if self.camera is not None: x -= self.camera.transform.position.x y -= self.camera.transform.position.y collider = e.collider rigid_body = e.rigid_body # transform origin crosshair pygame.draw.line(display, (255, 0, 0), (x-50, y), (x+50, y)) pygame.draw.line(display, (255, 0, 0), (x, y-50), (x, y+50)) # draw position vector relative to the world origin pygame.draw.line(display, (50, 50, 50), (x_origin, y_origin), (x, y)) if rigid_body is not None: # obtain a fraction of the velocity vector length = Vector2.get_scaled_by(rigid_body.velocity, 0.2) xend = x + length.x yend = y + length.y # draw the velocity vector of the rigid pygame.draw.line(display, (0, 255, 0), (x, y), (xend, yend)) # represent mass # larger circle means more mass mass = rigid_body.mass # scale down the mass mass /= 4 # mask surface to match the size of the mass circle transparency_mask = pygame.Surface((mass*2, mass*2)) # fill surface with a color mask and set the color key color_mask = (123, 54, 33) transparency_mask.fill(color_mask) transparency_mask.set_colorkey(color_mask) # draw circle to the transparency mask mass = int(mass) pygame.draw.circle(transparency_mask, (0, 100, 255), (mass, mass), mass) # change alpha transparency_mask.set_alpha(100) # draw transparency mask to the display display.blit(transparency_mask, (int(x)-mass, int(y)-mass)) # box collider if collider is not None: if collider.tag == BoxCollider.tag: # get relative position to transform get_relative_rect_pos(transform.position, collider) # center the box image x -= collider.box.width/2 y -= collider.box.height/2 # render based on the offset of the collider as well x_offset = collider.offset.x y_offset = collider.offset.y box = Rect(x+x_offset, y+y_offset, collider.box.width, collider.box.height) tol = Rect(x+x_offset, y+y_offset, collider.tolerance_hitbox.width, collider.tolerance_hitbox.height) tol.center = box.center # display collider rect properties color = (255, 255, 255) if collider.is_trigger: color = (0, 255, 255) pygame.draw.rect(display, color, box, 1) pygame.draw.rect(display, (255, 0, 0), tol, 1) pygame.draw.circle(display, (0, 255, 0), box.center, 3) pygame.draw.circle(display, (0, 255, 255), box.topleft, 5) elif collider.tag == CircleCollider.tag: radius = collider.radius pygame.draw.circle(display, (255, 255, 255), (int(x), int(y)), radius, 1)
def process(self, entities): # save the collisions of the past frame #PhysicsSystem.past_collisions = PhysicsSystem.collision_queue[:] # empty the collision queue del PhysicsSystem.collision_queue[:] for eA in entities: # ignore disabled entities if eA.disabled: continue transform_a = eA.transform collider_a = eA.collider rigid_body_a = eA.rigid_body valid_collider = collider_a is not None # if there is a collider attached to the entity, then make sure that the # entity also has a rigid body to modify or if the collider should trigger a collision event. consider_entity = False if valid_collider: consider_entity = rigid_body_a is not None or collider_a.treat_as_dynamic if valid_collider and consider_entity: # Move the rigid body if rigid_body_a is not None: self._integrate_motion(transform_a, rigid_body_a) # Find another entity that it may collide with for eB in entities: if eB.disabled: continue transform_b = eB.transform collider_b = eB.collider # Check that coll_comp_b is valid and that coll_comp_a is not colliding with itself if collider_b is not None and eA is not eB: collision_occurred = False # A flag to tell the physics systems not to apply physics or collision # resolution on the entity if this collider collides with another collider. b_isnt_trigger = not collider_b.is_trigger # box to box collision if collider_a.tag == BoxCollider.tag and collider_b.tag == BoxCollider.tag: # check for collision if PhysicsSystem.box2box_collision(collider_a, collider_b): collision_occurred = True if rigid_body_a is not None and b_isnt_trigger: PhysicsSystem.box2box_response(collider_a, collider_b) # circle to circle collision elif collider_a.tag == CircleCollider.tag and collider_b.tag == CircleCollider.tag: # check if circles collided if PhysicsSystem._circle2circle_collision(collider_a, collider_b): collision_occurred = True if rigid_body_a is not None and b_isnt_trigger: PhysicsSystem.circle2circle_response(collider_a, collider_b) # circle to box elif collider_a.tag == CircleCollider.tag and collider_b.tag == BoxCollider.tag: # create a temporary box collider associated to A box_collider_a = BoxCollider(collider_a.radius*2, collider_a.radius*2) box_collider_a.entity = collider_a.entity box_collider_a.restitution = collider_a.restitution box_collider_a.surface_friction = collider_a.surface_friction # Get the relative collision box positions to their transforms. get_relative_rect_pos(transform_a.position, box_collider_a) get_relative_rect_pos(transform_b.position, collider_b) # check for collision if PhysicsSystem._circle2box_collision(collider_a, collider_b): collision_occurred = True if rigid_body_a is not None and b_isnt_trigger: PhysicsSystem.box2box_response(box_collider_a, collider_b) if collision_occurred: # add collision event into the queue PhysicsSystem.collision_queue.append((eA, eB)) # call the collision inside the scripts for s in eA.scripts: s.collision_event(collider_b) for s in eB.scripts: s.collision_event(collider_a)
def process(self, entities): # save the collisions of the past frame #PhysicsSystem.past_collisions = PhysicsSystem.collision_queue[:] # empty the collision queue del PhysicsSystem.collision_queue[:] for eA in entities: # ignore disabled entities if eA.disabled: continue transform_a = eA.transform collider_a = eA.collider rigid_body_a = eA.rigid_body valid_collider = collider_a is not None # if there is a collider attached to the entity, then make sure that the # entity also has a rigid body to modify or if the collider should trigger a collision event. consider_entity = False if valid_collider: consider_entity = rigid_body_a is not None or collider_a.treat_as_dynamic if valid_collider and consider_entity: # Move the rigid body if rigid_body_a is not None: self._integrate_motion(transform_a, rigid_body_a) # Find another entity that it may collide with for eB in entities: if eB.disabled: continue transform_b = eB.transform collider_b = eB.collider # Check that coll_comp_b is valid and that coll_comp_a is not colliding with itself if collider_b is not None and eA is not eB: collision_occurred = False # A flag to tell the physics systems not to apply physics or collision # resolution on the entity if this collider collides with another collider. b_isnt_trigger = not collider_b.is_trigger a_isnt_trigger = not collider_a.is_trigger # box to box collision if collider_a.tag == BoxCollider.tag and collider_b.tag == BoxCollider.tag: # check for collision if PhysicsSystem.box2box_collision(collider_a, collider_b): collision_occurred = True if rigid_body_a is not None and b_isnt_trigger and a_isnt_trigger: PhysicsSystem.box2box_response(collider_a, collider_b) # circle to circle collision elif collider_a.tag == CircleCollider.tag and collider_b.tag == CircleCollider.tag: # check if circles collided if PhysicsSystem._circle2circle_collision(collider_a, collider_b): collision_occurred = True if rigid_body_a is not None and b_isnt_trigger and a_isnt_trigger: PhysicsSystem.circle2circle_response(collider_a, collider_b) # circle to box elif collider_a.tag == CircleCollider.tag and collider_b.tag == BoxCollider.tag: # create a temporary box collider associated to A box_collider_a = BoxCollider(collider_a.radius*2, collider_a.radius*2) box_collider_a.entity = collider_a.entity box_collider_a.restitution = collider_a.restitution box_collider_a.surface_friction = collider_a.surface_friction # Get the relative collision box positions to their transforms. get_relative_rect_pos(transform_a.position, box_collider_a) get_relative_rect_pos(transform_b.position, collider_b) # check for collision if PhysicsSystem._circle2box_collision(collider_a, collider_b): collision_occurred = True if rigid_body_a is not None and b_isnt_trigger and a_isnt_trigger: PhysicsSystem.box2box_response(box_collider_a, collider_b) if collision_occurred: # add collision event into the queue PhysicsSystem.collision_queue.append((eA, eB)) # call the collision inside the scripts for s in eA.scripts: s.collision_event(collider_b) for s in eB.scripts: s.collision_event(collider_a)