Quick Shot
A downloadable game
# Quick Shot made by Ari D Price
# Jan 3 2025
# for my video game final project semester 1
import pygame
import sys
from random import randint
import math
# Initialize pygame
pygame.init()
background_color = (randint(50, 255), randint(50, 255), randint(50, 255))
# Constants
SCREEN_WIDTH = 1000
SCREEN_HEIGHT = 700
gravity = 0.5
restitution = 0.8
ground_level = SCREEN_HEIGHT - 60 # Slightly above the bottom for ground collision
# Ball properties
SPAWNER_X = 0
spawner_y = SCREEN_HEIGHT // 2
x = SPAWNER_X # X-coordinate of the ball
y = spawner_y # Y-coordinate of the ball
velocity_x = 0 # Horizontal velocity of the ball
velocity_y = 0 # Vertical velocity of the ball
# Launch intensity control
launch_speed = 15 # Initial launch speed
min_speed = 5 # Minimum speed
max_speed = 30 # Maximum speed
# Scoreboard and font setup
score = 0
player1_score = 0 # Player 1's score
player2_score = 0 # Player 2's score
font = pygame.font.Font(None, 36)
able_to_score = False
# Sprite and ball size
sprite = pygame.image.load('1.png')
ball_width = sprite.get_width()
# Game state variables
start_message = True # Show the starting message
start_time = None # Tracks the game start time
turn = 1 # 1 for Player 1, 2 for Player 2
# sets the window name to the games name ("Quick Shot")
pygame.display.set_caption("Quick Shot")
# Initialize the screen and clock
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()
# Spawn ball function
def spawn_ball():
"""Respawns the ball, and resets its velocity."""
global x, y, velocity_x, velocity_y, launch_speed
x = SPAWNER_X
y = spawner_y
velocity_x = 0
velocity_y = 0
# Get mouse position
mouse_x, mouse_y = pygame.mouse.get_pos()
# Calculate direction from spawner to mouse position
dx = mouse_x - SPAWNER_X # dx is the direction on the x axis of where ball is launched
dy = mouse_y - spawner_y # dy is the direction on the y axis of where ball is launched
distance = math.sqrt(dx**2 + dy**2) # Calculate the distance
# Normalize direction and apply velocity
if distance > 0:
velocity_x = (dx / distance) * launch_speed
velocity_y = (dy / distance) * launch_speed
# Game loop
game_running = True
game_paused = False # if true this the game will puase
while game_running: # contains all teh events clock.tick(60)
# Event handling (handels the events that happen when you press certain keys on the key board)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if start_message: # If the message is showing (game not started)
if event.key == pygame.K_SPACE: # Start the game only when the spacebar is pressed
start_message = False # Hide the message
if start_time is None: # Ensuresthat the start_time is set only once
start_time = pygame.time.get_ticks()
elif not game_paused: # If the game is not paused, handle spacebar press
if event.key == pygame.K_SPACE: # Only spawns the ball when spacebar is pressed
able_to_score = True # makes sure that the ball cant score twice if it isnt respawned
spawn_ball()
# Controls the launch speed with Q and E keys, and up and down with the "w" and "s" keys
keys = pygame.key.get_pressed()# alows these keys to be held down and continuously cary out an action
# Movement keys
if keys[pygame.K_w]:
spawner_y = max(0, spawner_y - 4) # Moves the spawner up, but stays within the screen
if keys[pygame.K_s]:
spawner_y = min(SCREEN_HEIGHT - 10, spawner_y + 4) # Moves the spawner down, but stays within the screen
if keys[pygame.K_q]: # Decreases launch speed
launch_speed = max(min_speed, launch_speed - 0.25)
if keys[pygame.K_e]: # Increases launch speed
launch_speed = min(max_speed, launch_speed + 0.25)
# Update ball physics (applies gravity)
velocity_y += gravity # Applies gravity to vertical velocity
x += velocity_x # Updates the horizontal position
y += velocity_y # Updates the vertical position
# Checks for collision with the ground
if y >= ground_level:
y = ground_level # Keeps the ball on the ground
velocity_y = -velocity_y * restitution # Reverses and reduces the ball's vertical velocity
# Stops the ball from bouncing if the velocity is small
if abs(velocity_y) < 0.5:
velocity_y = 0
velocity_x = 0 # Stops ball's horizontal movement as well
# Checks for collision with the walls (left and right edges)
if x <= 0: # Left wall collision
x = 0
velocity_x = -velocity_x * restitution # Reverses and reduces the ball's horizontal velocity
if x >= SCREEN_WIDTH - 50: # Right wall (ball width assumed to be 50)
x = SCREEN_WIDTH - 50
velocity_x = -velocity_x * restitution # Reverse and reduce horizontal velocity
ball_radius = 50
try:
if x >= leftside_net_x + 19 and x <= leftside_net_x + 38 and y >= leftside_net_y - 80 and y <= leftside_net_y-20 and able_to_score == True:
able_to_score = False
score += 1
leftside_net_x = randint(600, 800)
leftside_net_y = randint(300, 600)
rightside_net_x = leftside_net_x + 76
except NameError:
leftside_net_x = randint(600, 800)
leftside_net_y = randint(300, 600)
rightside_net_x = leftside_net_x + 76
# Collision detection with left and right lines
if (leftside_net_x - 5 <= x + ball_radius and x - ball_radius <= leftside_net_x + 14) and (leftside_net_y - 140 <= y <= leftside_net_y+10): # makes the collision box for the left of the net
velocity_x = -velocity_x * restitution # makes it bounce
# ensure that the ball wont fase through the net
if x < leftside_net_x: x = leftside_net_x - 14 - ball_radius
elif x > leftside_net_x:
x = leftside_net_x + ball_radius
if (rightside_net_x - 5 <= x + ball_radius and x - ball_radius <= rightside_net_x + 14) and (leftside_net_y - 140 <= y <= leftside_net_y+10):# makes the collision box for the left of the net
velocity_x = -velocity_x * restitution# makes it bounce
# ensure that the ball wont fase through the net
if x < rightside_net_x:
x = rightside_net_x - ball_radius
elif x > rightside_net_x:
x = rightside_net_x + 14 + ball_radius
# Render
screen.fill(background_color)
# Show the starting message
if start_message:
message = ("Press SPACE to start ")
message2 = ("(SPACE to shoot, Q and E to change launch velocity,")
message3 = ("W and S to move up and down, aim with the mouse)")
text = font.render(message, True, (0, 0, 0))
text2 = font.render(message2, True, (0, 0, 0))
text3 = font.render(message3, True, (0, 0, 0))
screen.blit(text, (50, SCREEN_HEIGHT // 2))
screen.blit(text2, (50, (SCREEN_HEIGHT // 2) + 20))
screen.blit(text3, (50, (SCREEN_HEIGHT // 2) + 40))
# Draw the walls (edges of the window)
pygame.draw.rect(screen, (0, 0, 0), (0, 0, SCREEN_WIDTH, 10)) # Top wall
pygame.draw.rect(screen, (0, 0, 0), (0, SCREEN_HEIGHT - 10, SCREEN_WIDTH, 10)) # Bottom wall
pygame.draw.rect(screen, (0, 0, 0), (0, 0, 10, SCREEN_HEIGHT)) # Left wall
pygame.draw.rect(screen, (0, 0, 0), (SCREEN_WIDTH - 10, 0, 10, SCREEN_HEIGHT)) # Right wall
# Draw the ball
if not start_message:
screen.blit(sprite, (x, y))
# sets the window name to the players turn
if not start_message:
pygame.display.set_caption(f"Player {turn}'s Turn")
# Timer and player change logic
if start_time is not None:
elapsed_time = (pygame.time.get_ticks() - start_time) // 1000 # Time in seconds
# Change window title after 130 seconds
if elapsed_time >= 130:
if turn == 1:
player1_score = score # Save score for player 1
elif turn == 2:
player2_score = score # Save score for player 2
game_paused = True # Pause the game after Player 2's turn ends
score = 0 # Reset score for the next player
turn = 2 if turn == 1 else 1 # Switch turns
start_time = pygame.time.get_ticks() # Reset the start time for the next round
# Draw the spawner as a red square
pygame.draw.rect(screen, (255, 0, 0), (SPAWNER_X, spawner_y, 10, 10))
# Draw net lines
pygame.draw.line(screen, (70, 40, 1), (leftside_net_x, leftside_net_y), (leftside_net_x, leftside_net_y - 100), 10)
pygame.draw.line(screen, (70, 40, 1), (rightside_net_x, leftside_net_y), (rightside_net_x, leftside_net_y - 100), 10)
# Show the starting message
if start_message:
message = ("Press SPACE to start ")
message2 = ("(SPACE to shoot, Q and E to change launch velocity,")
message3 = ("W and S to move up and down, aim with the mouse)")
text = font.render(message, True, (0, 0, 0))
text2 = font.render(message2, True, (0, 0, 0))
text3 = font.render(message3, True, (0, 0, 0))
screen.blit(text, (50, SCREEN_HEIGHT // 2))
screen.blit(text2, (50, (SCREEN_HEIGHT // 2) + 20))
screen.blit(text3, (50, (SCREEN_HEIGHT // 2) + 40))
# Score text
score_text = font.render(f"Score: {score}", True, (0, 0, 0)) # Black text
screen.blit(score_text, (20, 20))
# Display the timer
if start_time is not None:
elapsed_time = (pygame.time.get_ticks() - start_time) // 1000 # Time in seconds
timer_text = font.render(f"Time: {elapsed_time}s", True, (0, 0, 0)) # Black text
screen.blit(timer_text, (SCREEN_WIDTH - 150, 20))
# Display the score of both players
player1_text = font.render(f"Player 1 Score: {player1_score}", True, (0, 0, 0))
player2_text = font.render(f"Player 2 Score: {player2_score}", True, (0, 0, 0))
screen.blit(player1_text, (20, 50))
screen.blit(player2_text, (20, 80))
# pauses the display
if game_paused:
if player1_score > player2_score: # if Player 1 Wins
result_text = font.render(f"Player 1 Wins! Final Score: {player1_score} - {player2_score}", True, (0, 255, 0))
elif player2_score > player1_score:# if Player 2 Wins
result_text = font.render(f"Player 2 Wins! Final Score: {player1_score} - {player2_score}", True, (0, 255, 0))
else:# if nobody Wins
result_text = font.render(f"It's a Tie! Final Score: {player1_score} - {player2_score}", True, (0, 255, 0))
screen.blit(result_text, (SCREEN_WIDTH // 2 - result_text.get_width() // 2, SCREEN_HEIGHT // 2))
pygame.display.update()
Leave a comment
Log in with itch.io to leave a comment.