Putting It All Together
🔗 Mouse pew pew shooter
In this example, we’re going to have pygame shoot projectiles from the mouse when the mouse is clicked:
'''
Bullet shooter
'''
import sys
import random
import pygame
pygame.init() # Initialize pygame
# Some constant values
screen_width = 1200
screen_height = 800
FPS = 60 # Frames per second
# colors
RED = [255, 0, 0]
LIGHT_GREY = [230, 230, 230]
BLACK = [0, 0, 0]
# Setup the screen surface
screen = pygame.display.set_mode([screen_width, screen_height])
pygame.display.set_caption("Bullet Shooter")
clock = pygame.time.Clock() # Get a clock to manage FPS
# Projectiles!
bullets = [] # Here's where we'll track all of the bullets on the screen
bullet_velocity_x = 10 # How fast should bullets move?
bullet_width = 7.5
bullet_height = 5
# Targets!
enemy_width = 50
enemy_height = 50
# We'll start with two, statically placed targets
enemies = [pygame.Rect([900,100],[enemy_width,enemy_height]), pygame.Rect([900,700],[enemy_width,enemy_height])]
# Game loop
while True:
screen.fill(LIGHT_GREY)
# Draw the enemies!
for enemy in enemies:
pygame.draw.rect(screen, RED, enemy)
# Challenge: (1) Every time you click, fire bullets from your mouse
# Challenge: (2) clean up off-screen bullets
# Challenge: (3) Have bullets that collide with enemies remove that enemy from the screen
# Challange: (4) spawn new enemies randomly
# Challenge: (5) spawn enemy when you press the spacebar
# Draw the projectiles
# - We don't need to track projectiles that go offscreen anymore (in fact, we
# really shouldn't track those), so we'll keep track of what projectiles are
# still on screen with on_screen_bullets
on_screen_bullets = []
for bullet in bullets:
bullet.left += bullet_velocity_x # Apply movement
pygame.draw.rect(screen, BLACK, bullet) # Draw the bullet
# Does this bullet collide with any enemies?
alive_enemies = [] # We'll use this to track which
# enemies are still alive after handling this bullet
for enemy in enemies:
if bullet.colliderect(enemy):
# If bullet collides, make some noise, and don't add to alive enemies list
print(random.choice(["AAAAHHHH","GRUNT", "UUUGGG", "SPLAT", "POP"]))
continue
alive_enemies.append(enemy) # Enemy escaped the projectile
enemies = alive_enemies # Update enemies list
# Is this projectile still on screen?
if bullet.left <= screen_width:
on_screen_bullets.append(bullet)
# Update list of projectiles with only those that are still on screen
bullets = on_screen_bullets
# Event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
# Fire bullet when player presses mouse button
pos = pygame.mouse.get_pos()
bullet = pygame.Rect(pos[0], pos[1], bullet_width, bullet_height)
bullets.append(bullet)
print(len(bullets))
pygame.display.update() # update the screen
clock.tick(FPS)
|>> download bullets_finished.py
🔗 Keyboard pew pew shooter
Can we adjust the program to have a character rectangle that the player moves around with arrow keys, and when the player presses the spacebar, it fires projectiles (instead of the mouse)?
'''
Bullet shooter game
'''
import sys
import random
import pygame
pygame.init()
# let's try to avoid magic numbers for this
screen_width = 1200
screen_height = 800
FPS = 60
screen = pygame.display.set_mode([screen_width, screen_height])
pygame.display.set_caption("Bullet Shooter")
clock = pygame.time.Clock()
RED = [255, 0, 0]
LIGHT_GREY = [230, 230, 230]
BLACK = [0, 0, 0]
BLUE = [0,0,230]
char_start_x = 0
char_start_y = 0
char_width = 50
char_height = 50
char_speed = 5 # How fast does character move?
cur_char_x_vel = 0 # What's the character's current x speed?
cur_char_y_vel = 0 # What's the character's current y speed?
character = pygame.Rect([char_start_x, char_start_y], [char_width, char_height])
bullets = [] # Here's where we'll track all of the bullets on the screen
bullet_velocity_x = 10 # How fast should bullets move?
bullet_width = 7.5
bullet_height = 5
enemy_width = 50
enemy_height = 50
enemies = [pygame.Rect([900,100],[enemy_width,enemy_height]), pygame.Rect([900,700],[enemy_width,enemy_height])]
# Game loop
while True:
screen.fill(LIGHT_GREY)
# Determine character movement
# Is the player pressing a key?
# - Is player moving vertically?
pressed_keys = pygame.key.get_pressed()
if pressed_keys[pygame.K_UP]:
print("up arrow")
cur_char_y_vel = -1*char_speed
elif pressed_keys[pygame.K_DOWN]:
print("down arrow")
cur_char_y_vel = char_speed
else:
cur_char_y_vel = 0
# - Is player moving horizontally?
if pressed_keys[pygame.K_RIGHT]:
print("down arrow")
cur_char_x_vel = char_speed
elif pressed_keys[pygame.K_LEFT]:
print("down arrow")
cur_char_x_vel = -1*char_speed
else:
cur_char_x_vel = 0
# Draw the character!
character.left += cur_char_x_vel
character.top += cur_char_y_vel
pygame.draw.rect(screen, BLUE, character)
# Draw the enemies!
for enemy in enemies:
pygame.draw.rect(screen, RED, enemy)
# Draw the bullets!
# Challenge: Every time you click, fire bullets from your mouse
# Challenge: Have bullets that collide with enemies remove that enemy from the screen
# Challenge: clean up off-screen bullets
# Challange: spawn new enemies
on_screen_bullets = []
for bullet in bullets:
bullet.left += bullet_velocity_x
pygame.draw.rect(screen, BLACK, bullet)
alive_enemies = []
for enemy in enemies:
if bullet.colliderect(enemy):
print(random.choice(["AAAAHHHH","GRUNT", "UUUGGG", "SPLAT", "POP"]))
continue
alive_enemies.append(enemy)
enemies = alive_enemies
if bullet.left <= screen_width:
on_screen_bullets.append(bullet)
bullets = on_screen_bullets
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
# Keydown event!
if event.key == pygame.K_SPACE:
# Fire a bullet
print("pressed space")
print(character.midright)
pos = character.midright
bullet = pygame.Rect(pos[0], pos[1], bullet_width, bullet_height)
bullets.append(bullet)
pygame.display.update()
clock.tick(FPS)
|>> download bullets_game_v0.py
🔗 Keyboard multi-direction pew pew shooter
If you did that, can you use WASD to change the direction that the projectiles are shot from the character’s rectangle? (e.g., ‘w’ points projectiles upward, ‘d’ to the right, etc)
'''
Bullet shooter game
'''
import sys
import random
import pygame
pygame.init()
# let's try to avoid magic numbers for this
screen_width = 1200
screen_height = 800
FPS = 60
screen = pygame.display.set_mode([screen_width, screen_height])
pygame.display.set_caption("Bullet Shooter")
clock = pygame.time.Clock()
RED = [255, 0, 0]
LIGHT_GREY = [230, 230, 230]
BLACK = [0, 0, 0]
BLUE = [0,0,230]
char_start_x = 0
char_start_y = 0
char_width = 50
char_height = 50
char_speed = 5 # How fast does character move?
character = {"rect":pygame.Rect([char_start_x, char_start_y], [char_width, char_height]),
"dir": "right",
"x_vel": 0,
"y_vel": 0,
"color": BLUE}
bullets = [] # Here's where we'll track all of the bullets on the screen
bullet_speed = 10 # How fast should bullets move?
bullet_width = 7.5
bullet_height = 5
enemy_width = 50
enemy_height = 50
enemies = [{"rect": pygame.Rect([900,100],[enemy_width,enemy_height]), "dir": "left"},
{"rect": pygame.Rect([900,700],[enemy_width,enemy_height]), "dir": "left"}]
# Game loop
while True:
screen.fill(LIGHT_GREY)
# Determine character movement
# Is the player pressing a key?
# - Is player moving vertically?
pressed_keys = pygame.key.get_pressed()
if pressed_keys[pygame.K_UP]:
print("up arrow")
character["y_vel"] = -1*char_speed
elif pressed_keys[pygame.K_DOWN]:
print("down arrow")
character["y_vel"] = char_speed
else:
character["y_vel"] = 0
# - Is player moving horizontally?
if pressed_keys[pygame.K_RIGHT]:
print("down arrow")
character["x_vel"] = char_speed
elif pressed_keys[pygame.K_LEFT]:
print("down arrow")
character["x_vel"] = -1*char_speed
else:
character["x_vel"] = 0
# Draw the character!
character["rect"].left += character["x_vel"]
character["rect"].top += character["y_vel"]
pygame.draw.rect(screen, BLUE, character["rect"])
# - indicate where character is facing
if character["dir"] == "up":
pos = character["rect"].midtop
pygame.draw.rect(screen, BLACK, pygame.Rect([pos[0], pos[1]-5], [5, 5]))
elif character["dir"] == "down":
pos = character["rect"].midbottom
pygame.draw.rect(screen, BLACK, pygame.Rect([pos[0], pos[1]], [5, 5]))
elif character["dir"] == "right":
pos = character["rect"].midright
pygame.draw.rect(screen, BLACK, pygame.Rect([pos[0], pos[1]], [5, 5]))
elif character["dir"] == "left":
pos = character["rect"].midleft
pygame.draw.rect(screen, BLACK, pygame.Rect([pos[0]-5, pos[1]], [5, 5]))
# Draw the enemies!
for enemy in enemies:
pygame.draw.rect(screen, RED, enemy["rect"])
# Draw the bullets!
# Challenge: Every time you click, fire bullets from your mouse
# Challenge: Have bullets that collide with enemies remove that enemy from the screen
# Challenge: clean up off-screen bullets
# Challange: spawn new enemies
on_screen_bullets = []
for bullet in bullets:
# What direction is the bullet going?
if bullet["dir"] == "up":
bullet["rect"].top -= bullet_speed
elif bullet["dir"] == "right":
bullet["rect"].left += bullet_speed
elif bullet["dir"] == "down":
bullet["rect"].top += bullet_speed
elif bullet["dir"] == "left":
bullet["rect"].left -= bullet_speed
# bullet["rect"].left += bullet_speed
pygame.draw.rect(screen, BLACK, bullet["rect"])
alive_enemies = []
for enemy in enemies:
if bullet["rect"].colliderect(enemy["rect"]):
print(random.choice(["AAAAHHHH","GRUNT", "UUUGGG", "SPLAT", "POP"]))
continue
alive_enemies.append(enemy)
enemies = alive_enemies
if bullet["rect"].left <= screen_width:
on_screen_bullets.append(bullet)
bullets = on_screen_bullets
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
# Keydown event!
if event.key == pygame.K_SPACE:
# Fire a bullet
print("pressed space")
pos = [0, 0]
if character["dir"] == "up":
pos = character["rect"].midtop
h = bullet_width
w = bullet_height
elif character["dir"] == "down":
pos = character["rect"].midbottom
h = bullet_width
w = bullet_height
elif character["dir"] == "right":
pos = character["rect"].midright
h = bullet_height
w = bullet_width
elif character["dir"] == "left":
pos = character["rect"].midleft
h = bullet_height
w = bullet_width
bullet = {"rect": pygame.Rect(pos[0], pos[1], w, h), "dir": character["dir"]}
bullets.append(bullet)
if event.key == pygame.K_w:
character["dir"] = "up"
if event.key == pygame.K_d:
character["dir"] = "right"
if event.key == pygame.K_s:
character["dir"] = "down"
if event.key == pygame.K_a:
character["dir"] = "left"
pygame.display.update()
clock.tick(FPS)
# Challenges:
# - Add enemy spawns
# - Add enemy movement
# - Add enemy shooting
|>> download bullets_game_v1.py