Pygame Draw Moving Shapes Source Code

draw_shapes.py
  1"""
  2Moving Sprite Stress Test
  3
  4Simple program to test how fast we can draw sprites that are moving
  5
  6Artwork from http://kenney.nl
  7"""
  8
  9# noinspection PyPackageRequirements
 10import pygame
 11import random
 12import os
 13from performance_timing import PerformanceTiming
 14
 15# Define some colors
 16BLACK = (0, 0, 0)
 17WHITE = (255, 255, 255)
 18RED = (255, 0, 0)
 19
 20# --- Constants ---
 21SPRITE_SCALING_COIN = 0.25
 22SPRITE_NATIVE_SIZE = 128
 23SPRITE_SIZE = int(SPRITE_NATIVE_SIZE * SPRITE_SCALING_COIN)
 24
 25RESULTS_FILE = "../../result_data/pygame/moving_shapes.csv"
 26RESULTS_IMAGE = "../../result_data/pygame/moving_shapes.png"
 27SCREEN_WIDTH = 1800
 28SCREEN_HEIGHT = 1000
 29SCREEN_TITLE = "Pygame - Moving Shapes Stress Test"
 30
 31
 32class Shape:
 33    """ Generic base shape class """
 34    def __init__(self, x, y, width, height, angle, delta_x, delta_y,
 35                 delta_angle, color):
 36        self.x = x
 37        self.y = y
 38        self.width = width
 39        self.height = height
 40        self.angle = angle
 41        self.delta_x = delta_x
 42        self.delta_y = delta_y
 43        self.delta_angle = delta_angle
 44        self.color = color
 45
 46    def move(self):
 47        self.x += self.delta_x
 48        self.y += self.delta_y
 49        self.angle += self.delta_angle
 50        if self.x < 0 and self.delta_x < 0:
 51            self.delta_x *= -1
 52        if self.y < 0 and self.delta_y < 0:
 53            self.delta_y *= -1
 54        if self.x > SCREEN_WIDTH and self.delta_x > 0:
 55            self.delta_x *= -1
 56        if self.y > SCREEN_HEIGHT and self.delta_y > 0:
 57            self.delta_y *= -1
 58
 59class Rectangle(Shape):
 60
 61    def draw(self, surface):
 62        rect = pygame.Rect(self.x, self.y, self.width, self.height)
 63        pygame.draw.rect(surface, self.color, rect)
 64
 65class Ellipse(Shape):
 66
 67    def draw(self, surface):
 68        rect = pygame.Rect(self.x, self.y, self.width, self.height)
 69        pygame.draw.ellipse(surface, self.color, rect)
 70
 71class MyGame:
 72    """ Our custom Window Class"""
 73
 74    def __init__(self):
 75        """ Initializer """
 76
 77        # Set the working directory (where we expect to find files) to the same
 78        # directory this .py file is in. You can leave this out of your own
 79        # code, but it is needed to easily run the examples using "python -m"
 80        # as mentioned at the top of this program.
 81        file_path = os.path.dirname(os.path.abspath(__file__))
 82        os.chdir(file_path)
 83
 84        # Variables that will hold sprite lists
 85        self.shape_list = []
 86
 87        self.performance_timing = PerformanceTiming(results_file=RESULTS_FILE,
 88                                                    start_n=0,
 89                                                    increment_n=200,
 90                                                    end_time=60)
 91
 92
 93        # Initialize Pygame
 94        pygame.init()
 95        pygame.display.set_caption(SCREEN_TITLE)
 96
 97        # Set the height and width of the screen
 98        self.screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])
 99
100        # This is a list of every sprite. All blocks and the player block as well.
101        self.coin_list = pygame.sprite.Group()
102
103        self.font = pygame.font.SysFont('Calibri', 25, True, False)
104
105    def add_shapes(self, amount):
106        for i in range(amount):
107            x = random.randrange(0, SCREEN_WIDTH)
108            y = random.randrange(0, SCREEN_HEIGHT)
109            width = random.randrange(10, 30)
110            height = random.randrange(10, 30)
111            angle = random.randrange(0, 360)
112
113            d_x = random.randrange(-3, 4)
114            d_y = random.randrange(-3, 4)
115            d_angle = random.randrange(-3, 4)
116
117            red = random.randrange(256)
118            green = random.randrange(256)
119            blue = random.randrange(256)
120            # alpha = random.randrange(256)
121
122            shape_type = random.randrange(2)
123            shape_type = 0
124
125            if shape_type == 0:
126                shape = Rectangle(x, y, width, height, angle, d_x, d_y,
127                                  d_angle, (red, green, blue))
128            elif shape_type == 1:
129                shape = Ellipse(x, y, width, height, angle, d_x, d_y,
130                            d_angle, (red, green, blue))
131            # elif shape_type == 2:
132            #     shape = Line(x, y, width, height, angle, d_x, d_y,
133            #                  d_angle, (red, green, blue, alpha))
134
135            self.shape_list.append(shape)
136
137    def on_draw(self):
138        """ Draw everything """
139
140        # Start timing how long this takes
141        self.performance_timing.start_timer('draw')
142
143        # Clear the screen
144        self.screen.fill((0, 0, 0))
145
146        for shape in self.shape_list:
147            shape.draw(self.screen)
148
149        pygame.display.flip()
150
151        # Stop timing how long this takes
152        self.performance_timing.stop_timer('draw')
153
154    def update(self, _delta_time):
155        # Start update timer
156        self.performance_timing.start_timer('update')
157
158        for shape in self.shape_list:
159            shape.move()
160
161        # Stop timing the update
162        self.performance_timing.stop_timer('update')
163
164        # Figure out if we need more coins
165        if self.performance_timing.target_n > len(self.shape_list):
166            new_coin_amount = self.performance_timing.target_n - len(self.shape_list)
167            self.add_shapes(new_coin_amount)
168
169
170def main():
171    """ Main method """
172    window = MyGame()
173
174    # Loop until the user clicks the close button.
175    done = False
176
177    # Used to manage how fast the screen updates
178    clock = pygame.time.Clock()
179
180    # -------- Main Program Loop -----------
181    while not window.performance_timing.end_run() and not done:
182        for event in pygame.event.get():
183            if event.type == pygame.QUIT:
184                done = True
185        window.update(0)
186        window.on_draw()
187        clock.tick(60)
188
189    # Save screenshot
190    pygame.image.save(window.screen, RESULTS_IMAGE)
191
192    pygame.quit()
193
194
195if __name__ == "__main__":
196    main()