def has_line_of_sight(point_1: Point, point_2: Point, walls: SpriteList, max_distance: int = -1, check_resolution: int = 2): """ Determine if we have line of sight between two points. Try to make sure that spatial hashing is enabled on the wall SpriteList or this will be very slow. :param Point point_1: Start position :param Point point_2: End position position :param SpriteList walls: List of all blocking sprites :param int max_distance: Max distance point 1 can see :param int check_resolution: Check every x pixels for a sprite. Trade-off between accuracy and speed. """ distance = get_distance(point_1[0], point_1[1], point_2[0], point_2[1]) steps = int(distance // check_resolution) for step in range(steps + 1): step_distance = step * check_resolution u = step_distance / distance midpoint = lerp_vec(point_1, point_2, u) if max_distance != -1 and step_distance > max_distance: return False # print(point_1, point_2, step, u, step_distance, midpoint) sprite_list = get_sprites_at_point(midpoint, walls) if len(sprite_list) > 0: return False return True
def on_update(self, delta_time): super().on_update(delta_time) # Do we have a path? if not self.path or len(self.path) == 0: print("No path for path following sprite") return # Grab the current point, and the point we are headed to x1 = self.center_x y1 = self.center_y x2 = self.path[self.cur_point][0] y2 = self.path[self.cur_point][1] # The distance between distance = arcade.get_distance(x1, y1, x2, y2) # Are we close to the destination point? If so, advance to the next point. if distance <= self.speed: self.cur_point += 1 if self.cur_point >= len(self.path): self.cur_point = 0 return # Figure out the angle between angle = math.atan2(y2 - y1, x2 - x1) # Figure out our vector given the speed self.change_x = math.cos(angle) * self.speed self.change_y = math.sin(angle) * self.speed # Move the character self.center_x += self.change_x self.center_y += self.change_y
def on_update(self, delta_time): for enemy in self.enemy_list: position = self.game_resources.player_sprite.position if arcade.get_distance(position[0], position[1], enemy.position[0], enemy.position[1]) < 500: enemy.calculate_astar() enemy.update_position()
def _move_sprite(moving_sprite: Sprite, walls: SpriteList, ramp_up: bool): # start_time = time.time() # See if we are starting this turn with a sprite already colliding with us. if len(check_for_collision_with_list(moving_sprite, walls)) > 0: _circular_check(moving_sprite, walls) original_x = moving_sprite.center_x original_y = moving_sprite.center_y original_angle = moving_sprite.angle # --- Rotate rotating_hit_list = [] if moving_sprite.change_angle: # Rotate moving_sprite.angle += moving_sprite.change_angle # Resolve collisions caused by rotating rotating_hit_list = check_for_collision_with_list(moving_sprite, walls) if len(rotating_hit_list) > 0: max_distance = (moving_sprite.width + moving_sprite.height) / 2 # Resolve any collisions by this weird kludge _circular_check(moving_sprite, walls) if get_distance(original_x, original_y, moving_sprite.center_x, moving_sprite.center_y) > max_distance: # Ok, glitched trying to rotate. Reset. moving_sprite.center_x = original_x moving_sprite.center_y = original_y moving_sprite.angle = original_angle # --- Move in the y direction moving_sprite.center_y += moving_sprite.change_y # Check for wall hit hit_list_x = check_for_collision_with_list(moving_sprite, walls) # print(f"Post-y move {hit_list_x}") complete_hit_list = hit_list_x # If we hit a wall, move so the edges are at the same point if len(hit_list_x) > 0: if moving_sprite.change_y > 0: while len(check_for_collision_with_list(moving_sprite, walls)) > 0: moving_sprite.center_y -= 1 # print(f"Spot X ({self.player_sprite.center_x}, {self.player_sprite.center_y})" # f" {self.player_sprite.change_y}") elif moving_sprite.change_y < 0: # Reset number of jumps for item in hit_list_x: while check_for_collision(moving_sprite, item): # self.player_sprite.bottom = item.top <- Doesn't work for ramps moving_sprite.center_y += 0.25 if item.change_x != 0: moving_sprite.center_x += item.change_x # print(f"Spot Y ({self.player_sprite.center_x}, {self.player_sprite.center_y})") else: pass # TODO: The code below can't execute, as "item" doesn't # exist. In theory, this condition should never be arrived at. # Collision while player wasn't moving, most likely # moving platform. # if self.player_sprite.center_y >= item.center_y: # self.player_sprite.bottom = item.top # else: # self.player_sprite.top = item.bottom moving_sprite.change_y = min(0.0, hit_list_x[0].change_y) # print(f"Spot D ({self.player_sprite.center_x}, {self.player_sprite.center_y})") moving_sprite.center_y = round(moving_sprite.center_y, 2) # print(f"Spot Q ({self.player_sprite.center_x}, {self.player_sprite.center_y})") # end_time = time.time() # print(f"Move 1 - {end_time - start_time:7.4f}") # start_time = time.time() loop_count = 0 # --- Move in the x direction if moving_sprite.change_x: # Keep track of our current y, used in ramping up almost_original_y = moving_sprite.center_y # Strip off sign so we only have to write one version of this for # both directions direction = math.copysign(1, moving_sprite.change_x) cur_x_change = abs(moving_sprite.change_x) upper_bound = cur_x_change lower_bound = 0 cur_y_change = 0 exit_loop = False while not exit_loop: loop_count += 1 # print(f"{cur_x_change=}, {upper_bound=}, {lower_bound=}, {loop_count=}") # Move sprite and check for collisions moving_sprite.center_x = original_x + cur_x_change * direction collision_check = check_for_collision_with_list( moving_sprite, walls) # Update collision list for sprite in collision_check: if sprite not in complete_hit_list: complete_hit_list.append(sprite) # Did we collide? if len(collision_check) > 0: # We did collide. Can we ramp up and not collide? if ramp_up: cur_y_change = cur_x_change moving_sprite.center_y = original_y + cur_y_change collision_check = check_for_collision_with_list( moving_sprite, walls) if len(collision_check) > 0: cur_y_change -= cur_x_change else: while (len(collision_check) == 0) and cur_y_change > 0: # print("Ramp up check") cur_y_change -= 1 moving_sprite.center_y = almost_original_y + cur_y_change collision_check = check_for_collision_with_list( moving_sprite, walls) cur_y_change += 1 collision_check = [] if len(collision_check) > 0: # print(f"Yes @ {cur_x_change}") upper_bound = cur_x_change - 1 if upper_bound - lower_bound <= 1: cur_x_change = lower_bound exit_loop = True # print(f"Exit 2 @ {cur_x_change}") else: cur_x_change = (upper_bound + lower_bound) / 2 else: exit_loop = True # print(f"Exit 1 @ {cur_x_change}") else: # No collision. Keep this new position and exit lower_bound = cur_x_change if upper_bound - lower_bound <= 1: # print(f"Exit 3 @ {cur_x_change}") exit_loop = True else: # print(f"No @ {cur_x_change}") cur_x_change = (upper_bound + lower_bound) / 2 # print(cur_x_change * direction, cur_y_change) moving_sprite.center_x = original_x + cur_x_change * direction moving_sprite.center_y = almost_original_y + cur_y_change # print(f"({moving_sprite.center_x}, {moving_sprite.center_y}) {cur_x_change * direction}, {cur_y_change}") # Add in rotating hit list for sprite in rotating_hit_list: if sprite not in complete_hit_list: complete_hit_list.append(sprite) # end_time = time.time() # print(f"Move 2 - {end_time - start_time:7.4f} {loop_count}") return complete_hit_list
def get_ball_to_goal_distance(self, player: Player): return arcade.get_distance(self.ball.x, self.ball.y, player.goal_x, player.goal_y)
def get_player_opponent_goal_distance(self, pl: Player, op: Player): return arcade.get_distance(pl.x, pl.y, op.goal_x, op.goal_x)
def get_player_goal_distance(self, player: Player): return arcade.get_distance(player.goal_x, player.goal_y, player.x, player.y)
def on_update(self, delta_time): """ Movement and game logic """ # move the player with the physics engine self.physics_engine.update() # Move the player self.player_list.update() # Update walls, used with moving platforms self.moving_plat_vertical_list.update() # Update the players animation self.player_list.update_animation() # for view port changed = False # if the player dies if self.player.hp <= 0: self.setup(self.map_change) arcade.play_sound(self.player_death_sound) # --- Manage Scrolling --- # Track if we need to change the viewport # --- Manage Combat Stuff for item in self.enemies_shoot_list: if (len(item.collides_with_list( self.wall_list)) > 0) or (arcade.get_distance( item.position[0], item.position[1], item.start_pos[0], item.start_pos[1]) > item.min_range): if item.does_stick: item.change_x = 0 item.change_y = 0 if random.randint(0, 100) < 40: self.pickup_list.append(item) self.enemies_shoot_list.remove(item) else: item.kill() else: item.kill() shot_list = arcade.check_for_collision_with_list( item, self.enemies_list) if arcade.check_for_collision(self.player, item): shot_list.append(self.player) for self.person in shot_list: arcade.play_sound(self.damage_taken_player_sound) self.person.hp -= item.damage item.kill() self.enemies_shoot_list.update() self.charge_list.update() if len(self.charge_list) == 0: MOVEMENT_SPEED = 5 else: MOVEMENT_SPEED = 2 for item in self.charge_list: if item.power <= 100: item.power += 3 else: item.power = 100 self.melee_list.update() for item in self.melee_list: item.center_x += self.player.change_x item.center_y += self.player.change_y item.life_span += 1 if item.life_span > item.attack_speed: item.kill() for bad_guy in self.enemies_list: slap_list = arcade.check_for_collision_with_list( bad_guy, self.melee_list) for item in slap_list: arcade.play_sound(self.damage_taken_enemy_sound) bad_guy.hp -= item.damage # bad_guy.kill() item.damage = 0 if bad_guy.hp <= 0: for drop in bad_guy.drop(): self.pickup_list.append(drop) arcade.play_sound(self.angry_peanut_death_sound) bad_guy.kill() # bad_guy.path = arcade.astar_calculate_path(bad_guy.position, self.player.position,self.barrier_list,False) bad_guy.chase(self.player.center_x, self.player.center_y) if arcade.check_for_collision(bad_guy, self.player): self.player.hp -= bad_guy.damage self.player.center_x += (self.player.center_x - bad_guy.center_x) self.player.center_y += (self.player.center_y - bad_guy.center_y) bump_list = arcade.check_for_collision_with_list( bad_guy, self.wall_list) if len(bump_list) > 0: bad_guy.center_x += (bad_guy.center_x - bump_list[0].center_x) bad_guy.center_y += (bad_guy.center_y - bump_list[0].center_y) self.frame_count += 1 if (self.frame_count) % (bad_guy.fire_rate * 60) == 0: if bad_guy.type == 'pion': bad_guy.has_shot = True if (bad_guy.has_shot == True): if arcade.has_line_of_sight(self.player.position, bad_guy.position, self.wall_list, 500): self.enemies_shoot_list.append( bad_guy.shoot(self.player)) bad_guy.has_shot = False elif bad_guy.type == 'boss': self.enemies_list.append(bad_guy.spawn()) pickup_hit_list = arcade.check_for_collision_with_list( self.player, self.pickup_list) for thing in pickup_hit_list: thing.kill() self.player.ammo += 1 # --- Logic for moving platforms --- for sprite in self.moving_plat_vertical_list: if sprite.boundary_top and sprite.top > sprite.boundary_top and sprite.change_y > 0: sprite.change_y *= -1 if sprite.boundary_bottom and sprite.bottom < sprite.boundary_bottom and sprite.change_y < 0: sprite.change_y *= -1 # --- Manage Scrolling --- # Scroll left left_boundary = self.view_left + LEFT_VIEWPORT_MARGIN if self.player.left < left_boundary: self.view_left -= left_boundary - self.player.left changed = True # Scroll right right_boundary = self.view_left + SCREEN_WIDTH - RIGHT_VIEWPORT_MARGIN if self.player.right > right_boundary: self.view_left += self.player.right - right_boundary changed = True # Scroll up top_boundary = self.view_bottom + SCREEN_HEIGHT - TOP_VIEWPORT_MARGIN if self.player.top > top_boundary: self.view_bottom += self.player.top - top_boundary changed = True # Scroll down bottom_boundary = self.view_bottom + BOTTOM_VIEWPORT_MARGIN if self.player.bottom < bottom_boundary: self.view_bottom -= bottom_boundary - self.player.bottom changed = True if changed: # Only scroll to integers. Otherwise we end up with pixels that # don't line up on the screen self.view_bottom = int(self.view_bottom) self.view_left = int(self.view_left) # Do the scrolling arcade.set_viewport(self.view_left, SCREEN_WIDTH + self.view_left, self.view_bottom, SCREEN_HEIGHT + self.view_bottom) for sprite in self.moving_plat_vertical_list: if arcade.check_for_collision(self.player, sprite) and \ self.player.change_y == 0: self.player.center_y = sprite.center_y # see if we touch any doors door_progress_hit_list = arcade.check_for_collision_with_list( self.player, self.doors_progress_list) if len(door_progress_hit_list) > 0: if self.map_change < 5: self.map_change += 1 else: self.map_change = 1 self.setup(self.map_change) self.view_left = 0 self.view_bottom = 0 changed = True # see if we touch any return doors door_return_hit_list = arcade.check_for_collision_with_list( self.player, self.doors_return_list) if len(door_return_hit_list) > 0: self.map_change -= 1 self.setup(self.map_change) self.view_left = 0 self.view_bottom = 0 changed = True # switches switch_hit_list = arcade.check_for_collision_with_list( self.player, self.switches_list) if len(switch_hit_list) > 0: for x in self.switch_blocks_list: x.remove_from_sprite_lists() arcade.play_sound(self.switch_sound) # keys and locked doors key_hit_list = arcade.check_for_collision_with_list( self.player, self.keys_list) if len(key_hit_list) > 0: for x in key_hit_list: x.kill() if len(self.locked_blocks_list) > 0: for y in self.locked_blocks_list: y.kill() for y in self.locked_blocks_list: y.kill() for y in self.locked_blocks_list: y.kill() for y in self.locked_blocks_list: y.kill() # hearts heart_hit_list = arcade.check_for_collision_with_list( self.player, self.hearts_list) if len(heart_hit_list) > 0: for x in heart_hit_list: x.kill() self.player.hp += 10 # breakable blocks # for block in self.breakable_blocks_list: # breakable_blocks_hit_list = arcade.check_for_collision_with_list(block, # self.melee_list) # for broken_block in breakable_blocks_hit_list: # broken_block.kill() for y in self.breakable_blocks_list: breakable_blocks_hit_list = arcade.check_for_collision_with_list( y, self.melee_list) if len(breakable_blocks_hit_list): y.kill() # dont touch dont_touch_hit_list = arcade.check_for_collision_with_list( self.player, self.dont_touch_list) if len(dont_touch_hit_list) > 0 and \ len(arcade.check_for_collision_with_list(self.player, self.moving_plat_vertical_list)) <= 0: self.setup(self.map_change) # Aiming self.player.view_position = [(self.player.center_x - self.view_left), (self.player.center_y - self.view_bottom)]
def on_update(self, delta_time): #move the player with the physics engine self.frame_count += 1 self.player_list.update_animation() self.enemy_list.update() self.physics_engine.update() self.projectile_list.update() self.charge_list.update() if len(self.enemy_list) < ENEMY_COUNT: self.enemy_list.append( enemy.Enemy(random.randint(30, 500), random.randint(30, 500))) for item in self.projectile_list: if (len(item.collides_with_list( self.wall_list)) > 0) or (arcade.get_distance( item.position[0], item.position[1], item.start_pos[0], item.start_pos[1]) > item.min_range): if item.does_stick: item.change_x = 0 item.change_y = 0 if random.randint(0, 100) < 40: self.pickup_list.append(item) self.projectile_list.remove(item) else: item.kill() else: item.kill() shot_list = arcade.check_for_collision_with_list( item, self.enemy_list) if arcade.check_for_collision(self.player_sprite, item): shot_list.append(self.player_sprite) for person in shot_list: person.hp -= item.damage item.kill() if len(self.charge_list) == 0: MOVEMENT_SPEED = 5 else: MOVEMENT_SPEED = 2 for item in self.charge_list: if item.power <= 100: item.power += 3 else: item.power = 100 self.melee_list.update() for item in self.melee_list: item.center_x += self.player_sprite.change_x item.center_y += self.player_sprite.change_y item.life_span += 1 if item.life_span > item.attack_speed: item.kill() if len(arcade.check_for_collision_with_list(item, self.wall_list)) > 0: item.kill() for bad_guy in self.enemy_list: slap_list = arcade.check_for_collision_with_list( bad_guy, self.melee_list) for item in slap_list: bad_guy.hp -= item.damage # bad_guy.kill() item.damage = 0 if bad_guy.hp <= 0: for drop in bad_guy.drop(): self.pickup_list.append(drop) bad_guy.kill() bad_guy.path = arcade.astar_calculate_path( bad_guy.position, self.player_sprite.position, self.barrier_list, False) try: bad_guy.chase(bad_guy.path[0][0], bad_guy.path[0][1]) except IndexError: self.player_sprite.hp -= bad_guy.damage except Exception as e: print(e) if (self.frame_count) % (bad_guy.fire_rate * 60) == 0: bad_guy.has_shot = True if (bad_guy.has_shot == True): if arcade.has_line_of_sight(self.player_sprite.position, bad_guy.position, self.wall_list, 500): self.projectile_list.append( bad_guy.shoot(self.player_sprite)) bad_guy.has_shot = False # print(bad_guy.path,"->", self.player_sprite.position) #calculate speed based on the keys pressed self.player_sprite.change_x = 0 self.player_sprite.change_y = 0 if self.up_pressed and not self.down_pressed: self.player_sprite.change_y = MOVEMENT_SPEED elif self.down_pressed and not self.up_pressed: self.player_sprite.change_y = -MOVEMENT_SPEED elif self.left_pressed and not self.right_pressed: self.player_sprite.change_x = -MOVEMENT_SPEED elif self.right_pressed and not self.left_pressed: self.player_sprite.change_x = MOVEMENT_SPEED #see if we hit any coins pickup_hit_list = arcade.check_for_collision_with_list( self.player_sprite, self.pickup_list) #loop through each coin we hit (if any) and remove it for thing in pickup_hit_list: # #Remove the coin thing.remove_from_sprite_lists() # #play a sound # arcade.play_sound(self.collect_coin_sound) # #Add one to the score self.ammo += 1
def on_update(self, delta_time): """ Movement and game logic """ # move the player with the physics engine self.physics_engine.update() # Move the player self.player_list.update() # Update the players animation self.player_list.update_animation() # for view port changed = False # see if we touch any doors door_hit_list = arcade.check_for_collision_with_list( self.player, self.doors_progress_list) if len(door_hit_list) > 0: self.map_change += 1 self.setup(self.map_change) self.view_left = 0 self.view_bottom = 0 changed = True # --- Manage Scrolling --- # Track if we need to change the viewport # --- Manage Combat Stuff for item in self.enemies_shoot_list: if (len(item.collides_with_list( self.wall_list)) > 0) or (arcade.get_distance( item.position[0], item.position[1], item.start_pos[0], item.start_pos[1]) > item.min_range): if item.does_stick: item.change_x = 0 item.change_y = 0 if random.randint(0, 100) < 40: self.pickup_list.append(item) self.enemies_shoot_list.remove(item) else: item.kill() else: item.kill() shot_list = arcade.check_for_collision_with_list( item, self.enemy_list) if arcade.check_for_collision(self.player, item): shot_list.append(self.player) for person in shot_list: person.hp -= item.damage item.kill() if len(self.charge_list) == 0: MOVEMENT_SPEED = 5 else: MOVEMENT_SPEED = 2 for item in self.charge_list: if item.power <= 100: item.power += 3 else: item.power = 100 self.melee_list.update() for item in self.melee_list: item.center_x += self.player.change_x item.center_y += self.player.change_y item.life_span += 1 if item.life_span > item.attack_speed: item.kill() if len(arcade.check_for_collision_with_list(item, self.wall_list)) > 0: item.kill() for bad_guy in self.enemy_list: slap_list = arcade.check_for_collision_with_list( bad_guy, self.melee_list) for item in slap_list: bad_guy.hp -= item.damage # bad_guy.kill() item.damage = 0 if bad_guy.hp <= 0: for drop in bad_guy.drop(): self.pickup_list.append(drop) bad_guy.kill() # bad_guy.path = arcade.astar_calculate_path(bad_guy.position, self.player.position,self.barrier_list,False) bad_guy.chase(self.player.center_x, self.player.center_y) if arcade.check_for_collision(bad_guy, self.player): self.player.hp -= bad_guy.damage self.player.center_x += (self.player.center_x - bad_guy.center_x) self.player.center_y += (self.player.center_y - bad_guy.center_y) bump_list = arcade.check_for_collision_with_list( bad_guy, self.wall_list) if len(bump_list) > 0: bad_guy.center_x += (bad_guy.center_x - bump_list[0].center_x) bad_guy.center_y += (bad_guy.center_y - bump_list[0].center_y) if (self.frame_count) % (bad_guy.fire_rate * 60) == 0: bad_guy.has_shot = True if (bad_guy.has_shot == True): if arcade.has_line_of_sight(self.player.position, bad_guy.position, self.wall_list, 500): self.enemies_shoot_list.append( bad_guy.shoot(self.player)) bad_guy.has_shot = False # print(bad_guy.path,"->", self.player.position) #calculate speed based on the keys pressed self.player.change_x = 0 self.player.change_y = 0 if self.up_pressed and not self.down_pressed: self.player.change_y = MOVEMENT_SPEED elif self.down_pressed and not self.up_pressed: self.player.change_y = -MOVEMENT_SPEED elif self.left_pressed and not self.right_pressed: self.player.change_x = -MOVEMENT_SPEED elif self.right_pressed and not self.left_pressed: self.player.change_x = MOVEMENT_SPEED pickup_hit_list = arcade.check_for_collision_with_list( self.player, self.pickup_list) for thing in pickup_hit_list: thing.kill() self.player.ammo += 1 # Scroll left left_boundary = self.view_left + LEFT_VIEWPORT_MARGIN if self.player.left < left_boundary: self.view_left -= left_boundary - self.player.left changed = True # Scroll right right_boundary = self.view_left + SCREEN_WIDTH - RIGHT_VIEWPORT_MARGIN if self.player.right > right_boundary: self.view_left += self.player.right - right_boundary changed = True # Scroll up top_boundary = self.view_bottom + SCREEN_HEIGHT - TOP_VIEWPORT_MARGIN if self.player.top > top_boundary: self.view_bottom += self.player.top - top_boundary changed = True # Scroll down bottom_boundary = self.view_bottom + BOTTOM_VIEWPORT_MARGIN if self.player.bottom < bottom_boundary: self.view_bottom -= bottom_boundary - self.player.bottom changed = True if changed: # Only scroll to integers. Otherwise we end up with pixels that # don't line up on the screen self.view_bottom = int(self.view_bottom) self.view_left = int(self.view_left) # Do the scrolling arcade.set_viewport(self.view_left, SCREEN_WIDTH + self.view_left, self.view_bottom, SCREEN_HEIGHT + self.view_bottom)