Sprite Rotation Around a Point

Screen shot of 2 uses for rotating a sprite around a point

This non-interactive example demonstrates two applications of rotating a sprite around a point:

  1. On the left, a beam spinning around a point in a circle

  2. On the right, a platform rotating around a point while staying flat

Although this behavior is inspired by platformers, it could be useful for other types of games.

The base class used in this example offers circular movement with finer control than the one in Collect Coins that are Moving in a Circle.

For a related example demonstrating how to mix rotation around a point with user input, see Move By Keyboard, Fire Towards Mouse.

sprite_rotate_around_point.py
  1"""
  2Rotating Sprites Around Points
  3
  4Two minimal examples demonstrating how to rotate sprites around points
  5and how you might apply them in a game.
  6
  7Artwork from https://kenney.nl
  8
  9If Python and Arcade are installed, this example can be run from the command line with:
 10python -m arcade.examples.sprite_rotate_around_point
 11"""
 12import arcade
 13from arcade.math import rotate_point
 14
 15WINDOW_WIDTH = 1280
 16WINDOW_HEIGHT = 720
 17QUARTER_WIDTH = WINDOW_WIDTH // 4
 18HALF_HEIGHT = WINDOW_HEIGHT // 2
 19
 20
 21WINDOW_TITLE = "Rotating Sprites Around Points"
 22
 23
 24class RotatingSprite(arcade.Sprite):
 25    """
 26    This sprite subclass implements a generic rotate_around_point method.
 27    """
 28
 29    def rotate_around_point(self, point, degrees, change_angle=True):
 30        """
 31        Rotate the sprite around a point by the set amount of degrees
 32
 33        You could remove the change_angle keyword and/or angle change
 34        if you know that sprites will always or never change angle.
 35
 36        Args:
 37            point:
 38                The point that the sprite will rotate about
 39            degrees:
 40                How many degrees to rotate the sprite
 41            change_angle:
 42                Whether the sprite's angle should also be adjusted.
 43        """
 44
 45        # If change_angle is true, change the sprite's angle
 46        if change_angle:
 47            self.angle += degrees
 48
 49        # Move the sprite along a circle centered on the point by degrees
 50        self.position = rotate_point(
 51            self.center_x, self.center_y,
 52            point[0], point[1], degrees)
 53
 54
 55class GameView(arcade.View):
 56
 57    def __init__(self):
 58        super().__init__()
 59
 60        self.sprites = arcade.SpriteList()
 61
 62        # This example is based off spinning lines of fire from Mario games
 63        # See https://www.mariowiki.com/Fire_Bar for more information
 64        self.left_rotating_laser_sprite = RotatingSprite(
 65            ":resources:images/space_shooter/laserBlue01.png",
 66            center_x=QUARTER_WIDTH + 26, center_y=HALF_HEIGHT)
 67
 68        self.laser_base_sprite = arcade.Sprite(
 69            ":resources:images/tiles/boxCrate.png", scale=0.25,
 70            center_x=QUARTER_WIDTH, center_y=HALF_HEIGHT)
 71
 72        self.laser_text = arcade.Text(
 73            "change_angle = True",
 74            QUARTER_WIDTH, WINDOW_HEIGHT // 2 - 150,
 75            anchor_x='center')
 76
 77        # This example demonstrates how to make platforms rotate around a point
 78        self.right_rotating_platform_sprite = RotatingSprite(
 79            ":resources:images/tiles/grassHalf.png", scale=0.25,
 80            center_x=3 * QUARTER_WIDTH + 50, center_y=HALF_HEIGHT)
 81
 82        self.platform_base_sprite = arcade.Sprite(
 83            ":resources:images/tiles/boxCrate.png", scale=0.25,
 84            center_x=3 * QUARTER_WIDTH, center_y=HALF_HEIGHT)
 85
 86        self.platform_text = arcade.Text(
 87            "change_angle = False",
 88            3 * QUARTER_WIDTH, HALF_HEIGHT - 150,
 89            anchor_x='center')
 90
 91        self.sprites.extend([
 92            self.laser_base_sprite,
 93            self.left_rotating_laser_sprite,
 94            self.platform_base_sprite,
 95            self.right_rotating_platform_sprite])
 96
 97    def on_update(self, delta_time: float):
 98        # Rotate the laser sprite and change its angle
 99        self.left_rotating_laser_sprite.rotate_around_point(
100            self.laser_base_sprite.position,
101            120 * delta_time)
102
103        # Rotate the platform sprite but don't change its angle
104        self.right_rotating_platform_sprite.rotate_around_point(
105            self.platform_base_sprite.position,
106            60 * delta_time, False)
107
108    def on_draw(self):
109        # Draw the sprite list.
110        self.clear()
111        self.sprites.draw()
112
113        self.laser_text.draw()
114        self.platform_text.draw()
115
116
117def main():
118    """ Main function """
119    # Create a window class. This is what actually shows up on screen
120    window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)
121
122    # Create and setup the GameView
123    game = GameView()
124
125    # Show GameView on screen
126    window.show_view(game)
127
128    # Start the arcade game loop
129    arcade.run()
130
131
132if __name__ == '__main__':
133    main()