From 2f792397537948633069990a8905b325a53a65b5 Mon Sep 17 00:00:00 2001 From: Paul V Craven Date: Fri, 9 Oct 2026 10:29:00 -0500 Subject: [PATCH] Remove outdated and duplicate names from the arcade namespace Removes AnimatedWalkingSprite (already documented as deprecated) and the FACE_* constants only it used, and get_game_controllers, a duplicate of get_joysticks whose name suggested it returned game controllers. Also drops the duplicate draw_lrbt_rectangle_filled/outline entries in arcade.__all__. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 10 +- arcade/__init__.py | 15 -- arcade/joysticks.py | 15 +- arcade/sprite/__init__.py | 12 -- arcade/sprite/animated.py | 163 +----------------- arcade/sprite/enums.py | 4 - .../sprite/test_sprite_animated_walking.py | 94 ---------- .../unit/sprite/test_sprite_init_arguments.py | 3 - util/update_quick_index.py | 1 - 9 files changed, 13 insertions(+), 304 deletions(-) delete mode 100644 arcade/sprite/enums.py delete mode 100644 tests/unit/sprite/test_sprite_animated_walking.py diff --git a/CHANGELOG.md b/CHANGELOG.md index dbb2502c08..00a2e12997 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,13 +51,17 @@ Arcade [PyPi Release History](https://pypi.org/project/arcade/#history) page. - Fixed `InputManager.parse()` raising `AttributeError`, so a saved input configuration couldn't be loaded. ### Breaking Changes +- Removed outdated and duplicate names from the `arcade` namespace ([#2402](https://github.com/pythonarcade/arcade/issues/2402)): + - `AnimatedWalkingSprite` and the `FACE_UP`, `FACE_DOWN`, `FACE_LEFT` and `FACE_RIGHT` constants it used. Its docs already called it deprecated and said to write your own sprite class instead. The `sprite_move_animation` example shows how. + - `get_game_controllers()`, which did the same as `get_joysticks()`. Its name suggested it returned game controllers, but it returned joysticks. For game controllers, use `get_controllers()`. + - `draw_lrbt_rectangle_filled` and `draw_lrbt_rectangle_outline` were each listed twice in `arcade.__all__`. - The default font is now Liberation Sans, which comes with Arcade, instead of whichever of Calibri and Arial the computer has ([#1135](https://github.com/pythonarcade/arcade/issues/1135)). Text looks the same on every computer. It applies to `Text`, `draw_text()`, `create_text_sprite()`, `TextPool`, and the GUI's `UILabel`, `UITextArea`, `UIInputText` and buttons (which still use Kenney Future first if you load the Kenney fonts). Liberation Sans has the same letter widths as Arial, so text on Windows, which used Calibri, is about 10% wider. For the old look, pass `font_name=("calibri", "arial")`. - The Liberation fonts load the first time one is used, so `font_name="Liberation Mono"` works without `load_liberation_fonts()`. - `UITextArea` and `UIInputText` accept font file paths and resource handles for `font_name`, like `Text`. - `arcade.load_tilemap()` and `TileMap` now give every layer's sprite list a spatial hash by default (`use_spatial_hash=True`) ([#2663](https://github.com/pythonarcade/arcade/issues/2663)). Forgetting it on a wall layer made collision checks against it much slower: 100 bullets checked against 2,000 wall tiles took 48 ms per frame without it and 0.6 ms with it. A hash makes moving a layer's sprites slower, so for a layer whose sprites move a lot, such as moving platforms, turn it off with `layer_options={"Moving Platforms": {"use_spatial_hash": False}}`, or for the whole map with `use_spatial_hash=False`. - `layer_options` now warns about option names it doesn't know, which it used to ignore. The performance tips page named the option `"use_spatial_hashing"`; it's `"use_spatial_hash"`. -- `Sprite`, `BasicSprite`, `SpriteSolidColor`, `SpriteCircle`, `TextureAnimationSprite` and `AnimatedWalkingSprite` raise `TypeError` for keyword arguments they don't accept, instead of silently ignoring them. For example, `Sprite(path, hit_box_algorithm=...)` used to do nothing; set the hit box algorithm when loading the texture instead. `Sprite` now takes `visible` as a named argument. - - `SpriteSolidColor`, `SpriteCircle`, `TextureAnimationSprite` and `AnimatedWalkingSprite` now pass extra keyword arguments on to `Sprite`, so arguments such as `angle` and `visible` work. They used to be dropped. +- `Sprite`, `BasicSprite`, `SpriteSolidColor`, `SpriteCircle` and `TextureAnimationSprite` raise `TypeError` for keyword arguments they don't accept, instead of silently ignoring them. For example, `Sprite(path, hit_box_algorithm=...)` used to do nothing; set the hit box algorithm when loading the texture instead. `Sprite` now takes `visible` as a named argument. + - `SpriteSolidColor`, `SpriteCircle` and `TextureAnimationSprite` now pass extra keyword arguments on to `Sprite`, so arguments such as `angle` and `visible` work. They used to be dropped. - This found arguments that had silently done nothing: tilemap image layers passed `filename` and `hit_box_algorithm`, animated tiles passed `path_or_texture`, and platform tutorial steps 19 and 20 passed `scaling` instead of `scale`, so their bullets were drawn at full size instead of 80%. - `arcade.math.get_angle_degrees()` now measures clockwise from straight up, like `Sprite.angle`: 0 is up, 90 is right, 180 is down and -90 is left. It used to measure clockwise from the right, which disagreed with `get_angle_radians()`, which already measured from up ([#2754](https://github.com/pythonarcade/arcade/issues/2754)). The two now always give the same angle in different units. A sprite whose image points up faces a point with `sprite.angle = get_angle_degrees(...)`. For the old value, subtract 90. - Fixed the `sprite_rotate_around_tank` example's corrected barrel, which sat 90 degrees off from the mouse, and updated `turn_and_move` for the new angles. `turn_and_move`'s sprite also now stops when moving straight along an axis, which it never did. @@ -85,7 +89,7 @@ Arcade [PyPi Release History](https://pypi.org/project/arcade/#history) page. - Type checking with mypy and pyright now fails the CI check, like formatting and linting. Their existing errors are fixed. - Fixed code excerpts in the docs that highlighted or showed the wrong lines, because the example code had changed since their line numbers were set. This covers 62 excerpts: 48 in the platformer, pymunk platformer, menu, card game, compute shader, raycasting and shader toy glow tutorials, and 14 on example pages. Most now highlight the same code they were written for. Where the code was rewritten, they highlight the code that does the same job now. - Removed `arcade/experimental/perspective_parallax.py`, an unreferenced demo of `PerspectiveProjector` that didn't show a parallax effect. The `background_parallax` example shows parallax scrolling. -- Sped up `import arcade` from about 2.7 to 0.9 seconds on Windows ([#1159](https://github.com/pythonarcade/arcade/issues/1159)). Most of the time went to pyglet looking for game controllers when imported. Arcade now imports the controller code the first time `get_controllers()`, `ControllerManager`, `get_joysticks()` or `get_game_controllers()` is used, so the wait happens then instead. Sound still loads at import, so playing the first sound doesn't pause the game. +- Sped up `import arcade` from about 2.7 to 0.9 seconds on Windows ([#1159](https://github.com/pythonarcade/arcade/issues/1159)). Most of the time went to pyglet looking for game controllers when imported. Arcade now imports the controller code the first time `get_controllers()`, `ControllerManager` or `get_joysticks()` is used, so the wait happens then instead. Sound still loads at import, so playing the first sound doesn't pause the game. - Arcade's extra controller mappings now load at the same time. Code that calls `pyglet.input.get_controllers()` directly without using Arcade's controller functions first only gets pyglet's own mappings. ## 4.0.0.dev8 diff --git a/arcade/__init__.py b/arcade/__init__.py index 278328a468..d22152f72f 100644 --- a/arcade/__init__.py +++ b/arcade/__init__.py @@ -141,7 +141,6 @@ def configure_logging(level: int | None = None): # Game controllers are imported on first use, because pyglet lists the # input devices when imported. See __getattr__ at the bottom of this file. if TYPE_CHECKING: - from .joysticks import get_game_controllers from .joysticks import get_joysticks from .controller import ControllerManager from .controller import get_controllers @@ -162,13 +161,8 @@ def configure_logging(level: int | None = None): from .sound import play_sound from .sound import stop_sound -from .sprite import FACE_DOWN -from .sprite import FACE_LEFT -from .sprite import FACE_RIGHT -from .sprite import FACE_UP from .sprite import TextureAnimationSprite from .sprite import load_animated_gif -from .sprite import AnimatedWalkingSprite from .sprite import TextureAnimation from .sprite import TextureKeyframe from .sprite import PyMunk @@ -283,16 +277,11 @@ def configure_logging(level: int | None = None): "PSControllerButtons", "XBoxControllerButtons", "AStarBarrierList", - "AnimatedWalkingSprite", "TextureAnimationSprite", "TextureAnimation", "TextureKeyframe", "ArcadeContext", "ControllerManager", - "FACE_DOWN", - "FACE_LEFT", - "FACE_RIGHT", - "FACE_UP", "MOUSE_BUTTON_LEFT", "MOUSE_BUTTON_MIDDLE", "MOUSE_BUTTON_RIGHT", @@ -361,8 +350,6 @@ def configure_logging(level: int | None = None): "draw_line_strip", "draw_lines", "draw_lrbt_rectangle_filled", - "draw_lrbt_rectangle_filled", - "draw_lrbt_rectangle_outline", "draw_lrbt_rectangle_outline", "draw_parabola_filled", "draw_parabola_outline", @@ -388,7 +375,6 @@ def configure_logging(level: int | None = None): "get_distance_between_sprites", "get_sprites_in_rect", "get_controllers", - "get_game_controllers", "get_image", "get_joysticks", "get_pixel", @@ -450,7 +436,6 @@ def configure_logging(level: int | None = None): if not headless: _LAZY_IMPORTS = { "get_joysticks": "joysticks", - "get_game_controllers": "joysticks", "joysticks": "joysticks", "ControllerManager": "controller", "get_controllers": "controller", diff --git a/arcade/joysticks.py b/arcade/joysticks.py index 826d1690e0..31e2358ca2 100644 --- a/arcade/joysticks.py +++ b/arcade/joysticks.py @@ -1,20 +1,15 @@ import pyglet.input from pyglet.input import Joystick -__all__ = ["get_joysticks", "get_game_controllers"] +__all__ = ["get_joysticks"] def get_joysticks() -> list[Joystick]: """ - Get a list of all the game controllers + Get a list of all the joysticks. - This is an alias of :func:`get_game_controllers`, which is better worded. + These are pyglet :py:class:`~pyglet.input.Joystick` objects, which give + raw access to the axes and buttons. For game controllers with named + buttons and sticks, use :py:func:`arcade.get_controllers` instead. """ return pyglet.input.get_joysticks() # type: ignore # pending https://github.com/pyglet/pyglet/issues/842 - - -def get_game_controllers() -> list[Joystick]: - """ - Get a list of all the game controllers - """ - return get_joysticks() diff --git a/arcade/sprite/__init__.py b/arcade/sprite/__init__.py index 611ae41c0d..f40c991b3c 100644 --- a/arcade/sprite/__init__.py +++ b/arcade/sprite/__init__.py @@ -11,15 +11,8 @@ TextureAnimationSprite, TextureAnimation, TextureKeyframe, - AnimatedWalkingSprite, ) from .colored import SpriteSolidColor, SpriteCircle -from .enums import ( - FACE_LEFT, - FACE_RIGHT, - FACE_UP, - FACE_DOWN, -) def load_animated_gif(resource_name: str | Path) -> TextureAnimationSprite: @@ -76,13 +69,8 @@ def load_animated_gif(resource_name: str | Path) -> TextureAnimationSprite: "TextureAnimationSprite", "TextureAnimation", "TextureKeyframe", - "AnimatedWalkingSprite", "load_animated_gif", "SpriteSolidColor", "SpriteCircle", - "FACE_LEFT", - "FACE_RIGHT", - "FACE_UP", - "FACE_DOWN", "PymunkMixin", ] diff --git a/arcade/sprite/animated.py b/arcade/sprite/animated.py index 9828b12cdf..42da56c3b5 100644 --- a/arcade/sprite/animated.py +++ b/arcade/sprite/animated.py @@ -1,16 +1,8 @@ import bisect import logging -import math from arcade import Texture -from arcade.types import Point2 - -from .enums import ( - FACE_DOWN, - FACE_LEFT, - FACE_RIGHT, - FACE_UP, -) + from .sprite import Sprite logger = logging.getLogger("arcade") @@ -211,156 +203,3 @@ def update_animation(self, delta_time: float = 1 / 60, **kwargs) -> None: if index != self._current_keyframe_index: self._current_keyframe_index = index self.texture = keyframe.texture - - -class AnimatedWalkingSprite(Sprite): - """ - Deprecated Sprite for platformer games that supports walking animations. - Make sure to call update_animation after loading the animations so the - initial texture can be set. Or manually set it. - - It is highly recommended you create your own version of this class rather than - try to use this pre-packaged one. - - For an example, see this section of the platformer tutorial: - :ref:`platformer_part_twelve`. - - Args: - scale: - Initial scale of the sprite. - center_x: - Initial x position of the sprite. - center_y: - Initial y position of the sprite. - **kwargs: - Passed to :py:class:`~arcade.Sprite`, such as ``angle``, ``scale`` or ``visible``. - """ - - def __init__( - self, - scale: float | Point2 = 1.0, - center_x: float = 0.0, - center_y: float = 0.0, - **kwargs, - ): - super().__init__( - None, - scale=scale, - center_x=center_x, - center_y=center_y, - **kwargs, - ) - self.state = FACE_RIGHT - self.stand_right_textures: list[Texture] = [] - self.stand_left_textures: list[Texture] = [] - self.walk_left_textures: list[Texture] = [] - self.walk_right_textures: list[Texture] = [] - self.walk_up_textures: list[Texture] = [] - self.walk_down_textures: list[Texture] = [] - self.cur_texture_index = 0 - self.texture_change_distance = 20 - self.last_texture_change_center_x: float = 0.0 - self.last_texture_change_center_y: float = 0.0 - - def update_animation(self, delta_time: float = 1 / 60) -> None: - """ - Logic for texture animation. - - Args: - delta_time: Time since last update. - """ - x1 = self.center_x - x2 = self.last_texture_change_center_x - y1 = self.center_y - y2 = self.last_texture_change_center_y - distance = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) - texture_list: list[Texture] = [] - - change_direction = False - if ( - self.change_x > 0 - and self.change_y == 0 - and self.state != FACE_RIGHT - and len(self.walk_right_textures) > 0 - ): - self.state = FACE_RIGHT - change_direction = True - elif ( - self.change_x < 0 - and self.change_y == 0 - and self.state != FACE_LEFT - and len(self.walk_left_textures) > 0 - ): - self.state = FACE_LEFT - change_direction = True - elif ( - self.change_y < 0 - and self.change_x == 0 - and self.state != FACE_DOWN - and len(self.walk_down_textures) > 0 - ): - self.state = FACE_DOWN - change_direction = True - elif ( - self.change_y > 0 - and self.change_x == 0 - and self.state != FACE_UP - and len(self.walk_up_textures) > 0 - ): - self.state = FACE_UP - change_direction = True - - if self.change_x == 0 and self.change_y == 0: - if self.state == FACE_LEFT: - self.texture = self.stand_left_textures[0] - elif self.state == FACE_RIGHT: - self.texture = self.stand_right_textures[0] - elif self.state == FACE_UP: - self.texture = self.walk_up_textures[0] - elif self.state == FACE_DOWN: - self.texture = self.walk_down_textures[0] - - elif change_direction or distance >= self.texture_change_distance: - self.last_texture_change_center_x = self.center_x - self.last_texture_change_center_y = self.center_y - - if self.state == FACE_LEFT: - texture_list = self.walk_left_textures - if texture_list is None or len(texture_list) == 0: - raise RuntimeError( - "update_animation was called on a sprite that doesn't have a " - "list of walk left textures." - ) - elif self.state == FACE_RIGHT: - texture_list = self.walk_right_textures - if texture_list is None or len(texture_list) == 0: - raise RuntimeError( - "update_animation was called on a sprite that doesn't have a list of " - "walk right textures." - ) - elif self.state == FACE_UP: - texture_list = self.walk_up_textures - if texture_list is None or len(texture_list) == 0: - raise RuntimeError( - "update_animation was called on a sprite that doesn't have a list of " - "walk up textures." - ) - elif self.state == FACE_DOWN: - texture_list = self.walk_down_textures - if texture_list is None or len(texture_list) == 0: - raise RuntimeError( - "update_animation was called on a sprite that doesn't " - "have a list of walk down textures." - ) - - self.cur_texture_index += 1 - if self.cur_texture_index >= len(texture_list): - self.cur_texture_index = 0 - - self.texture = texture_list[self.cur_texture_index] - - if self._texture is None: - logger.warning("Error, no texture set") - else: - self.width = self._texture.width * self.scale_x - self.height = self._texture.height * self.scale_y diff --git a/arcade/sprite/enums.py b/arcade/sprite/enums.py deleted file mode 100644 index 3239c9af73..0000000000 --- a/arcade/sprite/enums.py +++ /dev/null @@ -1,4 +0,0 @@ -FACE_RIGHT = 1 -FACE_LEFT = 2 -FACE_UP = 3 -FACE_DOWN = 4 diff --git a/tests/unit/sprite/test_sprite_animated_walking.py b/tests/unit/sprite/test_sprite_animated_walking.py deleted file mode 100644 index 2f46d06366..0000000000 --- a/tests/unit/sprite/test_sprite_animated_walking.py +++ /dev/null @@ -1,94 +0,0 @@ -import arcade - -COIN_SCALE = 0.5 -frame_count = 0 - - -def test_update_animation_preserves_scale_y(): - # update_animation must size height from scale_y, not scale_x, so a - # non-uniform scale is preserved (regression: scale_y was clobbered). - texture = arcade.Texture.create_empty("test-scale", (10, 20)) - sprite = arcade.AnimatedWalkingSprite(scale=(2.0, 3.0)) - sprite.stand_right_textures = [texture] - sprite.texture = texture - sprite.change_x = 0 - sprite.change_y = 0 - - sprite.update_animation() - - assert tuple(sprite.scale) == (2.0, 3.0) - assert sprite.width == 20.0 - assert sprite.height == 60.0 - - -def test_sprite_animated_old(window: arcade.Window): - global frame_count - frame_count = 0 - SCREEN_WIDTH = window.width - SCREEN_HEIGHT = window.height - window.background_color = arcade.color.AMAZON - - character_list = arcade.SpriteList() - - player = arcade.AnimatedWalkingSprite() - - player.scale = 1.0 - player.stand_right_textures = [] - player.stand_right_textures.append( - arcade.load_texture( - ":resources:images/animated_characters/female_person/femalePerson_idle.png" - ) - ) - player.stand_left_textures = [tex.flip_left_right() for tex in player.stand_right_textures] - - player.walk_right_textures = [] - - player.walk_right_textures.append( - arcade.load_texture( - ":resources:images/animated_characters/female_person/femalePerson_walk0.png" - ) - ) - player.walk_right_textures.append( - arcade.load_texture( - ":resources:images/animated_characters/female_person/femalePerson_walk1.png" - ) - ) - player.walk_right_textures.append( - arcade.load_texture( - ":resources:images/animated_characters/female_person/femalePerson_walk2.png" - ) - ) - player.walk_right_textures.append( - arcade.load_texture( - ":resources:images/animated_characters/female_person/femalePerson_walk3.png" - ) - ) - - player.walk_left_textures = [tex.flip_left_right() for tex in player.walk_right_textures] - - player.texture_change_distance = 20 - - player.center_x = SCREEN_WIDTH // 2 - player.center_y = SCREEN_HEIGHT // 2 - player.scale = 0.8 - player.change_x = 2 - player.texture = player.stand_left_textures[0] - - character_list.append(player) - - def on_draw(): - window.clear() - character_list.draw() - - def update(delta_time): - global frame_count - frame_count += 1 - if frame_count == 70: - player.change_x *= -1 - - character_list.update() - character_list.update_animation(delta_time) - - window.on_draw = on_draw - window.on_update = update - window.test(150) diff --git a/tests/unit/sprite/test_sprite_init_arguments.py b/tests/unit/sprite/test_sprite_init_arguments.py index a04dc15304..85de6b1e8a 100644 --- a/tests/unit/sprite/test_sprite_init_arguments.py +++ b/tests/unit/sprite/test_sprite_init_arguments.py @@ -15,7 +15,6 @@ lambda: arcade.SpriteSolidColor(10, 10, colour=(255, 0, 0)), lambda: arcade.SpriteCircle(5, arcade.color.RED, bogus=1), lambda: arcade.TextureAnimationSprite(bogus=1), - lambda: arcade.AnimatedWalkingSprite(bogus=1), ], ids=[ "Sprite", @@ -23,7 +22,6 @@ "SpriteSolidColor", "SpriteCircle", "TextureAnimationSprite", - "AnimatedWalkingSprite", ], ) def test_unknown_keyword_argument_raises(make): @@ -50,4 +48,3 @@ def test_subclasses_pass_sprite_arguments_on(): assert arcade.SpriteCircle(5, arcade.color.RED, angle=30).angle == 30 assert arcade.SpriteSolidColor(10, 10, visible=False).visible is False assert arcade.TextureAnimationSprite(angle=45).angle == 45 - assert arcade.AnimatedWalkingSprite(angle=90, visible=False).angle == 90 diff --git a/util/update_quick_index.py b/util/update_quick_index.py index 2c4f6228b9..da54efd882 100644 --- a/util/update_quick_index.py +++ b/util/update_quick_index.py @@ -100,7 +100,6 @@ "arcade.sprite.colored", "arcade.sprite.mixins", "arcade.sprite.animated", - "arcade.sprite.enums", ], }, "sprite_list.rst": {