class QBlock(Entity): def __init__(self, x, y, type): super(QBlock, self).__init__(x, y, 16, 16) self.active = False if type == 0: self.sprite = Sprite(self.x, self.y, SpriteType.Q_BLOCK_0) else: self.sprite = Sprite(self.x, self.y, SpriteType.Q_BLOCK_1) self.sprite.increment_sprite_y(16) self.active = True def toggle(self): self.active = not self.active if self.active: self.sprite.increment_sprite_y(16) else: self.sprite.increment_sprite_y(-16) def update(self, delta_time, scene_data): pass def draw(self, surface): if globals.debugging: self.sprite.draw(surface, CameraType.DYNAMIC) draw_rectangle(surface, self.bounds, CameraType.DYNAMIC, self.color, 2) else: self.sprite.draw(surface, CameraType.DYNAMIC)
class Crab(Kinetic): def __init__(self, x, y): super(Crab, self).__init__(x, y, 11, 9, 25) self.sprite = Sprite(self.x - 18, self.y - 19, SpriteType.CRAB) self.walk_animation = Animation(4, 4, 150) self.direction = Direction.RIGHT self.area = None self.query_result = None self.default_jump_height = 16 * 1.5 self.jump_duration = 0.5 self.jump_initial_velocity = 0 self.gravity = 0 self.lateral_acceleration = 0 self.aggravated_move_speed = 100 self.internal_bounds = Rect(self.x + 5, self.y + 5, 1, 1) self.grounded = False self.aggravated = False self.dead = False def set_location(self, x, y): super(Crab, self).set_location(x, y) self.sprite.set_location(self.x - 18, self.y - 19) self.internal_bounds = Rect(self.x + 5, self.y + 5, 1, 1) def toggle_aggravation(self): if self.dead: return self.aggravated = not self.aggravated def squish(self): self.dead = True self.velocity.y = -self.jump_initial_velocity * 0.75 self.velocity.x = - \ self.move_speed if randint(1, 10) % 2 == 0 else self.move_speed def _calculate_scaled_speed(self, delta_time): if self.aggravated: self.move_speed = self.aggravated_move_speed * delta_time else: self.move_speed = self.default_move_speed * delta_time time = 1 / delta_time * self.jump_duration self.jump_initial_velocity = 4 * self.default_jump_height / time self.gravity = 8 * self.default_jump_height / time**2 def _apply_force(self, delta_time): self.velocity.y += self.gravity if self.direction == Direction.RIGHT: self.velocity.x = self.move_speed if self.direction == Direction.LEFT: self.velocity.x = -self.move_speed self.set_location(self.x + self.velocity.x, self.y + self.velocity.y) def _update_collision_rectangles(self): self.collision_width = 3 self.collision_rectangles = [ Rect(self.x + 2, self.y - self.collision_width * 2, self.width - 4, self.collision_width * 2), Rect(self.x + 2, self.y + self.height, self.width - 4, self.collision_width * 2), Rect(self.x - self.collision_width, self.y + self.collision_width, self.collision_width, self.height - self.collision_width * 2), Rect(self.x + self.width, self.y + self.collision_width, self.collision_width, self.height - self.collision_width * 2) ] def __rectanlge_collision_logic(self, entity): # Bottom if self.velocity.y < 0 and self.collision_rectangles[0].colliderect( entity.bounds): self.set_location(self.x, entity.bounds.bottom) self.velocity.y = 0 # Top if self.velocity.y > 0 and self.collision_rectangles[1].colliderect( entity.bounds): self.set_location(self.x, entity.bounds.top - self.bounds.height) self.velocity.y = 0 self.grounded = True # Right if self.velocity.x < 0 and self.collision_rectangles[2].colliderect( entity.bounds): self.set_location(entity.bounds.right, self.y) self.velocity.x = 0 self.direction = Direction.RIGHT # Left if self.velocity.x > 0 and self.collision_rectangles[3].colliderect( entity.bounds): self.set_location(entity.bounds.left - self.bounds.width, self.y) self.velocity.x = 0 self.direction = Direction.LEFT def _collision(self, scene_data): if self.dead: return if self.x < 3: self.set_location(3, self.y) self.velocity.x = 0 self.direction = Direction.RIGHT if self.x + self.width > scene_data.scene_bounds.width: self.set_location(scene_data.scene_bounds.width - self.width, self.y) self.velocity.x = 0 self.direction = Direction.LEFT if self.y > scene_data.scene_bounds.height + 64: self.squish() self.area = Rect(self.x - 16, self.y - 16, self.width + 16 * 2, self.height + 16 * 2) self.query_result = scene_data.entity_quad_tree.query(self.area) self.grounded = False for e in self.query_result: if e is self: continue if isinstance(e, Block): self.__rectanlge_collision_logic(e) self._update_collision_rectangles() elif isinstance(e, QBlock): if e.active: if not self.dead and self.internal_bounds.colliderect( e.bounds): self.squish() self.__rectanlge_collision_logic(e) self._update_collision_rectangles() self.query_result = scene_data.kinetic_quad_tree.query(self.area) for e in self.query_result: if e is self: continue if isinstance(e, Crab): self.__rectanlge_collision_logic(e) self._update_collision_rectangles() def __update_ai(self, scene_data): if self.dead: if self.y > scene_data.scene_bounds.height + 64: self.remove = True if self.aggravated: if self.grounded: self.velocity.y = -self.jump_initial_velocity def __update_animation(self, delta_time): self.walk_animation.update(delta_time) self.sprite.set_frame(self.walk_animation.current_frame, self.walk_animation.columns) if self.aggravated: self.sprite.increment_sprite_y(32) if self.dead: self.sprite.flip_vertically(True) def update(self, delta_time, scene_data): self._calculate_scaled_speed(delta_time) self.__update_ai(scene_data) self._apply_force(delta_time) self._update_collision_rectangles() self._collision(scene_data) self.__update_animation(delta_time) def draw(self, surface): if globals.debugging: self._draw_collision_rectangles(surface) draw_rectangle(surface, self.bounds, CameraType.DYNAMIC, self.color) else: self.sprite.draw(surface, CameraType.DYNAMIC)