menator01
Gold Coder
Was helping someone with their project and decided to have my own go at it.
Python:
import pygame
from pygame import mixer
from random import randint, choice, random, shuffle, randrange
import math
from pathlib import Path
import os
pygame.init()
mixer.init()
path = Path(__file__).parent
# Set width and height of game window
WIDTH, HEIGHT = (1280, 840)
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Collision Balls')
CLOCK = pygame.time.Clock()
# Frames per second
FPS = 60
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
LIGHTBLUE = (180, 255, 255)
BLUE = (0, 180, 255)
GREEN = (0, 255, 0)
CYAN = (0, 255, 255)
YELLOW = (255, 255, 0)
ORANGE = (255,150,0)
PURPLE = (200,100,250)
# Set game variables
running = True
gamestate = 'page'
ball_number = 8
# Timers
checker = pygame.USEREVENT+3
pygame.time.set_timer(checker, 1000)
show_shrinker = pygame.USEREVENT+4
pygame.time.set_timer(show_shrinker, 5000)
invincible_timer = pygame.USEREVENT+5
pygame.time.set_timer(invincible_timer, 1000)
# Sprite groups
player_sprite = pygame.sprite.Group()
ball_sprite = pygame.sprite.Group()
shrinker_sprite = pygame.sprite.Group()
allsprites = pygame.sprite.Group()
# Define a start page - also is the game over page
def page(score=0):
screen.fill(BLACK)
font = pygame.font.SysFont(None, 180)
text = 'Collision Balls'
title_width, title_height = font.size(text)
title = font.render(text, True, ORANGE)
font = pygame.font.SysFont(None, 80)
text = f'Final Score: {score}'
score_width, score_height = font.size(text)
scores = font.render(text, True, PURPLE)
font = pygame.font.SysFont(None, 80)
text = 'Press spacebar to start'
instruct_width, instruct_height = font.size(text)
instructions = font.render(text, True, GREEN)
font = pygame.font.SysFont(None, 38)
text = 'Controls - Arrow Keys or w,s,a,d Keys'
con_width, con_height = font.size(text)
controls = font.render(text, True, (120,120,120))
screen.blit(title, ((WIDTH/2-title_width/2), HEIGHT*0.05))
screen.blit(instructions, ((WIDTH/2-instruct_width/2), HEIGHT*0.5))
screen.blit(controls, (WIDTH/2-con_width/2, HEIGHT*0.30))
if score > 0:
screen.blit(scores, ((WIDTH/2-score_width/2), HEIGHT*0.3))
pygame.display.update()
player_sprite.empty()
ball_sprite.empty()
shrinker_sprite.empty()
allsprites.empty()
def create_color():
color = ()
for i in range(3):
n = randrange(50,255)
color = color + (n,)
return color
class Music:
def __init__(self):
self.tracks = None
if os.path.exists(f'{path}/media/Royalty Free'):
self.tracks = os.listdir(f'{path}/media/Royalty Free')
def play(self):
if self.tracks:
tracks = []
if not tracks:
tracks = self.tracks.copy()
shuffle(tracks)
track = tracks.pop(0)
mixer.music.load(f'{path}/media/Royalty Free/{track}')
mixer.music.set_volume(0.5)
mixer.music.play()
def stop(self):
mixer.music.stop()
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.width = self.height = 30
self.image = pygame.Surface((self.width, self.height))
self.image.fill(RED)
self.rect = self.image.get_rect()
self.rect.center = ((WIDTH/2, HEIGHT/2))
self.speedx = self.speedy = 2
self.counter = 10
self.score = 0
self.invincible = False
self.current = pygame.time.get_ticks()
# Create a user event
self.grow_timer = pygame.USEREVENT + 1
# Set the event to fire the grow method every 10 seconds
pygame.time.set_timer(self.grow_timer, 10000)
player_sprite.add(self)
allsprites.add(self)
def grow(self):
''' Method for growing the player '''
self.width += self.rect.width * 0.1
self.height += self.rect.height * 0.1
# Don't want the size to big 80
if self.width > 80:
self.width = 80
self.height = 80
# Redraw the player
self.image = pygame.Surface((self.width, self.height))
self.image.fill(RED)
def shrink(self):
''' Method for shrinking player '''
self.width -= self.rect.width * 0.15
self.height -= self.rect.height * 0.15
# Don't want the size to be smaller than 20
if self.width <= 20:
self.width = 20
self.height = 20
self.image = pygame.Surface((self.width, self.height))
self.image.fill(RED)
def change(self):
self.invincible = False
def update(self):
# Set up a scoring system. For every one secong give .20 score
# Ever five seconds get one point
if pygame.time.get_ticks() - self.current >= 1000:
self.score += 0.20
self.current = pygame.time.get_ticks()
self.image.fill(PURPLE) if self.invincible else self.image.fill(RED)
self.speedx = self.speedy = 0
# Get keys pressed
key = pygame.key.get_pressed()
if key[pygame.K_LEFT] or key[pygame.K_a]:
self.speedx = -2
if key[pygame.K_RIGHT] or key[pygame.K_d]:
self.speedx = 2
if key[pygame.K_UP] or key[pygame.K_w]:
self.speedy = -2
if key[pygame.K_DOWN] or key[pygame.K_SPACE]:
self.speedy = 2
# Set bounds
if self.rect.left <= 0:
self.rect.left = 0
if self.rect.right >= WIDTH:
self.rect.right = WIDTH
if self.rect.top <= 0:
self.rect.top = 0
if self.rect.bottom >= HEIGHT:
self.rect.bottom = HEIGHT
self.rect.centerx += self.speedx
self.rect.centery += self.speedy
class Ball(pygame.sprite.Sprite):
''' Class creates a ball object '''
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((30,30))
self.image.fill(BLACK)
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.x = randint(self.rect.width, WIDTH-self.rect.width)
self.rect.y = randint(self.rect.height, HEIGHT-self.rect.height)
self.speed = 2.5
self.target_x, self.target_y = self.rect.x, self.rect.y
self.moves = 0
self.colors = create_color()
pygame.draw.circle(self.image, self.colors, (self.rect.width/2, self.rect.height/2), 15)
self.timer = pygame.USEREVENT + randint(10, 1000)
pygame.time.set_timer(self.timer, 20)
ball_sprite.add(self)
allsprites.add(self)
def target(self):
''' Method for setting a new target '''
self.target_x = randint(self.rect.width, WIDTH-self.rect.width)
self.target_y = randint(self.rect.height, HEIGHT-self.rect.height)
# Increase counter
self.moves += 1
def move(self):
''' Method for moving ball '''
dx = self.target_x - self.rect.x
dy = self.target_y - self.rect.y
distance = math.sqrt(dx**2 + dy**2)
if distance > self.speed:
self.rect.x += (dx/distance) * self.speed
self.rect.y += (dy/distance) * self.speed
else:
self.rect.x, self.rect.y = self.target_x, self.target_y
self.target()
class Shrinker(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((20,20))
self.image.fill(ORANGE)
self.rect = self.image.get_rect()
self.rect.x = randint(self.rect.width, WIDTH-self.rect.width)
self.rect.y = randint(self.rect.height, HEIGHT-self.rect.height)
self.change_player = False
self.born = pygame.time.get_ticks()
shrinker_sprite.add(self)
allsprites.add(self)
def update(self):
# Kills shrinker after five seconds
if pygame.time.get_ticks() - self.born > 5000:
self.born = pygame.time.get_ticks()
self.kill()
def change(self):
''' Method for random creation of either a regular shrinker or powered shrinker '''
if random() > 0.7:
self.image.fill(PURPLE)
self.change_player = True
else:
self.image.fill(ORANGE)
player = Player()
music = Music()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Countdown timer for invincible time
elif event.type == invincible_timer and player.invincible:
player.counter -= 1
if player.counter <= 0:
player.change()
player.counter = 10
player.invincible = False
# Create new shrinker
elif event.type == show_shrinker:
shrinker = Shrinker()
shrinker.change()
# Event for player growth
elif event.type == player.grow_timer:
player.grow()
# Check how many sprites are in ball_sprite
# If less than ball_number create ball
elif event.type == checker:
if len(ball_sprite) < ball_number:
Ball()
for sprite in ball_sprite:
if event.type == sprite.timer:
sprite.move()
elif sprite.moves == 3:
sprite.kill()
if gamestate == 'play':
shuffle(music.tracks)
if not mixer.music.get_busy():
music.play()
screen.fill(BLACK)
keys = pygame.key.get_pressed()
font = pygame.font.SysFont(None, 35)
text = f'Score: {round(player.score)}'
surface = font.render(text, True, CYAN)
screen.blit(surface, (10,10))
if player.invincible:
text = f'Invincible Timer: {player.counter:02}'
surface = font.render(text, True, ORANGE)
screen.blit(surface, (WIDTH-250, 10))
# Detect if player is shieled or not
# If player is shieled get points for ball collision and not die
# Shield will be placed random
shield = False if player.invincible else True
# Detect sprite collisions
collision = pygame.sprite.groupcollide(ball_sprite, player_sprite, True, shield)
# Collision with player and ball. Player not invincible
if collision and not player.invincible:
score = round(player.score)
gamestate = 'page'
# Player is invincible
elif collision and player.invincible:
player.score += 0.50
# Check for collision with shrinker
shrinker_collision = pygame.sprite.groupcollide(shrinker_sprite, player_sprite, True, False)
if shrinker_collision:
player.shrink()
if shrinker.change_player:
player.invincible = True
player.counter = 10
player.score += 0.35
allsprites.update()
allsprites.draw(screen)
pygame.display.update()
CLOCK.tick(FPS)
elif gamestate == 'page':
music.stop()
# Call page and pass player score
page(score=round(player.score))
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
player = Player()
gamestate = 'play'
pygame.quit()