Pygame Collision Source Code

collision.py
  1"""
  2Sample Python/Pygame Programs
  3Simpson College Computer Science
  4http://programarcadegames.com/
  5http://simpson.edu/computer-science/
  6"""
  7
  8# noinspection PyPackageRequirements
  9import pygame
 10import random
 11import os
 12from performance_timing import PerformanceTiming
 13
 14# Define some colors
 15BLACK = (0, 0, 0)
 16WHITE = (255, 255, 255)
 17RED = (255, 0, 0)
 18
 19# --- Constants ---
 20SPRITE_SCALING_COIN = 0.09
 21SPRITE_SCALING_PLAYER = 0.5
 22SPRITE_NATIVE_SIZE = 128
 23SPRITE_SIZE = int(SPRITE_NATIVE_SIZE * SPRITE_SCALING_COIN)
 24
 25SCREEN_WIDTH = 1800
 26SCREEN_HEIGHT = 1000
 27SCREEN_TITLE = "Pygame - Moving Sprite Stress Test"
 28
 29RESULTS_FILE = "../../result_data/pygame/collision.csv"
 30RESULTS_IMAGE = "../../result_data/pygame/collision.png"
 31
 32
 33class Coin(pygame.sprite.Sprite):
 34    """
 35    This class represents the ball
 36    It derives from the "Sprite" class in Pygame
 37    """
 38    # Static coin image
 39    coin_image = None
 40
 41    def __init__(self):
 42        """ Constructor. Pass in the color of the block,
 43        and its x and y position. """
 44        # Call the parent class (Sprite) constructor
 45        super().__init__()
 46
 47        # In Pygame, if we load and scale a coin image every time we create a sprite,
 48        # this will result in a noticeable performance hit. Therefore we do it once,
 49        # and re-use that image over-and-over.
 50        if Coin.coin_image is None:
 51            # Create an image of the block, and fill it with a color.
 52            # This could also be an image loaded from the disk.
 53            Coin.coin_image = pygame.image.load("../resources/coinGold.png")
 54            rect = Coin.coin_image.get_rect()
 55            Coin.coin_image = pygame.transform.scale(
 56                Coin.coin_image,
 57                (int(rect.width * SPRITE_SCALING_COIN), int(rect.height * SPRITE_SCALING_COIN)))
 58            Coin.coin_image.convert()
 59            Coin.coin_image.set_colorkey(BLACK)
 60
 61        self.image = Coin.coin_image
 62
 63        # Fetch the rectangle object that has the dimensions of the image
 64        # image.
 65        # Update the position of this object by setting the values
 66        # of rect.x and rect.y
 67        self.rect = self.image.get_rect()
 68
 69
 70class Player(pygame.sprite.Sprite):
 71    """
 72    This class represents the ball
 73    It derives from the "Sprite" class in Pygame
 74    """
 75
 76    def __init__(self):
 77        """ Constructor. Pass in the color of the block,
 78        and its x and y position. """
 79        # Call the parent class (Sprite) constructor
 80        super().__init__()
 81
 82        # Create an image of the block, and fill it with a color.
 83        # This could also be an image loaded from the disk.
 84        image = pygame.image.load("../resources/femalePerson_idle.png")
 85        rect = image.get_rect()
 86        image = pygame.transform.scale(image, (
 87            int(rect.width * SPRITE_SCALING_PLAYER), int(rect.height * SPRITE_SCALING_PLAYER)))
 88        self.image = image.convert()
 89        self.image.set_colorkey(BLACK)
 90
 91        # Fetch the rectangle object that has the dimensions of the image
 92        # image.
 93        # Update the position of this object by setting the values
 94        # of rect.x and rect.y
 95        self.rect = self.image.get_rect()
 96
 97        self.change_x = 0
 98        self.change_y = 0
 99
