def _move_sprite(moving_sprite: arcade.Sprite, walls: arcade.SpriteList): # Rotate moving_sprite.angle += moving_sprite.change_angle hit_list = check_for_collision_with_list(moving_sprite, walls) if len(hit_list) > 0: # Resolve any collisions by this weird kludge _circular_check(moving_sprite, walls) # --- 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}") # 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 check_for_collision_with_list(moving_sprite, walls): moving_sprite.center_y -= 1 elif moving_sprite.change_y < 0: while check_for_collision_with_list(moving_sprite, walls): moving_sprite.center_y += 1 was_falling = (abs(moving_sprite.change_y) > abs( moving_sprite.engine.gravity_constant)) if was_falling: # they have been moving for more than one frame play_sound_effect('impact') moving_sprite.change_y = min(0.0, hit_list_x[0].change_y) moving_sprite.center_y = round(moving_sprite.center_y, 2) # --- Move in the x direction moving_sprite.center_x += moving_sprite.change_x check_again = True while check_again: check_again = False # Check for wall hit hit_list_y = check_for_collision_with_list(moving_sprite, walls) # If we hit a wall, move so the edges are at the same point if len(hit_list_y) > 0: change_x = moving_sprite.change_x if change_x > 0: while check_for_collision_with_list(moving_sprite, walls): moving_sprite.center_x -= 1 elif change_x < 0: while check_for_collision_with_list(moving_sprite, walls): moving_sprite.center_x += 1 else: raise AssertionError( "Error, x collision while player wasn't moving.\n" "Make sure you aren't calling multiple updates, like " "a physics engine update and an all sprites list update.")
def sprite_update(self, vec: Vector, spr: arcade.Sprite, tex: int): """ Updates pos, and tex_index """ spr.center_x = vec.x * self._scale spr.center_y = vec.y * self._scale spr.set_texture(tex) spr.width = self._scale spr.height = self._scale
def _circular_check(player: arcade.Sprite, walls: arcade.SpriteList): """Guess our way out of a collision.""" original_x = player.center_x original_y = player.center_y vary = 1 while True: last_x = player.center_x last_y = player.center_y try_list = [ [original_x + vary, original_y], [original_x - vary, original_y], ] for my_item in try_list: x, y = my_item player.center_x = x player.center_y = y check_hit_list = check_for_collision_with_list(player, walls) if len(check_hit_list) == 0: return vary += 1 player.center_x = last_x player.center_y = last_y
def generate_sprites(map_object: TiledMap, layer_name: str, scaling: float, base_directory="") -> SpriteList: """ generate_sprites has been deprecated. Use arcade.tilemap.process_layer instead. Generate the sprites for a layer in a map. :param TiledMap map_object: Map previously read in from read_tiled_map function :param layer_name: Name of the layer we want to generate sprites from. Case sensitive. :param scaling: Scaling factor. :param base_directory: Directory to read images from. Defaults to current directory. :return: List of sprites :rtype: SpriteList """ sprite_list = SpriteList() if layer_name not in map_object.layers_int_data: print(f"Warning, no layer named '{layer_name}'.") return sprite_list map_array = map_object.layers_int_data[layer_name] # Loop through the layer and add in the wall list for row_index, row in enumerate(map_array): for column_index, item in enumerate(row): if str(item) in map_object.global_tile_set: tile_info = map_object.global_tile_set[str(item)] tmx_file = base_directory + tile_info.source my_sprite = Sprite(tmx_file, scaling) my_sprite.center_x = column_index * ( map_object.tilewidth * scaling) - map_object.tilewidth / 2 * scaling my_sprite.center_y = (map_object.height - row_index) * ( map_object.tileheight * scaling) - map_object.tileheight / 2 * scaling if tile_info.points is not None: my_sprite.set_points(tile_info.points) sprite_list.append(my_sprite) elif item != 0: print(f"Warning, could not find {item} image to load.") return sprite_list
def key_place_success(self, key_placed_successfully: bool, normal_key: arcade.Sprite, x_list: List[int], y_list: List[int]): """ Use recursion to check if key place is successful Attrs: key_placed_successfully(bool): break statement of the recursion function normal_key(arcade.Sprite): a key Sprite x_list: List[int]: all the x coordinates of the keys has been created y_list: List[int]: all the y coordinates of the keys has been created Return: the position of the key (x, y) """ if key_placed_successfully: return normal_key.center_x, normal_key.center_y normal_key.center_x = random.randrange(1500) normal_key.center_y = random.randrange(1500) # See if the key is hitting a wall, hitting another key, or too close from each other wall_hit_list = arcade.check_for_collision_with_list( normal_key, self.wall_list) key_hit_list = arcade.check_for_collision_with_list( normal_key, self.key_list) flag = True for item_x in x_list: if abs(int(item_x - normal_key.center_x)) < 30: flag = False for item_y in y_list: if abs(int(item_y - normal_key.center_y)) < 20: flag = False if len(wall_hit_list) == 0 and len(key_hit_list) == 0 and flag: key_placed_successfully = True return self.key_place_success(key_placed_successfully, normal_key, x_list, y_list)
def _move_sprite(moving_sprite: Sprite, walls: SpriteList, ramp_up: bool): # Rotate moving_sprite.angle += moving_sprite.change_angle hit_list = check_for_collision_with_list(moving_sprite, walls) if len(hit_list) > 0: # Resolve any collisions by this weird kludge _circular_check(moving_sprite, walls) # --- 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})") # --- Move in the x direction moving_sprite.center_x += moving_sprite.change_x check_again = True while check_again: check_again = False # Check for wall hit hit_list_y = check_for_collision_with_list(moving_sprite, walls) complete_hit_list = hit_list_x for sprite in hit_list_y: if sprite not in complete_hit_list: complete_hit_list.append(sprite) # If we hit a wall, move so the edges are at the same point if len(hit_list_y) > 0: change_x = moving_sprite.change_x if change_x > 0: if ramp_up: for _ in hit_list_y: # print(f"Spot 1 ({self.player_sprite.center_x}, {self.player_sprite.center_y})") # See if we can "run up" a ramp moving_sprite.center_y += change_x if len( check_for_collision_with_list( moving_sprite, walls)) > 0: # No, ramp run-up doesn't work. moving_sprite.center_y -= change_x moving_sprite.center_x -= 1 # print(f"Spot R ({self.player_sprite.center_x}, {self.player_sprite.center_y})") check_again = True break # else: # print("Run up ok 1") # print(f"Spot 2 ({self.player_sprite.center_x}, {self.player_sprite.center_y})") else: while len( check_for_collision_with_list( moving_sprite, walls)) > 0: moving_sprite.center_x -= 1 elif change_x < 0: if ramp_up: for item in hit_list_y: # See if we can "run up" a ramp moving_sprite.center_y -= change_x if len( check_for_collision_with_list( moving_sprite, walls)) > 0: # Can't run up the ramp, reverse moving_sprite.center_y += change_x moving_sprite.left = max(item.right, moving_sprite.left) # print(f"Reverse 1 {item.right}, {self.player_sprite.left}") # Ok, if we were shoved back to the right, we need to check this whole thing again. check_again = True break # print(f"Spot 4 ({self.player_sprite.center_x}, {self.player_sprite.center_y})") else: while len( check_for_collision_with_list( moving_sprite, walls)) > 0: moving_sprite.center_x += 1 else: print( "Error, x collision while player wasn't moving.\n" "Make sure you aren't calling multiple updates, like " "a physics engine update and an all sprites list update.") # print(f"Spot E ({self.player_sprite.center_x}, {self.player_sprite.center_y})") return complete_hit_list
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 placeSprite(sprite: Sprite, center_x: float, center_y: float): sprite.center_x = center_x sprite.center_y = center_y