This is my first big project that I started after completing the Pygame Shmup guide put together by KidsCanCode. I'm starting to feel like it's very close to being finished so wanted to post my code here to find out what could be improved or what isn't up to standard. Brownie points for whoever can figure out why the alien animation bugs after reinforcements are generated!
Any comments and/or feedback would be greatly appreciated :)
Github link: https://github.com/Dreadnought88111/Space-WIP
# Space WIP
# By Elias
# things to implement
# boss introduction cinematic
# announ. boss sound
# victory sound
# have aliens jump down vertically rather than diagonally
# known issues:
# aliens speed up when reinforcements are being dropped
# boss and bossvessel rect can be coliided with in level 1 despite them not being generated yet
# temporary fix introduced in the check collisions function not checking collision until level > 9
import math
import pygame
import random
import sys
from os import path
pygame.init()
pygame.mixer.init()
# asset folders
FONT_DIR = path.join(path.dirname(__file__), "fonts")
IMAGE_DIR = path.join(path.dirname(__file__), "images")
SOUND_DIR = path.join(path.dirname(__file__), "sounds")
# screen
WIDTH = 800
HEIGHT = 600
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Space WIP')
pygame.display.set_icon(pygame.image.load(path.join(IMAGE_DIR, "logo.png")).convert_alpha())
FPS = 60
# colours
BLACK = (0, 0, 0)
BLUE = (0, 255, 240)
GREEN = (0, 255, 0)
ORANGE = (255, 173, 0)
PURPLE = (255, 0, 255)
RED = (255, 0, 0)
WHITE = (255, 255, 255)
# fonts
FONT = path.join(FONT_DIR, '8-BitMadness.ttf')
LOGOFONT = path.join(FONT_DIR, "edunline.ttf")
STARTFONT = path.join(FONT_DIR, "upheavtt.ttf")
# images
alien2_1 = pygame.image.load(path.join(IMAGE_DIR, "enemy2_1.png")).convert_alpha()
alien2_2 = pygame.image.load(path.join(IMAGE_DIR, "enemy2_2.png")).convert_alpha()
alien_images = [pygame.transform.scale(alien2_1, (40, 35)), pygame.transform.scale(alien2_2, (40, 35))]
alien3_1 = pygame.image.load(path.join(IMAGE_DIR, "enemy3_1.png")).convert_alpha()
alien3_2 = pygame.image.load(path.join(IMAGE_DIR, "enemy3_2.png")).convert_alpha()
alien_backup_images = [pygame.transform.scale(alien3_1, (40, 35)), pygame.transform.scale(alien3_2, (40, 35))]
alien1_1 = pygame.image.load(path.join(IMAGE_DIR, "enemy1_1.png")).convert_alpha()
alien1_2 = pygame.image.load(path.join(IMAGE_DIR, "enemy1_2.png")).convert_alpha()
alien_elite_images = [pygame.transform.scale(alien1_1, (40, 35)), pygame.transform.scale(alien1_2, (40, 35))]
# music
MUSICVOLUME = 0.5
BACKGROUND1 = path.join(SOUND_DIR, 'Background1.ogg')
BACKGROUND2 = path.join(SOUND_DIR, 'Background2.ogg')
# sounds
SOUNDVOLUME = 0.2
ALIENAPPEAR = pygame.mixer.Sound(path.join(SOUND_DIR, 'AlienAppear.wav'))
ALIENAPPEAR.set_volume(SOUNDVOLUME)
ALIENEXPLOSIONSOUND = pygame.mixer.Sound(path.join(SOUND_DIR, 'AlienExplosion.wav'))
ALIENEXPLOSIONSOUND.set_volume(SOUNDVOLUME)
ALIENMOVESOUND = pygame.mixer.Sound(path.join(SOUND_DIR, 'AlienMove.wav'))
ALIENMOVESOUND.set_volume(SOUNDVOLUME)
GAMEOVER = pygame.mixer.Sound(path.join(SOUND_DIR, 'GameOver.wav'))
GAMEOVER.set_volume(MUSICVOLUME) # not an error
LASERSOUND = pygame.mixer.Sound(path.join(SOUND_DIR, 'Laser.wav'))
LASERSOUND.set_volume(SOUNDVOLUME)
MYSTERYEXPLOSION = pygame.mixer.Sound(path.join(SOUND_DIR, 'MysteryExplosion.wav'))
MYSTERYEXPLOSION.set_volume(SOUNDVOLUME)
PLAYERHIT = pygame.mixer.Sound(path.join(SOUND_DIR, 'PlayerHit.wav'))
PLAYERHIT.set_volume(SOUNDVOLUME)
POWERUPGENERATED = pygame.mixer.Sound(path.join(SOUND_DIR, 'PowerupGenerated.wav'))
POWERUPGENERATED.set_volume(SOUNDVOLUME)
POWERUPPICKEDUP = pygame.mixer.Sound(path.join(SOUND_DIR, 'PowerupPickedUp.wav'))
POWERUPPICKEDUP.set_volume(SOUNDVOLUME)
SATELLITEANNOUNCE = pygame.mixer.Sound(path.join(SOUND_DIR, 'Satelliteannounce.wav'))
SATELLITEANNOUNCE.set_volume(SOUNDVOLUME)
SATELLITEEXPLOSION = pygame.mixer.Sound(path.join(SOUND_DIR, 'SatelliteExplosion.wav'))
SATELLITEEXPLOSION.set_volume(SOUNDVOLUME)
# sprite groups
alien_group = pygame.sprite.Group()
alien_backup_group = pygame.sprite.Group()
alien_elite_group = pygame.sprite.Group()
alien_master_group = pygame.sprite.Group()
alien_reinforcements_group = pygame.sprite.Group()
alien_laser_group = pygame.sprite.Group()
barrier_master_group = pygame.sprite.Group()
boss_group = pygame.sprite.Group()
bossvessel_group = pygame.sprite.Group()
bossvessel_laser_group = pygame.sprite.Group()
explosion_group = pygame.sprite.Group()
laser_group = pygame.sprite.Group()
mystery_group = pygame.sprite.Group()
player_group = pygame.sprite.Group()
powerup_group = pygame.sprite.Group()
satellite_group = pygame.sprite.Group()
star_group = pygame.sprite.Group()
# miscellaneous
should_aliens_drop = False
should_aliens_move = False
ALIENBACKUPSCORE = 20
ALIENDROP = 20
ALIENELITESCORE = 30
ALIENSCORE = 10
ALIENSPEED = 10
ALIENSTARTYPOS = 65
BOSSVESSELDISTANCE = 90
BOSSVESSELMAXHEALTH = 100
LASERSPEED = 5
MYSTERYSCORE = 100
MYSTERYSPEED = 5
MYSTERYTIME = 10
MYSTERYXPOS = -75
PLAYERSPEED = 7
POWERUPSPEED = 2
SATELLITESPEED = -5
SATELLITETIME = 3
SATELLITEXPOS = WIDTH + 31
STARSPEED = 1
time_last_hit = 0
class Player(pygame.sprite.Sprite):
# the text in between brackets above ensure my class Player inherits from
# the pygame Sprite class
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(path.join(IMAGE_DIR, "ship.png")).convert()
self.image = pygame.transform.scale(self.image, (45, 45))
self.rect = self.image.get_rect(topleft=(300, 540))
self.speed = PLAYERSPEED
self.lives = 5
self.score = 0
self.last_shot = pygame.time.get_ticks() / 1000
self.cool_down = 0.5
self.radius = 21
self.double_shot = False
def update(self, keys):
if keys[pygame.K_LEFT] and self.rect.left >= 0:
self.rect.x -= self.speed
if keys[pygame.K_RIGHT] and self.rect.right <= WIDTH:
self.rect.x += self.speed
class Alien(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.index = 0
self.image = alien_images[self.index]
self.rect = self.image.get_rect()
self.alien_last_moved = 0
self.speed = ALIENSPEED
def update(self, now):
global should_aliens_drop
global should_aliens_move
if now - self.alien_last_moved >= 0.5:
self.alien_last_moved = now
if self.rect.right + self.speed >= (WIDTH - 10) or self.rect.left + self.speed <= 10:
should_aliens_drop = True
else:
should_aliens_move = True
class AlienBackup(Alien):
def __init__(self):
super().__init__()
self.image = alien_backup_images[Alien().index]
class AlienElite(Alien):
def __init__(self):
super().__init__()
self.image = alien_elite_images[Alien().index]
class Barrier(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((5, 5))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def update(self, keys, *args):
pass
class Boss(Alien):
def __init__(self):
super().__init__()
self.index = 0
self.image = alien_images[self.index]
self.rect = self.image.get_rect()
self.alien_last_moved = 0
self.speed = ALIENSPEED
def update(self, now, *args):
global should_aliens_drop
global should_aliens_move
if now - self.alien_last_moved >= 0.5:
self.alien_last_moved = now
if self.rect.right + (bossvessel.width / 2) + self.speed >= (WIDTH - 10) \
or self.rect.left - (bossvessel.width / 2) + self.speed <= 10:
should_aliens_drop = True
else:
should_aliens_move = True
class Bossvessel(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.width = 220
self.height = 200
self.image = pygame.image.load(path.join(IMAGE_DIR, "boss.png")).convert_alpha()
self.image = pygame.transform.scale(self.image, (self.width, self.height)) # 11, 10
self.rect = self.image.get_rect()
self.health = BOSSVESSELMAXHEALTH
def update(self):
self.rect.centerx = boss.rect.centerx
self.rect.centery = boss.rect.centery + BOSSVESSELDISTANCE
class ExplosionBlue(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(path.join(IMAGE_DIR, "explosionblue.png")).convert_alpha()
self.image = pygame.transform.scale(self.image, (45, 45))
self.rect = self.image.get_rect()
self.rect.x = x - 5
self.rect.y = y - 7
self.timer = pygame.time.get_ticks()
def update(self, current_time):
passed = (current_time * 1000) - self.timer
if passed >= 200:
self.kill()
class ExplosionGreen(ExplosionBlue):
def __init__(self, x, y):
super().__init__(x, y)
self.image = pygame.image.load(path.join(IMAGE_DIR, "explosiongreen.png")).convert_alpha()
self.image = pygame.transform.scale(self.image, (45, 45))
class ExplosionPurple(ExplosionBlue):
def __init__(self, x, y):
super().__init__(x, y)
self.image = pygame.image.load(path.join(IMAGE_DIR, "explosionpurple.png")).convert_alpha()
self.image = pygame.transform.scale(self.image, (45, 45))
class ExplosionRed(ExplosionBlue):
def __init__(self, x, y):
super().__init__(x, y)
self.image = pygame.image.load(path.join(IMAGE_DIR, "explosionred.png")).convert_alpha()
self.image = pygame.transform.scale(self.image, (45, 45))
class Laser(pygame.sprite.Sprite):
def __init__(self, x, y, speed, colour):
pygame.sprite.Sprite.__init__(self)
self.width = 2
self.height = 4
self.image = pygame.Surface((self.width, self.height))
self.colour = colour
self.image.fill(self.colour)
self.rect = self.image.get_rect()
self.speed = speed
self.rect.centerx = x
self.rect.centery = y
def update(self):
self.rect.y -= self.speed
if self.rect.y + (self.height / 2) <= 0 or self.rect.y - (self.height / 2) >= HEIGHT:
self.kill()
class Mystery(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.width = 75
self.height = 35
self.image = pygame.image.load(path.join(IMAGE_DIR, "mystery.png")).convert_alpha()
self.image = pygame.transform.scale(self.image, (self.width, self.height))
self.rect = self.image.get_rect()
self.speed = MYSTERYSPEED
self.last_appeared = 0
self.last_stopped = 0
self.rect.x = MYSTERYXPOS
self.rect.y = 25
def update(self, level, levelstarttime, now):
if len(mystery_group) == 1:
self.rect.x += self.speed
# Past lvl 3 when hit after it never returns due to speed never being reset to 5
if not ((WIDTH / 2) - 2 <= self.rect.centerx <= (WIDTH / 2) + 2):
self.speed = MYSTERYSPEED
if self.rect.x >= WIDTH:
self.last_stopped = 0
self.kill()
if 11 > level >= 6 and 60 >= (now - levelstarttime) >= 30:
if self.speed == 0 and (now - self.last_stopped) >= 3 and len(mystery_group) == 1 \
and (WIDTH / 2) - 2 <= self.rect.centerx <= (WIDTH / 2) + 2:
generate_alien_reinforcements()
ALIENAPPEAR.play()
self.rect.centerx = (WIDTH / 2) + 3
self.speed = MYSTERYSPEED
self.last_appeared = now
self.rect.x = (WIDTH / 2) + 6
if self.speed != 0 and (WIDTH / 2) - 2 <= self.rect.centerx <= (WIDTH / 2) + 2:
self.speed = 0
self.last_stopped = now
class Powerup(pygame.sprite.Sprite):
def __init__(self, x, y, colour):
pygame.sprite.Sprite.__init__(self)
self.width = 4
self.height = 20
self.image = pygame.Surface((self.width, self.height))
self.colour = colour
self.image.fill(self.colour)
self.rect = self.image.get_rect()
self.speed = POWERUPSPEED
self.generated_this_level = False
self.rect.centerx = x
self.rect.y = y
def update(self):
self.rect.y += self.speed
if self.rect.top >= HEIGHT:
self.kill()
class Satellite(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(path.join(IMAGE_DIR, "satellite.png")).convert_alpha()
self.image = pygame.transform.scale(self.image, (106, 40))
self.rect = self.image.get_rect()
self.speed = SATELLITESPEED
self.rect.x = SATELLITEXPOS
self.rect.y = 25
self.powerup_generated = False
self.last_stopped = 0
self.stopped_this_level = False
def update(self, now):
self.rect.x += self.speed
if self.rect.right <= 0:
self.kill()
if len(satellite_group) > 0 and self.rect.right <= WIDTH and self.rect.left >= 0 \
and not self.stopped_this_level:
if random.randint(1, 200) == 1:
self.last_stopped = pygame.time.get_ticks() / 1000
self.speed = 0
self.stopped_this_level = True
if 2 > now - self.last_stopped > 1 and len(powerup_group) == 0:
generate_powerup()
POWERUPGENERATED.play()
self.powerup_generated = True
if now - self.last_stopped >= 3:
self.speed = SATELLITESPEED
class Star(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([1, 1])
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.speed = STARSPEED
def update(self):
self.rect.y += self.speed
if self.rect.y >= HEIGHT:
self.rect.y = 0
# functions
def alien_drop():
for alien in alien_master_group:
alien.rect.y += ALIENDROP
alien.speed *= -1
def alien_move():
if len(boss_group) == 0:
for alien in alien_master_group:
alien.rect.x += alien.speed
for alien in alien_group:
alien.index += 1
if alien.index >= 2:
alien.index = 0
alien.image = alien_images[alien.index]
for alien in alien_backup_group:
alien.index += 1
if alien.index >= 2:
alien.index = 0
alien.image = alien_backup_images[alien.index]
for alien in alien_elite_group:
alien.index += 1
if alien.index >= 2:
alien.index = 0
alien.image = alien_elite_images[alien.index]
else:
for alien in alien_master_group:
alien.rect.x += alien.speed
for alien in alien_group:
alien.index += 1
if alien.index >= 2:
alien.index = 0
alien.image = alien_images[alien.index]
def alien_shoot():
if len(alien_laser_group) <= math.trunc(len(alien_group) / 10) and len(alien_group) > 0:
alien = random.choice(list(alien_group))
laser = Laser(alien.rect.centerx, alien.rect.centery, -LASERSPEED, BLUE)
alien_laser_group.add(laser)
if len(alien_laser_group) <= math.trunc(len(alien_backup_group) / 5) and len(alien_backup_group) > 0:
alien = random.choice(list(alien_backup_group))
laser = Laser(alien.rect.centerx, alien.rect.centery, -LASERSPEED, GREEN)
alien_laser_group.add(laser)
if len(alien_laser_group) <= math.trunc(len(alien_elite_group) / 2) and len(alien_elite_group) > 0:
alien = random.choice(list(alien_elite_group))
laser = Laser(alien.rect.centerx, alien.rect.centery, -LASERSPEED, PURPLE)
alien_laser_group.add(laser)
if len(alien_laser_group) <= math.trunc(len(alien_reinforcements_group) / 2) and len(
alien_reinforcements_group) > 0:
alien = random.choice(list(alien_reinforcements_group))
laser = Laser(alien.rect.centerx, alien.rect.centery, -LASERSPEED, PURPLE)
alien_laser_group.add(laser)
def bossvessel_shoot():
if len(bossvessel_group) > 0 and bossvessel.health > 0 and len(bossvessel_laser_group) < random.randint(0, 9):
laser = Laser(bossvessel.rect.left + (random.randint(0, 6) * 35), bossvessel.rect.y + bossvessel.height,
-LASERSPEED, RED)
bossvessel_laser_group.add(laser)
def check_collisions(now, bossgrouplen):
global time_last_hit
for alien in alien_master_group:
for barrier in barrier_master_group:
if alien.rect.colliderect(barrier.rect):
barrier.kill()
if alien.rect.colliderect(player.rect):
explosion_group.add(ExplosionGreen(alien.rect.x, alien.rect.y))
explosion_group.add(ExplosionGreen(player.rect.x, player.rect.y))
player.lives = 0
alien.kill()
ALIENEXPLOSIONSOUND.play()
player.kill()
pygame.sprite.groupcollide(alien_laser_group, barrier_master_group, True, True)
pygame.sprite.groupcollide(bossvessel_laser_group, barrier_master_group, True, True)
pygame.sprite.groupcollide(laser_group, barrier_master_group, True, True)
for laser in laser_group:
for alien in alien_group:
if laser.rect.colliderect(alien.rect):
explosion_group.add(ExplosionBlue(alien.rect.x, alien.rect.y))
player.score += ALIENSCORE
laser.kill()
alien.kill()
ALIENEXPLOSIONSOUND.play()
time_last_hit = now
for alien in alien_backup_group:
if laser.rect.colliderect(alien.rect):
explosion_group.add(ExplosionGreen(alien.rect.x, alien.rect.y))
player.score += ALIENBACKUPSCORE
laser.kill()
alien.kill()
ALIENEXPLOSIONSOUND.play()
time_last_hit = now
for alien in alien_elite_group:
if laser.rect.colliderect(alien.rect):
explosion_group.add(ExplosionPurple(alien.rect.x, alien.rect.y))
player.score += ALIENELITESCORE
laser.kill()
alien.kill()
ALIENEXPLOSIONSOUND.play()
time_last_hit = now
for alien in alien_reinforcements_group:
if laser.rect.colliderect(alien.rect):
explosion_group.add(ExplosionPurple(alien.rect.x, alien.rect.y))
player.score += ALIENELITESCORE
laser.kill()
alien.kill()
ALIENEXPLOSIONSOUND.play()
time_last_hit = now
if bossgrouplen > 0:
if laser.rect.colliderect(boss.rect):
laser.kill()
time_last_hit = now
if laser.rect.colliderect(bossvessel.rect):
bossvessel.health -= 1
if bossvessel.health <= 0:
explosion_group.add(ExplosionGreen(boss.rect.centerx, boss.rect.y))
boss.kill()
explosion_group.add(ExplosionRed(bossvessel.rect.centerx, bossvessel.rect.y))
bossvessel.kill()
laser.kill()
time_last_hit = now
if laser.rect.colliderect(mystery.rect):
explosion_group.add(ExplosionRed(mystery.rect.centerx, mystery.rect.y))
player.score += MYSTERYSCORE
mystery.rect.x = MYSTERYXPOS
laser.kill()
mystery.kill()
MYSTERYEXPLOSION.play()
time_last_hit = now
if laser.rect.colliderect(satellite.rect):
explosion_group.add(ExplosionBlue(satellite.rect.centerx, satellite.rect.y))
satellite.rect.x = SATELLITEXPOS
laser.kill()
satellite.kill()
SATELLITEEXPLOSION.play()
time_last_hit = now
for laser in alien_laser_group:
hits = pygame.sprite.spritecollide(laser, player_group, False, pygame.sprite.collide_circle)
for hit in hits:
player_hit()
laser.kill()
time_last_hit = now
if player.lives == 0:
explosion_group.add(ExplosionGreen(player.rect.x, player.rect.y))
player.kill()
for laser in bossvessel_laser_group:
hits = pygame.sprite.spritecollide(laser, player_group, False, pygame.sprite.collide_circle)
for hit in hits:
player_hit()
laser.kill()
time_last_hit = now
if player.lives == 0:
explosion_group.add(ExplosionGreen(player.rect.x, player.rect.y))
player.kill()
for powerup in powerup_group:
if powerup.rect.colliderect(player.rect):
powerup.kill()
POWERUPPICKEDUP.play()
if player.lives < 5:
randnumber = random.randint(1, 3)
if randnumber == 1:
player.double_shot = True
elif randnumber == 2:
num = random.randint(0, 3)
generate_barrier(num, num + 1)
else:
player.lives += 1
elif player.lives == 5:
randnumber = random.randint(1, 2)
if randnumber == 1:
player.double_shot = True
else:
num = random.randint(0, 3)
generate_barrier(num, num + 1)
def draw_boss_health_bar(screen):
pygame.draw.rect(screen, RED, pygame.Rect(5, HEIGHT - 10, WIDTH - 10, 10), 2)
pygame.draw.rect(screen, RED,
pygame.Rect(5, HEIGHT - 10, (WIDTH - 10) * (bossvessel.health / BOSSVESSELMAXHEALTH), 10))
def draw_lives(surf, x, y, lives, img):
for i in range(lives):
img_rect = img.get_rect()
img_rect.x = x + 30 * i
img_rect.y = y
surf.blit(img, img_rect)
def draw_text(surf, font, size, text, colour, x, y, location):
font = pygame.font.Font(font, size)
text_surface = font.render(text, True, colour)
text_rect = text_surface.get_rect()
if location == 'center':
text_rect.center = (x, y)
elif location == 'left':
text_rect.midleft = (x, y)
surf.blit(text_surface, text_rect)
def generate_barrier(num1, num2):
for i in range(num1, num2):
for x in range(20):
for y in range(10):
barrier = Barrier(50 + (x * 5) + (200 * i), 525 - (y * 5))
barrier_master_group.add(barrier)
def generate_aliens_lvl1():
for x in range(10):
for y in range(2):
alien = Alien()
alien.rect.x = 50 + (x * 50)
alien.rect.y = ALIENSTARTYPOS + (y * 45)
alien_group.add(alien)
alien_master_group.add(alien)
def generate_aliens_lvl2():
for x in range(10):
for y in range(4):
if y in (0, 1):
alien = AlienBackup()
alien.rect.x = 50 + (x * 50)
alien.rect.y = ALIENSTARTYPOS + (y * 45)
alien_backup_group.add(alien)
alien_master_group.add(alien)
elif y in (2, 3):
alien = Alien()
alien.rect.x = 50 + (x * 50)
alien.rect.y = ALIENSTARTYPOS + (y * 45)
alien_group.add(alien)
alien_master_group.add(alien)
def generate_aliens_lvl3():
for x in range(10):
for y in range(5):
if y == 0:
alien = AlienElite()
alien.rect.x = 50 + (x * 50)
alien.rect.y = ALIENSTARTYPOS + (y * 45)
alien_elite_group.add(alien)
alien_master_group.add(alien)
elif y in (1, 2):
alien = AlienBackup()
alien.rect.x = 50 + (x * 50)
alien.rect.y = ALIENSTARTYPOS + (y * 45)
alien_backup_group.add(alien)
alien_master_group.add(alien)
elif y in (3, 4):
alien = Alien()
alien.rect.x = 50 + (x * 50)
alien.rect.y = ALIENSTARTYPOS + (y * 45)
alien_group.add(alien)
alien_master_group.add(alien)
def generate_alien_reinforcements():
for x in range(5):
alien = AlienElite()
alien.rect.x = ((WIDTH / 2) - 120) + (x * 50)
alien.rect.y = ALIENSTARTYPOS
alien_reinforcements_group.add(alien)
alien_master_group.add(alien)
def generate_boss():
boss.rect.centerx = WIDTH / 2
boss.rect.y = ALIENSTARTYPOS
alien_group.add(boss)
alien_master_group.add(boss)
boss_group.add(boss)
def generate_boss_vessel():
bossvessel.rect.centerx = boss.rect.centerx
bossvessel.rect.centery = boss.rect.centery + BOSSVESSELDISTANCE
bossvessel_group.add(bossvessel)
def generate_mystery():
mystery.rect.x = MYSTERYXPOS
mystery_group.add(mystery)
mystery.last_appeared = pygame.time.get_ticks() / 1000
def generate_powerup():
powerup = Powerup(satellite.rect.centerx, satellite.rect.centery, ORANGE)
if powerup.generated_this_level is False:
powerup.generated_this_level = True
powerup_group.add(powerup)
def generate_satellite():
satellite.rect.x = SATELLITEXPOS
satellite_group.add(satellite)
def generate_stars():
for i in range(random.randint(80, 120)):
x = random.randint(1, WIDTH - 1)
y = random.randint(1, HEIGHT - 1)
star = Star()
star.rect.x = x
star.rect.y = y
star_group.add(star)
def intermission_screen(screen, image_name, image_scale_x, image_scale_y, screen_pos_x, screen_pos_y,
text, text_pos_x, text_pos_y, text_loc):
load_screen_image = pygame.image.load(path.join(IMAGE_DIR, image_name)).convert_alpha()
image = pygame.transform.scale(load_screen_image, (image_scale_x, image_scale_y))
screen.blit(image, (screen_pos_x, screen_pos_y))
draw_text(screen, FONT, 52, text, WHITE, text_pos_x, text_pos_y, text_loc)
def pauze_background_music():
pygame.mixer.music.pause()
def play_background_music():
if random.randint(1, 2) == 1:
pygame.mixer.music.load(BACKGROUND1)
else:
pygame.mixer.music.load(BACKGROUND2)
pygame.mixer.music.set_volume(MUSICVOLUME)
pygame.mixer.music.play(-1)
def player_hit():
player.lives -= 1
PLAYERHIT.play()
def unpauze_background_music():
pygame.mixer.music.unpause()
# miscellaneous
player = Player()
player_group.add(player)
boss = Boss()
bossvessel = Bossvessel()
mystery = Mystery()
satellite = Satellite()
class SpaceInvaders(object):
def __init__(self):
pygame.init()
self.clock = pygame.time.Clock()
self.fps = self.clock.get_fps()
self.screen = SCREEN
self.now = pygame.time.get_ticks() / 1000
self.levelstarttime = 0
self.level = 1
self.menu()
def game_over(self, endgame):
pygame.mixer.music.stop()
if endgame == 0:
endgametext = "GAME OVER"
endgamecolour = RED
else:
endgametext = "VICTORY"
endgamecolour = GREEN
pygame.time.wait(2000)
draw_text(self.screen, FONT, 64, endgametext, endgamecolour, WIDTH / 2, HEIGHT / 2, 'center')
GAMEOVER.play()
pygame.display.update()
pygame.time.wait(2000)
draw_text(self.screen, FONT, 32, "Press space bar to restart", WHITE, WIDTH / 2, (HEIGHT / 2) + 50, 'center')
draw_text(self.screen, FONT, 32, "or press escape to quit", WHITE, WIDTH / 2, (HEIGHT / 2) + 100, 'center')
pygame.display.update()
pygame.time.wait(2000)
SCREEN.fill(BLACK)
draw_text(self.screen, FONT, 64, endgametext, endgamecolour, WIDTH / 2, HEIGHT / 2, 'center')
draw_text(self.screen, FONT, 32, "Press space bar to restart", WHITE, WIDTH / 2, (HEIGHT / 2) + 50, 'center')
draw_text(self.screen, FONT, 32, "or press escape to quit", WHITE, WIDTH / 2, (HEIGHT / 2) + 100, 'center')
pygame.display.update()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
self.level = 1
self.new_game()
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
def intermission(self):
pauze_background_music()
pygame.time.wait(2000)
self.screen.fill(BLACK)
if 11 > self.level >= 1:
intermission_screen(self.screen, "ship.png", 45, 45, 50, (HEIGHT * 0.25) + 50,
'= Player', 100, (HEIGHT * 0.25) + 75, 'left')
intermission_screen(self.screen, "enemy2_1.png", 45, 45, (WIDTH / 2) + 50, (HEIGHT * 0.25) + 50,
'= ' + str(ALIENSCORE) + ' points', (WIDTH / 2) + 100, (HEIGHT * 0.25) + 75, 'left')
if 11 > self.level >= 2:
intermission_screen(self.screen, "enemy3_2.png", 45, 45, 50, (HEIGHT * 0.25) + 150,
'= ' + str(ALIENBACKUPSCORE) + ' points', 100, (HEIGHT * 0.25) + 175, 'left')
if 11 > self.level >= 3:
intermission_screen(self.screen, "enemy1_1.png", 45, 45, (WIDTH / 2) + 50, (HEIGHT * 0.25) + 150
, '= ' + str(ALIENELITESCORE) + ' points', (WIDTH / 2) + 100, (HEIGHT * 0.25) + 175, 'left')
if 11 > self.level >= 4:
intermission_screen(self.screen, "mystery.png", 75, 35, 35, (HEIGHT * 0.25) + 250,
'= ' + str(MYSTERYSCORE) + ' points', 110, (HEIGHT * 0.25) + 275, 'left')
if 11 > self.level >= 5:
intermission_screen(self.screen, "satellite.png", 106, 40, (WIDTH / 2) + 20, (HEIGHT * 0.25) + 250
, "= don't shoot", (WIDTH / 2) + 125, (HEIGHT * 0.25) + 275, 'left')
intermission_screen(self.screen, "powerup.png", 8, 40, (WIDTH / 2) + 75, (HEIGHT * 0.25) + 350
, "= powerup", (WIDTH / 2) + 100, (HEIGHT * 0.25) + 375, 'left')
if self.level == 6:
draw_text(self.screen, FONT, 52, 'Watch out for reinforcements', RED, WIDTH / 2, 50, 'center')
if self.level <= 10:
draw_text(self.screen, FONT, 52, 'level ' + str(int(self.level)), GREEN, WIDTH / 2, (HEIGHT * 0.25), 'center')
elif self.level == 11:
draw_text(self.screen, FONT, 52, 'FINAL BOSS', RED, WIDTH / 2, (HEIGHT / 2), 'center')
pygame.display.update()
pygame.time.wait(3000)
unpauze_background_music()
def menu(self):
generate_stars()
while True:
button = pygame.Rect((WIDTH / 2) - 100, (HEIGHT / 2), 200, 100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
if button.collidepoint(event.pos):
pygame.time.wait(2000)
self.intermission()
self.new_game()
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
self.intermission()
self.new_game()
keys = pygame.key.get_pressed()
self.screen.fill(BLACK)
pygame.draw.rect(self.screen, BLACK, button)
star_group.update()
star_group.draw(self.screen)
draw_text(self.screen, STARTFONT, 64, 'START', WHITE, button.centerx, button.centery, 'center')
draw_text(self.screen, LOGOFONT, 80, 'SPACE INVADERS', GREEN, WIDTH / 2, (HEIGHT / 2) - 100, 'center')
draw_text(self.screen, FONT, 25, 'Or press SPACE to start the game', WHITE, WIDTH / 2,
(HEIGHT - 100), 'center')
draw_text(self.screen, FONT, 25, 'Use arrow keys to move and space bar to shoot', WHITE, WIDTH / 2,
(HEIGHT - 50), 'center')
pygame.display.flip()
self.clock.tick(FPS)
def new_game(self):
global alien_group
alien_group = pygame.sprite.Group()
global alien_backup_group
alien_backup_group = pygame.sprite.Group()
global alien_elite_group
alien_elite_group = pygame.sprite.Group()
global alien_master_group
alien_master_group = pygame.sprite.Group()
global alien_reinforcements_group
alien_reinforcements_group = pygame.sprite.Group()
global alien_laser_group
alien_laser_group = pygame.sprite.Group()
global boss_group
boss_group = pygame.sprite.Group()
global bossvessel_group
bossvessel_group = pygame.sprite.Group()
global explosion_group
explosion_group = pygame.sprite.Group()
global laser_group
laser_group = pygame.sprite.Group()
global mystery_group
mystery_group = pygame.sprite.Group()
global powerup_group
powerup_group = pygame.sprite.Group()
global satellite_group
satellite_group = pygame.sprite.Group()
if self.level == 1:
global barrier_master_group
barrier_master_group = pygame.sprite.Group()
global player_group
player_group = pygame.sprite.Group()
global star_group
star_group = pygame.sprite.Group()
global player
player = Player()
player_group.add(player)
player.lives = 5
player.score = 0
generate_aliens_lvl1()
elif self.level == 2:
generate_aliens_lvl2()
elif 11 > self.level >= 3:
generate_aliens_lvl3()
if self.level <= 3:
generate_barrier(0, 4)
if self.level == 11:
generate_boss()
generate_boss_vessel()
generate_stars()
play_background_music()
mystery.last_appeared = pygame.time.get_ticks() / 1000
satellite.appeared_this_level = False
self.game_loop()
def game_start(self):
self.menu()
def game_loop(self):
while True:
self.now = (pygame.time.get_ticks() / 1000)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.K_SPACE and player.lives == 0:
SpaceInvaders()
global should_aliens_drop
should_aliens_drop = False
global should_aliens_move
should_aliens_move = False
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
if player.lives > 0:
if self.now - player.last_shot >= player.cool_down and not player.double_shot:
player.last_shot = self.now
laser = Laser(player.rect.centerx, player.rect.y, LASERSPEED, GREEN)
laser_group.add(laser)
LASERSOUND.play()
if self.now - player.last_shot >= player.cool_down and player.double_shot:
player.last_shot = self.now
laser = Laser(player.rect.centerx - 15, player.rect.y + 20, LASERSPEED, GREEN)
laser_group.add(laser)
laser = Laser(player.rect.centerx + 15, player.rect.y + 20, LASERSPEED, GREEN)
laser_group.add(laser)
LASERSOUND.play(1)
self.screen.fill(BLACK)
star_group.update()
star_group.draw(self.screen)
alien_master_group.update(self.now)
alien_master_group.draw(self.screen)
if should_aliens_drop:
alien_drop()
should_aliens_drop = False
if should_aliens_move:
alien_move()
should_aliens_move = False
alien_laser_group.update()
alien_laser_group.draw(self.screen)
barrier_master_group.update(keys)
barrier_master_group.draw(self.screen)
bossvessel_group.update(keys)
bossvessel_group.draw(self.screen)
bossvessel_laser_group.update(keys)
bossvessel_laser_group.draw(self.screen)
if self.level >= 10 and len(boss_group) == 1:
draw_boss_health_bar(self.screen)
explosion_group.update(self.now)
explosion_group.draw(self.screen)
laser_group.update()
laser_group.draw(self.screen)
mystery_group.update(self.level, self.levelstarttime, self.now)
mystery_group.draw(self.screen)
if self.level >= 4 and len(mystery_group) == 0 and (self.now - mystery.last_appeared) >= MYSTERYTIME:
generate_mystery()
player_group.update(keys)
player_group.draw(self.screen)
powerup_group.update(keys)
powerup_group.draw(self.screen)
satellite_group.update(self.now)
satellite_group.draw(self.screen)
if self.level >= 5 and len(satellite_group) == 0 and random.randint(1, 750) == 1 \
and not satellite.powerup_generated:
generate_satellite()
SATELLITEANNOUNCE.play()
check_collisions(self.now, len(boss_group))
# print(len(bossvessel_group))
draw_text(self.screen, FONT, 32, 'FPS ' + str(int(self.clock.get_fps())), WHITE, WIDTH - 60, 14, 'center')
draw_text(self.screen, FONT, 32, 'SCORE ' + str(int(player.score)), WHITE, WIDTH / 2, 14, 'center')
draw_lives(self.screen, 10, 5, player.lives, pygame.transform.scale(player.image, (18, 18)))
if player.lives == 0 and self.now - time_last_hit >= 2:
self.game_over(len(player_group))
if len(alien_master_group) == 0 and self.now - time_last_hit >= 2:
satellite.stopped_this_level = False
self.level += 1
self.levelstarttime = self.now
player.double_shot = False
self.intermission()
self.new_game()
if len(boss_group) == 0:
alien_shoot()
else:
bossvessel_shoot()
pygame.display.flip()
self.clock.tick(FPS)
if __name__ == '__main__':
# Make a game instance, and run the game.
game = SpaceInvaders()
# game.game_loop()
game.menu()
pygame.display.set_icon(pygame.image.load(path.join(IMAGE_DIR, "logo.png")).convert_alpha()) FileNotFoundError: No such file or directory.
You'll need to post the assets somewhere (perhaps on github/gitlab?) so we can see how the game runs. \$\endgroup\$