def __init__(self, origin_centre_pos, facing_direction, fov=90.0, length=1000.0): self.facing_direction = Vector2(facing_direction[:]) self.origin_centre_position = Vector2(origin_centre_pos[:]) self.field_of_view = math.radians(fov) self.length = length self.length_squared = length ** 2 self.epsilon = 0.075 # to handle floating point inaccuracy at small values (I think) self.arc_epsilon = 1.5 # to handle small gaps between arc points self.halfAuxRayTilt = 8.72664625995e-3 # half degree in radians self.half_aux_ray_tilt_cos = math.cos(self.halfAuxRayTilt) # 0.999961923064 self.half_aux_ray_tilt_sin = math.sin(self.halfAuxRayTilt) # 8.72653549837e-3 self.collision_circle = CollisionCircle(self.origin_centre_position.x, self.origin_centre_position.y, self.length, {CollisionType.WORLD_SOLID: CollisionNoHandler(), CollisionType.WORLD_JUMP_THROUGH: CollisionNoHandler(), CollisionType.WORLD_PLATFORM_EDGE: CollisionNoHandler(), CollisionType.WORLD_JUMP_THROUGH_EDGE: CollisionNoHandler()}, CollisionType.VIEW_CONE, [CollisionType.WORLD_SOLID, CollisionType.WORLD_JUMP_THROUGH, CollisionType.WORLD_PLATFORM_EDGE, CollisionType.WORLD_JUMP_THROUGH_EDGE] ) self.neg_cos_fov = math.cos(-self.field_of_view / 2) self.neg_sin_fov = math.sin(-self.field_of_view / 2) self.sin_fov = math.sin(self.field_of_view / 2) self.cos_fov = math.cos(self.field_of_view / 2) self.perp_facing_cos = math.cos(math.radians(90)) self.perp_facing_sin = math.sin(math.radians(90)) self.angle_points_array = [] self.rays = [] self.hit_points = [] self.ctrl_points = [] self.blocking_edges = [] self.perp_facing_vec = None self.cone_extent_facings = None self.on_cone_changed_direction() self.end_positions = None self.on_cone_moved() self.fov_edges = [Edge("min", Vector2(self.origin_centre_position), Vector2(self.end_positions[0])), Edge("max", Vector2(self.origin_centre_position), Vector2(self.end_positions[1]))] self.timing_clock = pygame.time.Clock()
def __init__(self, start_pos, initial_heading_vector, damage, collision_grid, *groups): super().__init__(*groups) self.collision_grid = collision_grid self.image_name = "images/arrow.png" self.original_image = pygame.image.load(self.image_name) self.image = self.original_image.copy() self.rect = self.image.get_rect() self.rect.center = start_pos self.current_vector = [initial_heading_vector[0], initial_heading_vector[1]] self.position = [float(self.rect.center[0]), float(self.rect.center[1])] self.world_position = [float(self.rect.center[0]), float(self.rect.center[1])] self.should_die = False self.bullet_speed = 300.0 self.damage = damage self.shot_range = 1000.0 self.collision_rect = CollisionRect(self.rect, 0, {GameCollisionType.MONSTER: CollisionNoHandler(), GameCollisionType.TILE: CollisionNoHandler()}, GameCollisionType.PLAYER_WEAPON, [GameCollisionType.MONSTER, GameCollisionType.TILE]) self.collision_rect.set_owner(self) self.collision_grid.add_new_shape_to_grid(self.collision_rect)
def __init__(self, position, tile_angle, tile_data, layer, collision_grid, *groups): super().__init__(*groups) self.collision_grid = collision_grid self.group_tile_data = tile_data self.tile_data = tile_data self.world_position = [position[0], position[1]] self.position = [position[0], position[1]] self.angle = tile_angle self.collide_radius = self.group_tile_data.collide_radius self.collidable = self.group_tile_data.collidable self.tile_id = self.group_tile_data.tile_id self.image = pygame.transform.rotate(self.group_tile_data.tile_image, self.angle) self.rect = self.image.get_rect() self.rect.center = self.position self.is_visible = False self.layer = layer self.drawable_collision_shape = None if self.collidable: self.collision_shape = CompositeCollisionShape( self.world_position[0], self.world_position[1], (self.rect.width, self.rect.height), { GameCollisionType.MONSTER: CollisionRubHandler(), GameCollisionType.PLAYER: CollisionRubHandler(), GameCollisionType.PLAYER_WEAPON: CollisionNoHandler(), GameCollisionType.MONSTER_WEAPON: CollisionNoHandler() }, GameCollisionType.TILE, [ GameCollisionType.MONSTER, GameCollisionType.PLAYER, GameCollisionType.PLAYER_WEAPON, GameCollisionType.MONSTER_WEAPON ]) for shape in self.tile_data.collision_shapes: if shape[0] == "rect": self.collision_shape.add_rotatable_rect(shape[2].copy(), 0) if shape[0] == "circle": self.collision_shape.add_circle(shape[1][0], shape[1][1], shape[3]) self.collision_shape.set_owner(self) self.collision_grid.add_new_shape_to_grid(self.collision_shape) self.drawable_collision_shape = DrawableCompositeShape( self.collision_shape)
def __init__(self, x, y, shape_type, aabb_rect, handlers_by_colliding_game_type=None, game_type=None, game_types_to_collide=None): if game_types_to_collide is None: game_types_to_collide = [] if handlers_by_colliding_game_type is None: handlers_by_colliding_game_type = {None: CollisionNoHandler()} self.next_shape_in_grid_square_index = -1 self.text_id = "" self.x = float(x) self.y = float(y) self.type = shape_type self.current_grid_pos = [0, 0] self.nearby_grid_range_x = [0, 0] self.nearby_grid_range_y = [0, 0] self.collided_shapes_this_frame = [ ] # Intended so games can tell if two objects collided in the last frame self.collided_shapes_this_loop = [ ] # Used by collision handlers to check if they should to keep iterating self.loop_mtv_vectors_by_shape = {} self.frame_mtv_vectors_by_shape = {} self.owner = None self.game_types_to_collide = game_types_to_collide self.game_type = game_type self.handlers_by_colliding_game_type = handlers_by_colliding_game_type self.num_squares_to_search_around_grid_pos = 1 self.aabb_rect = aabb_rect # overridden by base classes, this is essentially # the smallest size of height/width for an axis aligned square that will # fit this shape self.longest_aab_square_dimension = 0 # this is the shortest distance between the centre of the shape and any edge/corner # helpful when assessing the maximum distance we can safely move a colliding shape in one frame. self.shortest_centre_to_edge = 0 self.moved_since_last_collision_test = True self.print_collision_stages = False
def __init__(self, start_pos, image, type_name, collision_grid, *groups): super().__init__(*groups) self.collision_grid = collision_grid self.world_position = [start_pos[0], start_pos[1]] self.type_name = type_name self.image = image self.rect = self.image.get_rect() self.rect.center = start_pos self.position = [ float(self.rect.center[0]), float(self.rect.center[1]) ] self.should_die = False self.collide_radius = 8 self.collision_circle = CollisionCircle( self.position[0], self.position[1], self.collide_radius, {GameCollisionType.PLAYER: CollisionNoHandler()}, GameCollisionType.PICKUP, [GameCollisionType.PLAYER]) self.collision_circle.set_owner(self) self.collision_grid.add_new_shape_to_grid(self.collision_circle)
def __init__(self, grid_size, grid_pixel_size): self.grid_square_pixel_size = grid_pixel_size self.grid_size = grid_size self.grid = [] self.all_dynamic_collision_shapes = [] # shapes that move around # special case shapes that fit in a single grid square and stay there # no need to move these around grid or test them against # other shapes - moving shapes will test against them self.static_grid_aligned_collision_shapes = [] self.shapes_collided_this_frame = [] self.shapes_collided_this_loop = [] self.rub_handler = CollisionRubHandler() self.no_handler = CollisionNoHandler() # fill empty grid for x_axis in range(0, self.grid_size[0]): column = [] for y_axis in range(0, self.grid_size[1]): column.append(GridSquare()) self.grid.append(column)
def __init__(self, monster_id, start_pos, sprite_map, all_monster_sprites, play_area, tiled_level, collision_grid, *groups): super().__init__(*groups) self.id = monster_id self.start_pos = start_pos self.play_area = play_area self.tiled_level = tiled_level self.score = 100 self.xp = 25 self.collision_grid = collision_grid self.point_cost = 10 # point cost if self.id == "goblin": self.sprite_map_row = 0 self.walk_cycle_length = 4 elif self.id == "ent": self.sprite_map_row = 1 self.walk_cycle_length = 8 elif self.id == "spider": self.sprite_map_row = 2 self.walk_cycle_length = 7 self.anim_stand = sprite_map[0][self.sprite_map_row] self.walk_anim_speed = 64.0 / self.walk_cycle_length self.walk_cycle = [] for anim_index in range(0, self.walk_cycle_length): self.walk_cycle.append(sprite_map[anim_index][self.sprite_map_row]) self.attack_time_delay = 0.5 self.sprite_rot_centre_offset = [0.0, 0.0] self.image = self.anim_stand.copy() # self.sprite = pygame.sprite.Sprite() self.test_collision_sprite = pygame.sprite.Sprite() self.rect = self.image.get_rect() self.rect.center = self.start_pos self.position = [float(self.rect.center[0]), float(self.rect.center[1])] self.screen_position = [0, 0] self.screen_position[0] = self.position[0] self.screen_position[1] = self.position[1] self.collide_radius = 20 # we do collisions in world space self.collision_circle = CollisionCircle(self.position[0], self.position[1], self.collide_radius, {GameCollisionType.PLAYER_WEAPON: CollisionNoHandler(), GameCollisionType.TILE: CollisionRubHandler(), GameCollisionType.PLAYER: CollisionRubHandler(), GameCollisionType.MONSTER: CollisionRubHandler()}, GameCollisionType.MONSTER, [GameCollisionType.PLAYER_WEAPON, GameCollisionType.TILE, GameCollisionType.PLAYER, GameCollisionType.MONSTER]) self.collision_circle.set_owner(self) self.collision_grid.add_new_shape_to_grid(self.collision_circle) self.drawable_circle = DrawableCollisionCircle(self.collision_circle) self.update_screen_position(self.tiled_level.position_offset) self.change_direction_time = 5.0 self.change_direction_accumulator = 0.0 self.next_way_point = self.get_random_point_in_radius_of_point([500, 400], 96) x_dist = float(self.next_way_point[0]) - float(self.position[0]) y_dist = float(self.next_way_point[1]) - float(self.position[1]) self.distance_to_next_way_point = math.sqrt((x_dist * x_dist) + (y_dist * y_dist)) self.current_vector = [x_dist / self.distance_to_next_way_point, y_dist / self.distance_to_next_way_point] self.old_facing_angle = 0.0 self.rotate_sprite(self) self.should_die = False self.is_dead = False self.sprite_needs_update = True self.all_monster_sprites = all_monster_sprites self.is_on_screen = False self.health = 100 self.slow_down_percentage = 1.0 self.is_wandering_aimlessly = True self.random_target_change_time = random.uniform(3.0, 15.0) self.random_target_change_acc = 0.0 self.time_to_home_in_on_player = False self.monster_home_on_target_time = random.uniform(0.3, 1.5) self.monster_home_on_target_acc = 0.0 self.is_time_to_start_attack = True self.attack_time_acc = 0.0 self.attack_time_delay = 3.0 self.is_attacking = False self.should_do_attack_damage = False self.attack_anim_acc = 0.0 self.attack_anim_total_time = 0.8 self.attack_damage = 15 self.sprite_flash_acc = 0.0 self.sprite_flash_time = 0.15 self.should_flash_sprite = False self.active_flash_sprite = False self.flash_sprite = pygame.sprite.Sprite() self.player_distance = 1000 self.air_timer = 0.0 self.air_velocity_vector = [0.0, 0.0] self.attack_range = 86.0 self.collision_obj_rects = [] self.collision_obj_rect = pygame.Rect(0.0, 0.0, 2.0, 2.0) self.max_coll_handling_attempts = 10 self.move_accumulator = 0.0 self.move_speed = 0.0 self.idle_move_speed = 0.0 self.attack_move_speed = 0.0
def test_cone(): pygame.init() screen = pygame.display.set_mode((800, 600)) background = pygame.Surface((800, 600)) background.fill(pygame.Color("#000000")) running = True view_cone = ViewCone([400, 300], [1.0, 0.0], fov=60, length=200) test_rect = CollisionRect(pygame.Rect((310, 400), (30, 30)), 0, {CollisionType.VIEW_CONE: CollisionNoHandler()}, CollisionType.WORLD_SOLID, [CollisionType.VIEW_CONE] ) drawable_test_rect = DrawableCollisionRect(test_rect) test_rect_2 = CollisionRect(pygame.Rect((340, 400), (30, 30)), 0, {CollisionType.VIEW_CONE: CollisionNoHandler()}, CollisionType.WORLD_SOLID, [CollisionType.VIEW_CONE] ) drawable_test_rect_2 = DrawableCollisionRect(test_rect_2) drawable_test_circle = DrawableCollisionCircle(view_cone.collision_circle) test_rect.normals["right"].should_skip = True test_rect_2.normals["left"].should_skip = True test_points = [] for _ in range(0, 1000): test_points.append(pygame.math.Vector2(float(random.randint(10, 790)), float(random.randint(10, 590)))) clock = pygame.time.Clock() while running: clock.tick(60) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1: mouse_pos = pygame.mouse.get_pos() vec_to_mouse = [mouse_pos[0] - view_cone.origin_centre_position[0], mouse_pos[1] - view_cone.origin_centre_position[1]] length = math.sqrt(vec_to_mouse[0] ** 2 + vec_to_mouse[1] ** 2) if length > 0.0: vec_to_mouse_norm = Vector2(vec_to_mouse[0] / length, vec_to_mouse[1] / length) view_cone.set_facing_direction(vec_to_mouse_norm) if event.button == 3: view_cone.set_position(Vector2(pygame.mouse.get_pos())) screen.blit(background, (0, 0)) view_cone.update() for point in test_points: if view_cone.is_subject_visible(point): pygame.draw.line(screen, pygame.Color("#0000FF"), point, [point.x + 1, point.y + 1], 2) else: pygame.draw.line(screen, pygame.Color("#FF0000"), point, [point.x + 1, point.y + 1], 2) if collide_circle_with_rotated_rectangle(view_cone.collision_circle, test_rect): test_rect.add_frame_collided_shape(view_cone.collision_circle) view_cone.collision_circle.add_frame_collided_shape(test_rect) else: test_rect.clear_frame_collided_shapes() view_cone.collision_circle.clear_frame_collided_shapes() if collide_circle_with_rotated_rectangle(view_cone.collision_circle, test_rect_2): test_rect_2.add_frame_collided_shape(view_cone.collision_circle) view_cone.collision_circle.add_frame_collided_shape(test_rect_2) else: test_rect_2.clear_frame_collided_shapes() view_cone.collision_circle.clear_frame_collided_shapes() drawable_test_rect.update_collided_colours() drawable_test_rect_2.update_collided_colours() drawable_test_circle.update_collided_colours() drawable_test_rect.draw(screen) drawable_test_rect_2.draw(screen) # drawable_test_circle.draw(screen) view_cone.draw(screen) pygame.display.flip()
def __init__(self, character, start_pos, tiled_level, control_scheme, hud_buttons, collision_grid, projectile_sprite_group, player_sprites): super().__init__(player_sprites) self.collision_grid = collision_grid self.player_sprites = player_sprites self.character = character self.xp = 0 self.level = 1 self.score = 0 self.scheme = control_scheme self.image_name = "images/player_2.png" self.original_image = pygame.image.load(self.image_name) self.sprite_sheet = self.original_image.copy() self.hud_buttons = hud_buttons self.player_world_target = [0.0, 0.0] # ------------------------------------------ # Add new weapon objects here # ------------------------------------------ self.bow_weapon = BowWeapon(self, self.sprite_sheet, self.collision_grid, projectile_sprite_group) self.sword_weapon = SwordWeapon(self, self.sprite_sheet, self.collision_grid, projectile_sprite_group) self.magic_weapon = MagicWeapon(self, self.sprite_sheet) self.active_weapon = self.bow_weapon for button in self.hud_buttons: if button.button_image_name == "bow_icon": button.set_selected() else: button.clear_selected() # self.sprite = pygame.sprite.Sprite() self.test_collision_sprite = pygame.sprite.Sprite() self.flash_sprite = pygame.sprite.Sprite() self.image = self.active_weapon.anim_set.stand self.rect = self.active_weapon.anim_set.stand.get_rect() self.rect.center = start_pos self.sprite_rot_centre_offset = [0.0, 11.0] self.speed = 0.0 self.acceleration = 200.0 self.max_speed = 250.0 self.collide_radius = 18 self.max_health = 100 + (50 * self.level * (self.character.strength / 20)) self.health = self.max_health self.max_mana = 50.0 + (50.0 * self.level * (self.character.magic / 20)) self.mana = self.max_mana self.mana_recharge = 1.0 + (1.0 * self.level * (self.character.magic / 20)) self.should_die = False self.move_accumulator = 0.0 self.position = [float(self.rect.center[0]), float(self.rect.center[1])] self.player_move_target = self.position self.distance_to_move_target = 0.0 self.current_vector = [0.0, -1.0] self.new_facing_angle = 0 self.screen_position = [0, 0] self.screen_position[0] = self.position[0] self.screen_position[1] = self.position[1] self.update_screen_position(tiled_level.position_offset) direction_magnitude = math.sqrt(self.current_vector[0] ** 2 + self.current_vector[1] ** 2) if direction_magnitude > 0.0: unit_dir_vector = [self.current_vector[0] / direction_magnitude, self.current_vector[1] / direction_magnitude] self.new_facing_angle = math.atan2(-unit_dir_vector[0], -unit_dir_vector[1]) * 180 / math.pi self.old_facing_angle = self.new_facing_angle self.rect.center = self.rot_point([self.screen_position[0], self.screen_position[1] + self.sprite_rot_centre_offset[1]], self.screen_position, -self.new_facing_angle) self.left_mouse_held = False self.right_mouse_held = False self.per_bullet_damage = 25 self.player_fire_target = [10000, 10000] self.switch_to_bow = False self.switch_to_sword = False self.switch_to_magic = False self.sprite_flash_acc = 0.0 self.sprite_flash_time = 0.15 self.should_flash_sprite = False self.sprite_flashing = False self.is_collided = False self.firing = False self.firing_timer = 0.0 self.has_new_high_score = False self.should_draw_collision_obj = False self.collision_obj_rects = [] self.collision_obj_rect = pygame.Rect(0.0, 0.0, 2.0, 2.0) self.world_click_pos = [0, 0] # we do collisions in world space self.collision_circle = CollisionCircle(self.position[0], self.position[1], self.collide_radius, {GameCollisionType.MONSTER_WEAPON: CollisionNoHandler(), GameCollisionType.TILE: CollisionRubHandler(), GameCollisionType.MONSTER: CollisionRubHandler(), GameCollisionType.PICKUP: CollisionNoHandler()}, GameCollisionType.PLAYER, [GameCollisionType.MONSTER_WEAPON, GameCollisionType.TILE, GameCollisionType.MONSTER, GameCollisionType.PICKUP]) self.collision_circle.set_owner(self) self.collision_grid.add_new_shape_to_grid(self.collision_circle) self.drawable_circle = DrawableCollisionCircle(self.collision_circle)