```"""
Show how to fire bullets at the mouse.

Sample Python/Pygame Programs
Simpson College Computer Science
http://simpson.edu/computer-science/
"""
import pygame
import random
import math

# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
BLUE = (0, 0, 255)

SCREEN_WIDTH = 700
SCREEN_HEIGHT = 400
# --- Classes

class Block(pygame.sprite.Sprite):
""" This class represents the block. """
def __init__(self, color):
# Call the parent class (Sprite) constructor
super().__init__()

self.image = pygame.Surface([20, 15])
self.image.fill(color)

self.rect = self.image.get_rect()

class Player(pygame.sprite.Sprite):
""" This class represents the Player. """

def __init__(self):
""" Set up the player on creation. """
# Call the parent class (Sprite) constructor
super().__init__()

self.image = pygame.Surface([20, 20])
self.image.fill(RED)

self.rect = self.image.get_rect()

class Bullet(pygame.sprite.Sprite):
""" This class represents the bullet. """

def __init__(self, start_x, start_y, dest_x, dest_y):
""" Constructor.
It takes in the starting x and y location.
It also takes in the destination x and y position.
"""

# Call the parent class (Sprite) constructor
super().__init__()

# Set up the image for the bullet
self.image = pygame.Surface([4, 10])
self.image.fill(BLACK)

self.rect = self.image.get_rect()

# Move the bullet to our starting location
self.rect.x = start_x
self.rect.y = start_y

# Because rect.x and rect.y are automatically converted
# to integers, we need to create different variables that
# store the location as floating point numbers. Integers
# are not accurate enough for aiming.
self.floating_point_x = start_x
self.floating_point_y = start_y

# Calculation the angle in radians between the start points
# and end points. This is the angle the bullet will travel.
x_diff = dest_x - start_x
y_diff = dest_y - start_y
angle = math.atan2(y_diff, x_diff);

# Taking into account the angle, calculate our change_x
# and change_y. Velocity is how fast the bullet travels.
velocity = 5
self.change_x = math.cos(angle) * velocity
self.change_y = math.sin(angle) * velocity

def update(self):
""" Move the bullet. """

# The floating point x and y hold our more accurate location.
self.floating_point_y += self.change_y
self.floating_point_x += self.change_x

# The rect.x and rect.y are converted to integers.
self.rect.y = int(self.floating_point_y)
self.rect.x = int(self.floating_point_x)

# If the bullet flies of the screen, get rid of it.
if self.rect.x < 0 or self.rect.x > SCREEN_WIDTH or self.rect.y < 0 or self.rect.y > SCREEN_HEIGHT:
self.kill()

# --- Create the window

# Initialize Pygame
pygame.init()

# Set the height and width of the screen

screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])

# --- Sprite lists

# This is a list of every sprite. All blocks and the player block as well.
all_sprites_list = pygame.sprite.Group()

# List of each block in the game
block_list = pygame.sprite.Group()

# List of each bullet
bullet_list = pygame.sprite.Group()

# --- Create the sprites

for i in range(50):
# This represents a block
block = Block(BLUE)

# Set a random location for the block
block.rect.x = random.randrange(SCREEN_WIDTH)
block.rect.y = random.randrange(SCREEN_HEIGHT - 50)

# Add the block to the list of objects

# Create a red player block
player = Player()

# Loop until the user clicks the close button.
done = False

# Used to manage how fast the screen updates
clock = pygame.time.Clock()

score = 0

player.rect.x = SCREEN_WIDTH / 2
player.rect.y = SCREEN_HEIGHT / 2

# -------- Main Program Loop -----------
while not done:
# --- Event Processing
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True

elif event.type == pygame.MOUSEBUTTONDOWN:
# Fire a bullet if the user clicks the mouse button

# Get the mouse position
pos = pygame.mouse.get_pos()

mouse_x = pos
mouse_y = pos

# Create the bullet based on where we are, and where we want to go.
bullet = Bullet(player.rect.x, player.rect.y, mouse_x, mouse_y)

# Add the bullet to the lists

# --- Game logic

# Call the update() method on all the sprites
all_sprites_list.update()

# Calculate mechanics for each bullet
for bullet in bullet_list:

# See if it hit a block
block_hit_list = pygame.sprite.spritecollide(bullet, block_list, True)

# For each block hit, remove the bullet and add to the score
for block in block_hit_list:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
score += 1
print(score)

# Remove the bullet if it flies up off the screen
if bullet.rect.y < -10:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)

# --- Draw a frame

# Clear the screen
screen.fill(WHITE)

# Draw all the spites
all_sprites_list.draw(screen)

# Go ahead and update the screen with what we've drawn.
pygame.display.flip()

# --- Limit to 20 frames per second
clock.tick(60)

pygame.quit()

```
﻿