Это мой первый большой проект, который я начал после завершения руководства Pygame Shmup, составленного KidsCanCode. Я начинаю чувствовать, что это очень близко к завершению, поэтому я хотел опубликовать здесь свой код, чтобы узнать, что можно улучшить, а что не соответствует стандартам. Очки Брауни для тех, кто может понять, почему возникают ошибки анимации пришельцев после подкрепления!
Будем очень благодарны за любые комментарии и / или отзывы 🙂
Ссылка на Github: 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()