100    def update(self):
101        """ Called each frame. """
102        self.rect.x += self.change_x
103        self.rect.y += self.change_y
104
105
106class MyGame:
107    """ Our custom Window Class"""
108
109    def __init__(self):
110        """ Initializer """
111
112        # Set the working directory (where we expect to find files) to the same
113        # directory this .py file is in. You can leave this out of your own
114        # code, but it is needed to easily run the examples using "python -m"
115        # as mentioned at the top of this program.
116        file_path = os.path.dirname(os.path.abspath(__file__))
117        os.chdir(file_path)
118
119        # Variables that will hold sprite lists
120        self.coin_list = None
121
122        self.performance_timing = PerformanceTiming(results_file=RESULTS_FILE,
123                                                    start_n=0,
124                                                    increment_n=1000,
125                                                    end_time=60)
126
127        # Initialize Pygame
128        pygame.init()
129
130        # Set the height and width of the screen
131        self.screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])
132
133        # This is a list of every sprite. All blocks and the player block as well.
134        self.coin_list = pygame.sprite.Group()
135        self.player_list = pygame.sprite.Group()
136
137        # Create the player instance
138        self.player = Player()
139
140        self.player.rect.x = random.randrange(SPRITE_SIZE, SCREEN_WIDTH - SPRITE_SIZE)
141        self.player.rect.y = random.randrange(SPRITE_SIZE, SCREEN_HEIGHT - SPRITE_SIZE)
142        self.player.change_x = 3
143        self.player.change_y = 5
144
145        self.player_list.add(self.player)
146
147        self.font = pygame.font.SysFont('Calibri', 25, True, False)
148
149    def add_coins(self, amount):
150
151        # Create the coins
152        for i in range(amount):
153            # Create the coin instance
154            # Coin image from kenney.nl
155            coin = Coin()
156
157            # Position the coin
158            coin.rect.x = random.randrange(SPRITE_SIZE, SCREEN_WIDTH - SPRITE_SIZE)
159            coin.rect.y = random.randrange(SPRITE_SIZE, SCREEN_HEIGHT - SPRITE_SIZE)
160
161            # Add the coin to the lists
162            self.coin_list.add(coin)
163
164    def on_draw(self):
165        """ Draw everything """
166
167        # Start timing how long this takes
168        self.performance_timing.start_timer('draw')
169
170        # Clear the screen
171        self.screen.fill((59, 122, 87))
172
173        # Draw all the spites
174        self.coin_list.draw(self.screen)
175        self.player_list.draw(self.screen)
176
177        pygame.display.flip()
178
179        # Stop timing how long this takes
180        self.performance_timing.stop_timer('draw')
181
182    def update(self, _delta_time):
183        # Start update timer
184        self.performance_timing.start_timer('update')
185
186        # Start update timer
187        self.player_list.update()
188
189        if self.player.rect.x < 0 and self.player.change_x < 0:
190            self.player.change_x *= -1
191        if self.player.rect.y < 0 and self.player.change_y < 0:
192            self.player.change_y *= -1
193
194        if self.player.rect.x > SCREEN_WIDTH and self.player.change_x > 0:
195            self.player.change_x *= -1
196        if self.player.rect.y > SCREEN_HEIGHT and self.player.change_y > 0:
197            self.player.change_y *= -1
198
199        coin_hit_list = pygame.sprite.spritecollide(self.player, self.coin_list, False)
200        for coin in coin_hit_list:
201            coin.rect.x = random.randrange(SCREEN_WIDTH)
202            coin.rect.y = random.randrange(SCREEN_HEIGHT)
203
204        # Stop timing the update
205        self.performance_timing.stop_timer('update')
206
207        # Figure out if we need more coins
208        if self.performance_timing.target_n > len(self.coin_list):
209            new_coin_amount = self.performance_timing.target_n - len(self.coin_list)
210            self.add_coins(new_coin_amount)
211
212
213def main():
214    """ Main method """
215    window = MyGame()
216
217    # Loop until the user clicks the close button.
218    done = False
219
220    # Used to manage how fast the screen updates
221    clock = pygame.time.Clock()
222
223    # -------- Main Program Loop -----------
224    while not window.performance_timing.end_run() and not done:
225        for event in pygame.event.get():
226            if event.type == pygame.QUIT:
227                done = True
228        window.update(0)
229        window.on_draw()
230        clock.tick(60)
231
232    # Save screenshot
233    pygame.image.save(window.screen, RESULTS_IMAGE)
234
235    pygame.quit()
236
237
238if __name__ == "__main__":
239    main()