1- import sys # Import the system module, literally just for quitting the game cleanly
1+ import sys
2+ import time
23import pygame
34from pygame .locals import *
4- from random import randint , random # Import random functions from the random module
5+ from random import randint , random
56
67FPS = 60
78WIDTH , HEIGHT = 400 , 400
1415player_img = pygame .image .load ("player.png" ).convert_alpha ()
1516player_img = pygame .transform .scale (player_img , (36 , 56 ))
1617cookie_img = pygame .image .load ("cookie.png" ).convert_alpha ()
17- bullet_img = pygame .image .load ("bullet.png" ).convert_alpha () # Load the bullet image
18- bullet_img = pygame .transform .scale (bullet_img , (12 , 28 )) # Resize it to the correct size
19- bg_img = pygame .image .load ("background.png" ).convert () # We don't need the background to be transparent, so we use "convert"
18+ bullet_spritesheet = pygame .image .load ("bullet.png" ).convert_alpha ()
19+ bullet_imgs = []
20+ for x in range (4 ):
21+ bullet_img = bullet_spritesheet .subsurface (x * 3 , 0 , 3 , 7 )
22+ bullet_img = pygame .transform .scale (bullet_img , (12 , 28 ))
23+ bullet_imgs .append (bullet_img )
24+ bg_img = pygame .image .load ("background.png" ).convert ()
2025
21- class Player (pygame .sprite .Sprite ): # Make the player have stuff that a pygame sprite needs to have (Inheriting from pygame.sprite.Sprite)
22- def __init__ (self ): # The function that gets called when the sprite is created
23- super ().__init__ () # Initialize the player as a pygame sprite
26+ class Player (pygame .sprite .Sprite ):
27+ def __init__ (self ):
28+ super ().__init__ ()
2429
25- self .image = player_img # Set the player's image to the player image. Pygame uses this variable to draw the sprite
26- self .rect = player_img .get_rect () # Generate the player's rect. Pygame uses this variable to know where to draw the sprite
30+ self .image = player_img
31+ self .rect = player_img .get_rect ()
2732
28- self .x = 180 # Custom x position variable
29- self .y = 340 # Custom y position variable
33+ self .x = 180
34+ self .y = 340
3035
31- def update (self ): # The function that contains player logic
36+ def update (self ):
3237 keys = pygame .key .get_pressed ()
3338 if keys [K_LEFT ]:
34- self .x -= 4 # Get keys and move the player, we've done this before :P
39+ self .x -= 4
3540 if keys [K_RIGHT ]:
3641 self .x += 4
3742
38- self .rect .x = self .x # Update the player rect position to our x and y variables
43+ self .rect .x = self .x
3944 self .rect .y = self .y
4045
41- if self .rect .left < 0 : # Restrict the player's left to inside the screen
46+ if self .rect .left < 0 :
4247 self .rect .left = 0
43- self .x = self .rect .x # Re-update the rect after we do so
44- elif self .rect .right > WIDTH : # Restrict the player's right to inside the screen
48+ self .x = self .rect .x
49+ elif self .rect .right > WIDTH :
4550 self .rect .right = WIDTH
46- self .x = self .rect .x # Re-update the rect after we do so
47-
48- # "spritecollide" detects collision between a sprite and sprites in a group
49- # This function takes a sprite: "self" (the player)
50- # takes a group: "cookies"
51- # takes a boolean (True/False) that determines whether the collided sprite in the group gets deleted or not
52- # and optionally takes a special function: "pygame.sprite.collide_rect_ratio(0.8)"
53- # In this case, our special pygame function makes the rects of each sprite 0.8 times smaller (so it's harder to lose, you're welcome)
51+ self .x = self .rect .x
5452 if pygame .sprite .spritecollide (self , cookies , False , pygame .sprite .collide_rect_ratio (0.8 )):
55- pygame .quit () # If the player collided with something, quit the game
56- sys .exit () # A new thingy that just makes sure the game closes correctly, don't worry about it
53+ pygame .quit ()
54+ sys .exit ()
5755
58- def draw (self , screen ): # Function that draw the player
59- screen .blit (self .image , self .rect ) # Draw the image at the position of the rect
56+ def draw (self , screen ):
57+ screen .blit (self .image , self .rect )
6058
6159class Cookie (pygame .sprite .Sprite ):
62- # The cookie takes 4 arguments in the brackets after __init__:
63- # x: the x position of the cookie
64- # y: the y position of the cookie
65- # x_vel: the x velocity of the cookie
66- # y_vel: the y_velocity of the cookie
6760 def __init__ (self , x , y , x_vel , y_vel ):
6861 super ().__init__ (cookies )
6962
70- self .image = cookie_img # Set the cookie's image to cookie image
71- self .rect = self .image .get_rect () # Generate a rect from the image
63+ self .image = cookie_img
64+ self .rect = self .image .get_rect ()
7265
73- self .x = x # The x position of the cookie
74- self .y = y # The y position of the cookie
75- self .x_vel = x_vel # The x velocity (speed) of the cookie
76- self .y_vel = y_vel # The y velocity (speed) of the cookie
66+ self .x = x
67+ self .y = y
68+ self .x_vel = x_vel
69+ self .y_vel = y_vel
7770
7871 def update (self ):
79- self .x += self .x_vel # Add the x velocity to the x position
80- self .y += self .y_vel # Add the y velocity to the y position
72+ self .x += self .x_vel
73+ self .y += self .y_vel
8174
82- self .rect .x = self .x # Set the x position of the rect to draw the image at to be x
83- self .rect .y = self .y # Set the y position of the rect to draw the image at to be y
75+ self .rect .x = self .x
76+ self .rect .y = self .y
8477
85- if self .rect .left < 0 or self .rect .right > WIDTH : # If the left or right side of the rect is outside the window
86- self .x_vel = - self .x_vel # Reverse the x velocity (bounce)
87- if self .rect .top < 0 or self .rect .bottom > HEIGHT : # If the top or bottom side of the rect is outside the window
88- self .y_vel = - self .y_vel # Reverse the y velocity (bounce)
78+ if self .rect .left < 0 or self .rect .right > WIDTH :
79+ self .x_vel = - self .x_vel
80+ if self .rect .top < 0 or self .rect .bottom > HEIGHT :
81+ self .y_vel = - self .y_vel
8982
9083class Bullet (pygame .sprite .Sprite ):
9184 def __init__ (self , x , y ):
9285 super ().__init__ (bullets )
9386
94- self .image = bullet_img
87+ self .image = bullet_imgs [0 ]
88+ self .index = 0
89+ self .animation_time = time .time ()
9590 self .rect = self .image .get_rect ()
9691
9792 self .x = x
9893 self .y = y
9994
10095 def update (self ):
101- self .y -= 10 # Constantly move the bullet up
96+ self .image = bullet_imgs [self .index ]
97+ if time .time () - self .animation_time > 0.1 :
98+ self .animation_time = time .time ()
99+ self .index += 1
100+ if self .index == 4 :
101+ self .index = 0
102+
103+ self .y -= 10
102104
103- # Update the center x and y position of the bullet, we are using "center" here so that it's easier to align the bullet with the player
104105 self .rect .centerx = self .x
105106 self .rect .centery = self .y
106107
107- if self .rect .bottom < 0 : # If the bottom side of the bullet goes above the top of the screen
108- self .kill () # Remove the bullet, .kill() will remove the sprite from all groups, which will essentially delete it
108+ if self .rect .bottom < 0 :
109+ self .kill ()
109110
110- bullets = pygame .sprite .Group () # Create a pygame group for bullets
111- cookies = pygame .sprite .Group () # Create a pygame group for cookies
112- player = Player () # Create the player
111+ bullets = pygame .sprite .Group ()
112+ cookies = pygame .sprite .Group ()
113+ player = Player ()
113114
114- spawn_chance = 1 / 100 # Extra: the percentage chance a cookie spawns every frame (starting at 1%)
115+ spawn_chance = 1 / 100
115116
116117running = True
117118while running :
@@ -120,35 +121,28 @@ def update(self):
120121 for event in pygame .event .get ():
121122 if event .type == QUIT :
122123 running = False
123- # We are using this type of key press detection because this only detects when the key is pressed down, instead of continuously
124- if event .type == KEYDOWN : # If a key is pressed
125- if event .key == K_SPACE : # If the key is space
126- Bullet (player .rect .centerx , player .y ) # Spawn a bullet at the correct position relative to the player
127-
128- spawn_chance += 0.002 / 100 # Increase the spawn chance by 0.002% per frame
129- if spawn_chance > 5 / 100 : # If the spawn chance is greater than 5%
130- spawn_chance = 5 / 100 # Cap it at 5% (if you want the game to be playable ;))
131- if random () < spawn_chance : # If the random percentage generated is less than the spawn chance percentage
132- # Spawn the cookie at roughly the top half of the screen
133- # and also give it a randomized direction by passing in a random velocity
124+
125+ if event .type == KEYDOWN :
126+ if event .key == K_SPACE :
127+ Bullet (player .rect .centerx , player .y )
128+
129+ spawn_chance += 0.002 / 100
130+ if spawn_chance > 5 / 100 :
131+ spawn_chance = 5 / 100
132+ if random () < spawn_chance :
134133 Cookie (randint (50 , WIDTH - 50 ), randint (50 , 100 ), randint (- 5 , 5 ), randint (- 5 , 5 ))
135134
136- bullets .update () # Update all bullets
137- cookies .update () # Update all cookies
138- player .update () # Update the player
139- # The "groupcollide" function detects collision between two sprite groups
140- # This function takes two groups between which you want to test for collision
141- # It also takes two booleans (True/False) that determines whether the collided sprites get deleted or not
142- # The first and second boolean corresponds to the first and second group, respectively
143- # It also takes an optional function, that pygame uses to modify the collision, we are not using that here
144- # Go up the the player & cookie collision to see more about this optional function
135+ bullets .update ()
136+ cookies .update ()
137+ player .update ()
138+
145139 pygame .sprite .groupcollide (bullets , cookies , True , True )
146140
147- screen .blit (bg_img , (0 , 0 )) # Draw the background image
141+ screen .blit (bg_img , (0 , 0 ))
148142
149- bullets .draw (screen ) # Draw all bullets
150- cookies .draw (screen ) # Draw all cookies
151- player .draw (screen ) # Draw the player
143+ bullets .draw (screen )
144+ cookies .draw (screen )
145+ player .draw (screen )
152146
153147 pygame .display .update ()
154148
0 commit comments