diff --git a/controller-keys.json b/controller-keys.json new file mode 100644 index 0000000..7511bf1 --- /dev/null +++ b/controller-keys.json @@ -0,0 +1,19 @@ +{ + "x": 0, + "circle": 1, + "square": 2, + "triangle": 3, + "share": 4, + "PS": 5, + "options": 6, + "left_stick_click": 7, + "right_stick_click": 8, + "L1": 9, + "R1": 10, + "up_arrow": 11, + "down_arrow": 12, + "left_arrow": 13, + "right_arrow": 14, + "touchpad": 15 + + } \ No newline at end of file diff --git a/images/artie.svg b/images/artie.svg new file mode 100644 index 0000000..ead712f --- /dev/null +++ b/images/artie.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/background.jpg b/images/background.jpg index 1630cf5..4e4afa6 100644 Binary files a/images/background.jpg and b/images/background.jpg differ diff --git a/images/enemy1_1.png b/images/enemy1_1.png index 7cf439c..1b97e42 100644 Binary files a/images/enemy1_1.png and b/images/enemy1_1.png differ diff --git a/images/enemy1_2.png b/images/enemy1_2.png index 6997674..bda0734 100644 Binary files a/images/enemy1_2.png and b/images/enemy1_2.png differ diff --git a/images/enemy2_1.png b/images/enemy2_1.png index 93096c1..8980dd7 100644 Binary files a/images/enemy2_1.png and b/images/enemy2_1.png differ diff --git a/images/enemy2_2.png b/images/enemy2_2.png index 1bbe526..6969bc1 100644 Binary files a/images/enemy2_2.png and b/images/enemy2_2.png differ diff --git a/images/enemy3_1.png b/images/enemy3_1.png index 2102c38..fab6bc0 100644 Binary files a/images/enemy3_1.png and b/images/enemy3_1.png differ diff --git a/images/enemy3_2.png b/images/enemy3_2.png index 97e2638..d936d03 100644 Binary files a/images/enemy3_2.png and b/images/enemy3_2.png differ diff --git a/images/enemylaser.png b/images/enemylaser.png index 85efadc..fafc686 100644 Binary files a/images/enemylaser.png and b/images/enemylaser.png differ diff --git a/images/laser.png b/images/laser.png index fafc686..85efadc 100644 Binary files a/images/laser.png and b/images/laser.png differ diff --git a/images/old-ship.png b/images/old-ship.png new file mode 100644 index 0000000..e383b6d Binary files /dev/null and b/images/old-ship.png differ diff --git a/images/ship.png b/images/ship.png index e383b6d..d501454 100644 Binary files a/images/ship.png and b/images/ship.png differ diff --git a/leaderboard.json b/leaderboard.json new file mode 100644 index 0000000..8c9b7bd --- /dev/null +++ b/leaderboard.json @@ -0,0 +1 @@ +{"First": 123, "Second": 122, "Third": 121} \ No newline at end of file diff --git a/spaceinvaders.py b/spaceinvaders.py index 96d43ec..d600720 100755 --- a/spaceinvaders.py +++ b/spaceinvaders.py @@ -5,6 +5,8 @@ from pygame import * import sys +import os +import json from os.path import abspath, dirname from random import choice @@ -16,12 +18,13 @@ # Colors (R, G, B) WHITE = (255, 255, 255) GREEN = (78, 255, 87) -YELLOW = (241, 255, 0) +YELLOW = (255, 209, 0) BLUE = (80, 255, 239) PURPLE = (203, 0, 255) RED = (237, 28, 36) -SCREEN = display.set_mode((800, 600)) + +SCREEN = display.set_mode((0,0)) FONT = FONT_PATH + 'space_invaders.ttf' IMG_NAMES = ['ship', 'mystery', 'enemy1_1', 'enemy1_2', @@ -32,22 +35,43 @@ IMAGES = {name: image.load(IMAGE_PATH + '{}.png'.format(name)).convert_alpha() for name in IMG_NAMES} -BLOCKERS_POSITION = 450 -ENEMY_DEFAULT_POSITION = 65 # Initial value for a new game +PLAYER_NAME = ['A', 'A', 'A'] +CURSOR_POSITION = 0 +CURSOR_LETTER = 0 +ROUND = 1 + +BLOCKERS_POSITION = 1450 +ENEMY_DEFAULT_POSITION = 750 # Initial value for a new game ENEMY_MOVE_DOWN = 35 +with open(os.path.join("controller-keys.json"), 'r+') as file: + button_keys = json.load(file) +# 0: Left analog horizonal, 1: Left Analog Vertical, 2: Right Analog Horizontal +# 3: Right Analog Vertical 4: Left Trigger, 5: Right Trigger +analog_keys = {0:0, 1:0, 2:0, 3:0, 4:-1, 5: -1 } + +joystick.init() +joysticks = [] +for i in range(joystick.get_count()): + joysticks.append(joystick.Joystick(i)) +for joystick in joysticks: + joystick.init() class Ship(sprite.Sprite): def __init__(self): sprite.Sprite.__init__(self) self.image = IMAGES['ship'] - self.rect = self.image.get_rect(topleft=(375, 540)) - self.speed = 5 + self.rect = self.image.get_rect(topleft=(375, 1540)) + self.speed = 8 - def update(self, keys, *args): - if keys[K_LEFT] and self.rect.x > 10: + def update(self, keys, buttons, *args): + if keys[K_LEFT] and self.rect.x > 100: + self.rect.x -= self.speed + if keys[K_RIGHT] and self.rect.x < 1300: + self.rect.x += self.speed + if buttons['left_arrow'] and self.rect.x > 100: self.rect.x -= self.speed - if keys[K_RIGHT] and self.rect.x < 740: + if buttons['right_arrow'] and self.rect.x < 1300: self.rect.x += self.speed game.screen.blit(self.image, self.rect) @@ -65,9 +89,19 @@ def __init__(self, xpos, ypos, direction, speed, filename, side): def update(self, keys, *args): game.screen.blit(self.image, self.rect) self.rect.y += self.speed * self.direction - if self.rect.y < 15 or self.rect.y > 600: + if self.rect.y < 700 or self.rect.y > 1600: self.kill() +class Leaderboard(): + def __init__(self): + self.total = 0 + self.leaderboard + + def incrementScore(self): + self.total += 1 + + def storeHighScore(self, name): + leaderboard class Enemy(sprite.Sprite): def __init__(self, row, column): @@ -104,13 +138,14 @@ def load_images(self): class EnemiesGroup(sprite.Group): def __init__(self, columns, rows): + global ROUND sprite.Group.__init__(self) self.enemies = [[None] * columns for _ in range(rows)] self.columns = columns self.rows = rows self.leftAddMove = 0 self.rightAddMove = 0 - self.moveTime = 600 + self.moveTime = 85 - (10 * ROUND) self.direction = 1 self.rightMoves = 30 self.leftMoves = 30 @@ -120,6 +155,7 @@ def __init__(self, columns, rows): self._aliveColumns = list(range(columns)) self._leftAliveColumn = 0 self._rightAliveColumn = columns - 1 + self.multiplier = 0.5 + ROUND / 2 def update(self, current_time): if current_time - self.timer > self.moveTime: @@ -140,11 +176,12 @@ def update(self, current_time): if self.bottom < enemy.rect.y + 35: self.bottom = enemy.rect.y + 35 else: - velocity = 10 if self.direction == 1 else -10 + velocity = 15 if self.direction == 1 else -15 for enemy in self: enemy.rect.x += velocity enemy.toggle_image() self.moveNumber += 1 + self.timer += self.moveTime @@ -171,9 +208,9 @@ def random_bottom(self): def update_speed(self): if len(self) == 1: - self.moveTime = 200 + self.moveTime -= 10 elif len(self) <= 10: - self.moveTime = 400 + self.moveTime -= 5 def kill(self, enemy): self.enemies[enemy.row][enemy.column] = None @@ -215,7 +252,7 @@ def __init__(self): sprite.Sprite.__init__(self) self.image = IMAGES['mystery'] self.image = transform.scale(self.image, (75, 35)) - self.rect = self.image.get_rect(topleft=(-80, 45)) + self.rect = self.image.get_rect(topleft=(-80, 800)) self.row = 5 self.moveTime = 25000 self.direction = 1 @@ -224,7 +261,7 @@ def __init__(self): self.mysteryEntered.set_volume(0.3) self.playSound = True - def update(self, keys, currentTime, *args): + def update(self, keys, _buttons, currentTime, *args): resetTimer = False passed = currentTime - self.timer if passed > self.moveTime: @@ -309,7 +346,7 @@ class Life(sprite.Sprite): def __init__(self, xpos, ypos): sprite.Sprite.__init__(self) self.image = IMAGES['ship'] - self.image = transform.scale(self.image, (23, 23)) + self.image = transform.scale(self.image, (40, 40)) self.rect = self.image.get_rect(topleft=(xpos, ypos)) def update(self, *args): @@ -318,12 +355,82 @@ def update(self, *args): class Text(object): def __init__(self, textFont, size, message, color, xpos, ypos): + self.message = message + self.xpos = xpos + self.ypos = ypos self.font = font.Font(textFont, size) self.surface = self.font.render(message, True, color) - self.rect = self.surface.get_rect(topleft=(xpos, ypos)) + self.rect = self.surface.get_rect(topleft=(self.xpos, ypos)) def draw(self, surface): surface.blit(self.surface, self.rect) + + def move(self, position): + self.rect = self.surface.get_rect(topleft=(position, self.ypos)) + +class NameInput(): + def __init__(self, screen): + self.screen = screen + ### + ### move the ref to the current player and the cursor position to a global variable that isn't reset by the main game loop. + ### + global PLAYER_NAME + global CURSOR_POSITION + self.letterOneText = Text(FONT, 50, PLAYER_NAME[0], WHITE, 625, 1410) + self.letterTwoText = Text(FONT, 50, PLAYER_NAME[1], WHITE, 675, 1410) + self.letterThreeText = Text(FONT, 50, PLAYER_NAME[2], WHITE, 725, 1410) + + self.letterOneText.draw(screen) + self.letterTwoText.draw(screen) + self.letterThreeText.draw(screen) + + if CURSOR_POSITION == 0: + self.underline = Text(FONT, 50, '_', WHITE, 625, 1430) + self.underline.draw(self.screen) + if CURSOR_POSITION == 1: + self.underline = Text(FONT, 50, '_', WHITE, 675, 1430) + self.underline.draw(self.screen) + if CURSOR_POSITION == 2: + self.underline = Text(FONT, 50, '_', WHITE, 725, 1430) + self.underline.draw(self.screen) + + def handle_input(self, button): + global CURSOR_LETTER + global CURSOR_POSITION + global PLAYER_NAME + alph = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] + if button == button_keys['right_arrow']: + if CURSOR_POSITION < 2: + CURSOR_POSITION += 1 + else: + CURSOR_POSITION = 0 + CURSOR_LETTER = alph.index(PLAYER_NAME[CURSOR_POSITION]) + if button == button_keys['left_arrow']: + if CURSOR_POSITION > 0: + CURSOR_POSITION -= 1 + else: + CURSOR_POSITION = 2 + CURSOR_LETTER = alph.index(PLAYER_NAME[CURSOR_POSITION]) + if button == button_keys['down_arrow']: + if CURSOR_LETTER >= 0: + CURSOR_LETTER -= 1 + else: + CURSOR_LETTER = 25 + PLAYER_NAME[CURSOR_POSITION] = alph[CURSOR_LETTER] + if button == button_keys['up_arrow']: + if CURSOR_LETTER < 27: + CURSOR_LETTER += 1 + else: + CURSOR_LETTER = 0 + + if CURSOR_POSITION == 0: + self.underline.move(625) + if CURSOR_POSITION == 1: + self.underline.move(675) + if CURSOR_POSITION == 2: + self.underline.move(725) + + class SpaceInvaders(object): @@ -341,24 +448,31 @@ def __init__(self): self.gameOver = False # Counter for enemy starting position (increased each new round) self.enemyPosition = ENEMY_DEFAULT_POSITION - self.titleText = Text(FONT, 50, 'Space Invaders', WHITE, 164, 155) - self.titleText2 = Text(FONT, 25, 'Press any key to continue', WHITE, - 201, 225) - self.gameOverText = Text(FONT, 50, 'Game Over', WHITE, 250, 270) - self.nextRoundText = Text(FONT, 50, 'Next Round', WHITE, 240, 270) - self.enemy1Text = Text(FONT, 25, ' = 10 pts', GREEN, 368, 270) - self.enemy2Text = Text(FONT, 25, ' = 20 pts', BLUE, 368, 320) - self.enemy3Text = Text(FONT, 25, ' = 30 pts', PURPLE, 368, 370) - self.enemy4Text = Text(FONT, 25, ' = ?????', RED, 368, 420) - self.scoreText = Text(FONT, 20, 'Score', WHITE, 5, 5) - self.livesText = Text(FONT, 20, 'Lives ', WHITE, 640, 5) - - self.life1 = Life(715, 3) - self.life2 = Life(742, 3) - self.life3 = Life(769, 3) + self.titleText = Text(FONT, 65, 'Course Invaders', YELLOW, 380, 1000) + self.titleText2 = Text(FONT, 30, 'Collect as many registrations as you can while', WHITE, + 260, 1100) + self.titleText3 = Text(FONT, 30, 'avoiding the aliens\' cancellations', WHITE, + 380, 1140) + + self.gameOverText = Text(FONT, 50, 'Game Over', RED, 535, 1250) + self.finalScoreText = Text(FONT, 50, 'Registrations:', WHITE, 420, 1310) + self.nextRoundText = Text(FONT, 50, 'Next Round', WHITE, 240, 1250) + self.enemy1Text = Text(FONT, 25, '= 10 pts', GREEN, 680, 1250) + self.enemy2Text = Text(FONT, 25, '= 20 pts', BLUE, 680, 1300) + self.enemy3Text = Text(FONT, 25, '= 30 pts', PURPLE, 680, 1350) + self.enemy4Text = Text(FONT, 25, '= ?????', RED, 680, 1400) + self.scoreText = Text(FONT, 35, 'Registrations', WHITE, 250, 600) + self.livesText = Text(FONT, 35, 'Lives: ', WHITE, 940, 600) + + self.life1 = Life(1100, 600) + self.life2 = Life(1150, 600) + self.life3 = Life(1200, 600) self.livesGroup = sprite.Group(self.life1, self.life2, self.life3) def reset(self, score): + global ROUND + + ROUND += 1 self.player = Ship() self.playerGroup = sprite.Group(self.player) self.explosionsGroup = sprite.Group() @@ -370,7 +484,7 @@ def reset(self, score): self.allSprites = sprite.Group(self.player, self.enemies, self.livesGroup, self.mysteryShip) self.keys = key.get_pressed() - + self.buttons = self.initButtons() self.timer = time.get_ticks() self.noteTimer = time.get_ticks() self.shipTimer = time.get_ticks() @@ -379,12 +493,19 @@ def reset(self, score): self.makeNewShip = False self.shipAlive = True + def initButtons(self): + buttons = {} + for key in button_keys.keys(): + buttons[key] = False + return buttons + + def make_blockers(self, number): blockerGroup = sprite.Group() for row in range(4): for column in range(9): - blocker = Blocker(10, GREEN, row, column) - blocker.rect.x = 50 + (200 * number) + (column * blocker.width) + blocker = Blocker(10, YELLOW, row, column) + blocker.rect.x = 300 + (200 * number) + (column * blocker.width) blocker.rect.y = BLOCKERS_POSITION + (row * blocker.height) blockerGroup.add(blocker) return blockerGroup @@ -419,6 +540,17 @@ def play_main_music(self, currentTime): def should_exit(evt): # type: (pygame.event.EventType) -> bool return evt.type == QUIT or (evt.type == KEYUP and evt.key == K_ESCAPE) + + @staticmethod + def should_reset(evt): + # type: (pygame.event.EventType) -> bool + if evt.type == KEYUP: + return True + elif evt.type == JOYBUTTONUP: + if evt.button == button_keys['circle']: + return True + + def check_input(self): self.keys = key.get_pressed() @@ -427,9 +559,9 @@ def check_input(self): sys.exit() if e.type == KEYDOWN: if e.key == K_SPACE: - if len(self.bullets) == 0 and self.shipAlive: + if len(self.bullets) <= 15 and self.shipAlive: if self.score < 1000: - bullet = Bullet(self.player.rect.x + 23, + bullet = Bullet(self.player.rect.x + 75, self.player.rect.y + 5, -1, 15, 'laser', 'center') self.bullets.add(bullet) @@ -445,21 +577,55 @@ def check_input(self): self.bullets.add(leftbullet) self.bullets.add(rightbullet) self.allSprites.add(self.bullets) - self.sounds['shoot2'].play() + self.sounds['shoot2'].play() + if e.type == JOYBUTTONDOWN: + if e.button == button_keys['x']: + if len(self.bullets) <= 15 and self.shipAlive: + if self.score < 1000: + bullet = Bullet(self.player.rect.x + 75, + self.player.rect.y + 5, -1, + 15, 'laser', 'center') + self.bullets.add(bullet) + self.allSprites.add(self.bullets) + self.sounds['shoot'].play() + else: + leftbullet = Bullet(self.player.rect.x + 8, + self.player.rect.y + 5, -1, + 15, 'laser', 'left') + rightbullet = Bullet(self.player.rect.x + 38, + self.player.rect.y + 5, -1, + 15, 'laser', 'right') + self.bullets.add(leftbullet) + self.bullets.add(rightbullet) + self.allSprites.add(self.bullets) + self.sounds['shoot2'].play() + else: + for btnKey in button_keys.keys(): + if e.button == button_keys[btnKey]: + self.buttons[btnKey] = True + if e.type == JOYBUTTONUP: + if e.button == button_keys['x']: + 1 + 1 + #do nothing + else: + for btnKey in button_keys.keys(): + if e.button == button_keys[btnKey]: + self.buttons[btnKey] = False + def make_enemies(self): enemies = EnemiesGroup(10, 5) for row in range(5): for column in range(10): enemy = Enemy(row, column) - enemy.rect.x = 157 + (column * 50) + enemy.rect.x = 300 + (column * 80) enemy.rect.y = self.enemyPosition + (row * 45) enemies.add(enemy) self.enemies = enemies def make_enemies_shoot(self): - if (time.get_ticks() - self.timer) > 700 and self.enemies: + if (time.get_ticks() - self.timer) > 500 and self.enemies: enemy = self.enemies.random_bottom() self.enemyBullets.add( Bullet(enemy.rect.x + 14, enemy.rect.y + 20, 1, 5, @@ -489,10 +655,12 @@ def create_main_menu(self): self.enemy3 = transform.scale(self.enemy3, (40, 40)) self.enemy4 = IMAGES['mystery'] self.enemy4 = transform.scale(self.enemy4, (80, 40)) - self.screen.blit(self.enemy1, (318, 270)) - self.screen.blit(self.enemy2, (318, 320)) - self.screen.blit(self.enemy3, (318, 370)) - self.screen.blit(self.enemy4, (299, 420)) + self.screen.blit(self.enemy1, (600, 1250)) + self.screen.blit(self.enemy2, (600, 1300)) + self.screen.blit(self.enemy3, (600, 1350)) + self.screen.blit(self.enemy4, (575, 1400)) + self.startText = Text(FONT, 40, "Press X to start the game", WHITE, 375, 1600) + self.startText.draw(self.screen) def check_collisions(self): sprite.groupcollide(self.bullets, self.enemyBullets, True, True) @@ -531,9 +699,9 @@ def check_collisions(self): self.shipTimer = time.get_ticks() self.shipAlive = False - if self.enemies.bottom >= 540: + if self.enemies.bottom >= 1540: sprite.groupcollide(self.enemies, self.playerGroup, True, True) - if not self.player.alive() or self.enemies.bottom >= 600: + if not self.player.alive() or self.enemies.bottom >= 1600: self.gameOver = True self.startGame = False @@ -551,6 +719,8 @@ def create_new_ship(self, createShip, currentTime): self.shipAlive = True def create_game_over(self, currentTime): + global ROUND + ROUND = 0 self.screen.blit(self.background, (0, 0)) passed = currentTime - self.timer if passed < 750: @@ -561,28 +731,49 @@ def create_game_over(self, currentTime): self.gameOverText.draw(self.screen) elif 2250 < passed < 2750: self.screen.blit(self.background, (0, 0)) - elif passed > 3000: - self.mainScreen = True + elif 3000 < passed < 6750: + self.gameOverText.draw(self.screen) + self.finalScoreText2 = Text(FONT, 50, str(self.score), YELLOW, 950, 1310) + self.finalScoreText.draw(self.screen) + self.finalScoreText2.draw(self.screen) + elif passed > 7000: + self.finalScoreText.draw(self.screen) + self.finalScoreText2.draw(self.screen) + self.goBackText = Text(FONT, 50, "Press circle to reset the game", WHITE, 200, 1450) + self.goBackText.draw(self.screen) + + + # with open(os.path.join("leaderboard.json"), 'r+') as file: + # leaderboard = json.load(file) + + # input = NameInput(self.screen) for e in event.get(): if self.should_exit(e): sys.exit() - + elif self.should_reset(e) and passed > 7000: + self.mainScreen = True + # elif e.type == JOYBUTTONUP: + # input.handle_input(e.button) + def main(self): + global ROUND while True: if self.mainScreen: self.screen.blit(self.background, (0, 0)) self.titleText.draw(self.screen) self.titleText2.draw(self.screen) + self.titleText3.draw(self.screen) self.enemy1Text.draw(self.screen) self.enemy2Text.draw(self.screen) self.enemy3Text.draw(self.screen) self.enemy4Text.draw(self.screen) self.create_main_menu() + for e in event.get(): if self.should_exit(e): sys.exit() - if e.type == KEYUP: + if e.type == KEYUP or e.type == JOYBUTTONUP: # Only create blockers on a new game, not a new round self.allBlockers = sprite.Group(self.make_blockers(0), self.make_blockers(1), @@ -592,14 +783,13 @@ def main(self): self.reset(0) self.startGame = True self.mainScreen = False - elif self.startGame: if not self.enemies and not self.explosionsGroup: currentTime = time.get_ticks() if currentTime - self.gameTimer < 3000: self.screen.blit(self.background, (0, 0)) - self.scoreText2 = Text(FONT, 20, str(self.score), - GREEN, 85, 5) + self.scoreText2 = Text(FONT, 35, str(self.score), + YELLOW, 600, 600) self.scoreText.draw(self.screen) self.scoreText2.draw(self.screen) self.nextRoundText.draw(self.screen) @@ -616,14 +806,14 @@ def main(self): self.play_main_music(currentTime) self.screen.blit(self.background, (0, 0)) self.allBlockers.update(self.screen) - self.scoreText2 = Text(FONT, 20, str(self.score), GREEN, - 85, 5) + self.scoreText2 = Text(FONT, 35, str(self.score), YELLOW, + 600, 600) self.scoreText.draw(self.screen) self.scoreText2.draw(self.screen) self.livesText.draw(self.screen) self.check_input() self.enemies.update(currentTime) - self.allSprites.update(self.keys, currentTime) + self.allSprites.update(self.keys, self.buttons, currentTime) self.explosionsGroup.update(currentTime) self.check_collisions() self.create_new_ship(self.makeNewShip, currentTime) diff --git a/spaceinvaders1080p.py b/spaceinvaders1080p.py new file mode 100644 index 0000000..8fac698 --- /dev/null +++ b/spaceinvaders1080p.py @@ -0,0 +1,834 @@ +#!/usr/bin/env python + +# Space Invaders +# Created by Lee Robinson + +from pygame import * +import sys +import os +import json +from os.path import abspath, dirname +from random import choice + +BASE_PATH = abspath(dirname(__file__)) +FONT_PATH = BASE_PATH + '/fonts/' +IMAGE_PATH = BASE_PATH + '/images/' +SOUND_PATH = BASE_PATH + '/sounds/' + +# Colors (R, G, B) +WHITE = (255, 255, 255) +GREEN = (78, 255, 87) +YELLOW = (255, 209, 0) +BLUE = (80, 255, 239) +PURPLE = (203, 0, 255) +RED = (237, 28, 36) + + +SCREEN = display.set_mode((0,0)) +FONT = FONT_PATH + 'space_invaders.ttf' +IMG_NAMES = ['ship', 'mystery', + 'enemy1_1', 'enemy1_2', + 'enemy2_1', 'enemy2_2', + 'enemy3_1', 'enemy3_2', + 'explosionblue', 'explosiongreen', 'explosionpurple', + 'laser', 'enemylaser'] +IMAGES = {name: image.load(IMAGE_PATH + '{}.png'.format(name)).convert_alpha() + for name in IMG_NAMES} + +PLAYER_NAME = ['A', 'A', 'A'] +CURSOR_POSITION = 0 +CURSOR_LETTER = 0 +ROUND = 1 + +BLOCKERS_POSITION = 1450 +ENEMY_DEFAULT_POSITION = 750 # Initial value for a new game +ENEMY_MOVE_DOWN = 35 + +with open(os.path.join("controller-keys.json"), 'r+') as file: + button_keys = json.load(file) +# 0: Left analog horizonal, 1: Left Analog Vertical, 2: Right Analog Horizontal +# 3: Right Analog Vertical 4: Left Trigger, 5: Right Trigger +analog_keys = {0:0, 1:0, 2:0, 3:0, 4:-1, 5: -1 } + +joystick.init() +joysticks = [] +for i in range(joystick.get_count()): + joysticks.append(joystick.Joystick(i)) +for joystick in joysticks: + joystick.init() + +class Ship(sprite.Sprite): + def __init__(self): + sprite.Sprite.__init__(self) + self.image = IMAGES['ship'] + self.rect = self.image.get_rect(topleft=(375, 1540)) + self.speed = 8 + + def update(self, keys, buttons, *args): + if keys[K_LEFT] and self.rect.x > 100: + self.rect.x -= self.speed + if keys[K_RIGHT] and self.rect.x < 900: + self.rect.x += self.speed + if buttons['left_arrow'] and self.rect.x > 100: + self.rect.x -= self.speed + if buttons['right_arrow'] and self.rect.x < 900: + self.rect.x += self.speed + game.screen.blit(self.image, self.rect) + + +class Bullet(sprite.Sprite): + def __init__(self, xpos, ypos, direction, speed, filename, side): + sprite.Sprite.__init__(self) + self.image = IMAGES[filename] + self.rect = self.image.get_rect(topleft=(xpos, ypos)) + self.speed = speed + self.direction = direction + self.side = side + self.filename = filename + + def update(self, keys, *args): + game.screen.blit(self.image, self.rect) + self.rect.y += self.speed * self.direction + if self.rect.y < 700 or self.rect.y > 1600: + self.kill() + +class Leaderboard(): + def __init__(self): + self.total = 0 + self.leaderboard + + def incrementScore(self): + self.total += 1 + + def storeHighScore(self, name): + leaderboard + +class Enemy(sprite.Sprite): + def __init__(self, row, column): + sprite.Sprite.__init__(self) + self.row = row + self.column = column + self.images = [] + self.load_images() + self.index = 0 + self.image = self.images[self.index] + self.rect = self.image.get_rect() + + def toggle_image(self): + self.index += 1 + if self.index >= len(self.images): + self.index = 0 + self.image = self.images[self.index] + + def update(self, *args): + game.screen.blit(self.image, self.rect) + + def load_images(self): + images = {0: ['1_2', '1_1'], + 1: ['2_2', '2_1'], + 2: ['2_2', '2_1'], + 3: ['3_1', '3_2'], + 4: ['3_1', '3_2'], + } + img1, img2 = (IMAGES['enemy{}'.format(img_num)] for img_num in + images[self.row]) + self.images.append(transform.scale(img1, (40, 35))) + self.images.append(transform.scale(img2, (40, 35))) + + +class EnemiesGroup(sprite.Group): + def __init__(self, columns, rows): + global ROUND + sprite.Group.__init__(self) + self.enemies = [[None] * columns for _ in range(rows)] + self.columns = columns + self.rows = rows + self.leftAddMove = 0 + self.rightAddMove = 0 + self.moveTime = 85 - (10 * ROUND) + self.direction = 1 + self.rightMoves = 30 + self.leftMoves = 30 + self.moveNumber = 15 + self.timer = time.get_ticks() + self.bottom = game.enemyPosition + ((rows - 1) * 45) + 35 + self._aliveColumns = list(range(columns)) + self._leftAliveColumn = 0 + self._rightAliveColumn = columns - 1 + self.multiplier = 0.5 + ROUND / 2 + + def update(self, current_time): + if current_time - self.timer > self.moveTime: + if self.direction == 1: + max_move = self.rightMoves + self.rightAddMove + else: + max_move = self.leftMoves + self.leftAddMove + + if self.moveNumber >= max_move: + self.leftMoves = 30 + self.rightAddMove + self.rightMoves = 30 + self.leftAddMove + self.direction *= -1 + self.moveNumber = 0 + self.bottom = 0 + for enemy in self: + enemy.rect.y += ENEMY_MOVE_DOWN + enemy.toggle_image() + if self.bottom < enemy.rect.y + 35: + self.bottom = enemy.rect.y + 35 + else: + velocity = 15 if self.direction == 1 else -15 + for enemy in self: + enemy.rect.x += velocity + enemy.toggle_image() + self.moveNumber += 1 + + + self.timer += self.moveTime + + def add_internal(self, *sprites): + super(EnemiesGroup, self).add_internal(*sprites) + for s in sprites: + self.enemies[s.row][s.column] = s + + def remove_internal(self, *sprites): + super(EnemiesGroup, self).remove_internal(*sprites) + for s in sprites: + self.kill(s) + self.update_speed() + + def is_column_dead(self, column): + return not any(self.enemies[row][column] + for row in range(self.rows)) + + def random_bottom(self): + col = choice(self._aliveColumns) + col_enemies = (self.enemies[row - 1][col] + for row in range(self.rows, 0, -1)) + return next((en for en in col_enemies if en is not None), None) + + def update_speed(self): + if len(self) == 1: + self.moveTime -= 10 + elif len(self) <= 10: + self.moveTime -= 5 + + def kill(self, enemy): + self.enemies[enemy.row][enemy.column] = None + is_column_dead = self.is_column_dead(enemy.column) + if is_column_dead: + self._aliveColumns.remove(enemy.column) + + if enemy.column == self._rightAliveColumn: + while self._rightAliveColumn > 0 and is_column_dead: + self._rightAliveColumn -= 1 + self.rightAddMove += 5 + is_column_dead = self.is_column_dead(self._rightAliveColumn) + + elif enemy.column == self._leftAliveColumn: + while self._leftAliveColumn < self.columns and is_column_dead: + self._leftAliveColumn += 1 + self.leftAddMove += 5 + is_column_dead = self.is_column_dead(self._leftAliveColumn) + + +class Blocker(sprite.Sprite): + def __init__(self, size, color, row, column): + sprite.Sprite.__init__(self) + self.height = size + self.width = size + self.color = color + self.image = Surface((self.width, self.height)) + self.image.fill(self.color) + self.rect = self.image.get_rect() + self.row = row + self.column = column + + def update(self, keys, *args): + game.screen.blit(self.image, self.rect) + + +class Mystery(sprite.Sprite): + def __init__(self): + sprite.Sprite.__init__(self) + self.image = IMAGES['mystery'] + self.image = transform.scale(self.image, (75, 35)) + self.rect = self.image.get_rect(topleft=(-80, 800)) + self.row = 5 + self.moveTime = 25000 + self.direction = 1 + self.timer = time.get_ticks() + self.mysteryEntered = mixer.Sound(SOUND_PATH + 'mysteryentered.wav') + self.mysteryEntered.set_volume(0.3) + self.playSound = True + + def update(self, keys, _buttons, currentTime, *args): + resetTimer = False + passed = currentTime - self.timer + if passed > self.moveTime: + if (self.rect.x < 0 or self.rect.x > 800) and self.playSound: + self.mysteryEntered.play() + self.playSound = False + if self.rect.x < 840 and self.direction == 1: + self.mysteryEntered.fadeout(4000) + self.rect.x += 2 + game.screen.blit(self.image, self.rect) + if self.rect.x > -100 and self.direction == -1: + self.mysteryEntered.fadeout(4000) + self.rect.x -= 2 + game.screen.blit(self.image, self.rect) + + if self.rect.x > 830: + self.playSound = True + self.direction = -1 + resetTimer = True + if self.rect.x < -90: + self.playSound = True + self.direction = 1 + resetTimer = True + if passed > self.moveTime and resetTimer: + self.timer = currentTime + + +class EnemyExplosion(sprite.Sprite): + def __init__(self, enemy, *groups): + super(EnemyExplosion, self).__init__(*groups) + self.image = transform.scale(self.get_image(enemy.row), (40, 35)) + self.image2 = transform.scale(self.get_image(enemy.row), (50, 45)) + self.rect = self.image.get_rect(topleft=(enemy.rect.x, enemy.rect.y)) + self.timer = time.get_ticks() + + @staticmethod + def get_image(row): + img_colors = ['purple', 'blue', 'blue', 'green', 'green'] + return IMAGES['explosion{}'.format(img_colors[row])] + + def update(self, current_time, *args): + passed = current_time - self.timer + if passed <= 100: + game.screen.blit(self.image, self.rect) + elif passed <= 200: + game.screen.blit(self.image2, (self.rect.x - 6, self.rect.y - 6)) + elif 400 < passed: + self.kill() + + +class MysteryExplosion(sprite.Sprite): + def __init__(self, mystery, score, *groups): + super(MysteryExplosion, self).__init__(*groups) + self.text = Text(FONT, 20, str(score), WHITE, + mystery.rect.x + 20, mystery.rect.y + 6) + self.timer = time.get_ticks() + + def update(self, current_time, *args): + passed = current_time - self.timer + if passed <= 200 or 400 < passed <= 600: + self.text.draw(game.screen) + elif 600 < passed: + self.kill() + + +class ShipExplosion(sprite.Sprite): + def __init__(self, ship, *groups): + super(ShipExplosion, self).__init__(*groups) + self.image = IMAGES['ship'] + self.rect = self.image.get_rect(topleft=(ship.rect.x, ship.rect.y)) + self.timer = time.get_ticks() + + def update(self, current_time, *args): + passed = current_time - self.timer + if 300 < passed <= 600: + game.screen.blit(self.image, self.rect) + elif 900 < passed: + self.kill() + + +class Life(sprite.Sprite): + def __init__(self, xpos, ypos): + sprite.Sprite.__init__(self) + self.image = IMAGES['ship'] + self.image = transform.scale(self.image, (40, 40)) + self.rect = self.image.get_rect(topleft=(xpos, ypos)) + + def update(self, *args): + game.screen.blit(self.image, self.rect) + + +class Text(object): + def __init__(self, textFont, size, message, color, xpos, ypos): + self.message = message + self.xpos = xpos + self.ypos = ypos + self.font = font.Font(textFont, size) + self.surface = self.font.render(message, True, color) + self.rect = self.surface.get_rect(topleft=(self.xpos, ypos)) + + def draw(self, surface): + surface.blit(self.surface, self.rect) + + def move(self, position): + self.rect = self.surface.get_rect(topleft=(position, self.ypos)) + +class NameInput(): + def __init__(self, screen): + self.screen = screen + ### + ### move the ref to the current player and the cursor position to a global variable that isn't reset by the main game loop. + ### + global PLAYER_NAME + global CURSOR_POSITION + self.letterOneText = Text(FONT, 50, PLAYER_NAME[0], WHITE, 625, 1410) + self.letterTwoText = Text(FONT, 50, PLAYER_NAME[1], WHITE, 675, 1410) + self.letterThreeText = Text(FONT, 50, PLAYER_NAME[2], WHITE, 725, 1410) + + self.letterOneText.draw(screen) + self.letterTwoText.draw(screen) + self.letterThreeText.draw(screen) + + if CURSOR_POSITION == 0: + self.underline = Text(FONT, 50, '_', WHITE, 625, 1430) + self.underline.draw(self.screen) + if CURSOR_POSITION == 1: + self.underline = Text(FONT, 50, '_', WHITE, 675, 1430) + self.underline.draw(self.screen) + if CURSOR_POSITION == 2: + self.underline = Text(FONT, 50, '_', WHITE, 725, 1430) + self.underline.draw(self.screen) + + def handle_input(self, button): + global CURSOR_LETTER + global CURSOR_POSITION + global PLAYER_NAME + alph = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] + if button == button_keys['right_arrow']: + if CURSOR_POSITION < 2: + CURSOR_POSITION += 1 + else: + CURSOR_POSITION = 0 + CURSOR_LETTER = alph.index(PLAYER_NAME[CURSOR_POSITION]) + if button == button_keys['left_arrow']: + if CURSOR_POSITION > 0: + CURSOR_POSITION -= 1 + else: + CURSOR_POSITION = 2 + CURSOR_LETTER = alph.index(PLAYER_NAME[CURSOR_POSITION]) + if button == button_keys['down_arrow']: + if CURSOR_LETTER >= 0: + CURSOR_LETTER -= 1 + else: + CURSOR_LETTER = 25 + PLAYER_NAME[CURSOR_POSITION] = alph[CURSOR_LETTER] + if button == button_keys['up_arrow']: + if CURSOR_LETTER < 27: + CURSOR_LETTER += 1 + else: + CURSOR_LETTER = 0 + + if CURSOR_POSITION == 0: + self.underline.move(625) + if CURSOR_POSITION == 1: + self.underline.move(675) + if CURSOR_POSITION == 2: + self.underline.move(725) + + + + +class SpaceInvaders(object): + def __init__(self): + # It seems, in Linux buffersize=512 is not enough, use 4096 to prevent: + # ALSA lib pcm.c:7963:(snd_pcm_recover) underrun occurred + mixer.pre_init(44100, -16, 1, 4096) + init() + self.clock = time.Clock() + self.caption = display.set_caption('Space Invaders') + self.screen = SCREEN + self.background = image.load(IMAGE_PATH + 'background.jpg').convert() + self.startGame = False + self.mainScreen = True + self.gameOver = False + # Counter for enemy starting position (increased each new round) + self.enemyPosition = ENEMY_DEFAULT_POSITION + self.titleText = Text(FONT, 65, 'Course Invaders', YELLOW, 180, 400) + self.titleText2 = Text(FONT, 30, 'Collect as many registrations as you can while', WHITE, + 60, 500) + self.titleText3 = Text(FONT, 30, 'avoiding the aliens\' cancellations', WHITE, + 180, 550) + + self.gameOverText = Text(FONT, 50, 'Game Over', RED, 325, 500) + self.finalScoreText = Text(FONT, 50, 'Registrations:', WHITE, 150, 700) + self.nextRoundText = Text(FONT, 50, 'Next Round', WHITE, 325, 950) + self.enemy1Text = Text(FONT, 25, '= 10 pts', GREEN, 450, 750) + self.enemy2Text = Text(FONT, 25, '= 20 pts', BLUE, 450, 800) + self.enemy3Text = Text(FONT, 25, '= 30 pts', PURPLE, 450, 850) + self.enemy4Text = Text(FONT, 25, '= ?????', RED, 450, 900) + self.scoreText = Text(FONT, 35, 'Registrations', WHITE, 100, 600) + self.livesText = Text(FONT, 35, 'Lives: ', WHITE, 650, 600) + + self.life1 = Life(850, 600) + self.life2 = Life(900, 600) + self.life3 = Life(950, 600) + self.livesGroup = sprite.Group(self.life1, self.life2, self.life3) + + def reset(self, score): + global ROUND + + ROUND += 1 + self.player = Ship() + self.playerGroup = sprite.Group(self.player) + self.explosionsGroup = sprite.Group() + self.bullets = sprite.Group() + self.mysteryShip = Mystery() + self.mysteryGroup = sprite.Group(self.mysteryShip) + self.enemyBullets = sprite.Group() + self.make_enemies() + self.allSprites = sprite.Group(self.player, self.enemies, + self.livesGroup, self.mysteryShip) + self.keys = key.get_pressed() + self.buttons = self.initButtons() + self.timer = time.get_ticks() + self.noteTimer = time.get_ticks() + self.shipTimer = time.get_ticks() + self.score = score + self.create_audio() + self.makeNewShip = False + self.shipAlive = True + + def initButtons(self): + buttons = {} + for key in button_keys.keys(): + buttons[key] = False + return buttons + + + def make_blockers(self, number): + blockerGroup = sprite.Group() + for row in range(4): + for column in range(9): + blocker = Blocker(10, YELLOW, row, column) + blocker.rect.x = 200 + (200 * number) + (column * blocker.width) + blocker.rect.y = BLOCKERS_POSITION + (row * blocker.height) + blockerGroup.add(blocker) + return blockerGroup + + def create_audio(self): + self.sounds = {} + for sound_name in ['shoot', 'shoot2', 'invaderkilled', 'mysterykilled', + 'shipexplosion']: + self.sounds[sound_name] = mixer.Sound( + SOUND_PATH + '{}.wav'.format(sound_name)) + self.sounds[sound_name].set_volume(0.2) + + self.musicNotes = [mixer.Sound(SOUND_PATH + '{}.wav'.format(i)) for i + in range(4)] + for sound in self.musicNotes: + sound.set_volume(0.5) + + self.noteIndex = 0 + + def play_main_music(self, currentTime): + if currentTime - self.noteTimer > self.enemies.moveTime: + self.note = self.musicNotes[self.noteIndex] + if self.noteIndex < 3: + self.noteIndex += 1 + else: + self.noteIndex = 0 + + self.note.play() + self.noteTimer += self.enemies.moveTime + + @staticmethod + def should_exit(evt): + # type: (pygame.event.EventType) -> bool + return evt.type == QUIT or (evt.type == KEYUP and evt.key == K_ESCAPE) + + @staticmethod + def should_reset(evt): + # type: (pygame.event.EventType) -> bool + if evt.type == KEYUP: + return True + elif evt.type == JOYBUTTONUP: + if evt.button == button_keys['circle']: + return True + + + + def check_input(self): + self.keys = key.get_pressed() + for e in event.get(): + if self.should_exit(e): + sys.exit() + if e.type == KEYDOWN: + if e.key == K_SPACE: + if len(self.bullets) <= 15 and self.shipAlive: + if self.score < 1000: + bullet = Bullet(self.player.rect.x + 75, + self.player.rect.y + 5, -1, + 15, 'laser', 'center') + self.bullets.add(bullet) + self.allSprites.add(self.bullets) + self.sounds['shoot'].play() + else: + leftbullet = Bullet(self.player.rect.x + 8, + self.player.rect.y + 5, -1, + 15, 'laser', 'left') + rightbullet = Bullet(self.player.rect.x + 38, + self.player.rect.y + 5, -1, + 15, 'laser', 'right') + self.bullets.add(leftbullet) + self.bullets.add(rightbullet) + self.allSprites.add(self.bullets) + self.sounds['shoot2'].play() + if e.type == JOYBUTTONDOWN: + if e.button == button_keys['x']: + if len(self.bullets) <= 15 and self.shipAlive: + if self.score < 1000: + bullet = Bullet(self.player.rect.x + 75, + self.player.rect.y + 5, -1, + 15, 'laser', 'center') + self.bullets.add(bullet) + self.allSprites.add(self.bullets) + self.sounds['shoot'].play() + else: + leftbullet = Bullet(self.player.rect.x + 8, + self.player.rect.y + 5, -1, + 15, 'laser', 'left') + rightbullet = Bullet(self.player.rect.x + 38, + self.player.rect.y + 5, -1, + 15, 'laser', 'right') + self.bullets.add(leftbullet) + self.bullets.add(rightbullet) + self.allSprites.add(self.bullets) + self.sounds['shoot2'].play() + else: + for btnKey in button_keys.keys(): + if e.button == button_keys[btnKey]: + self.buttons[btnKey] = True + if e.type == JOYBUTTONUP: + if e.button == button_keys['x']: + 1 + 1 + #do nothing + else: + for btnKey in button_keys.keys(): + if e.button == button_keys[btnKey]: + self.buttons[btnKey] = False + + + def make_enemies(self): + enemies = EnemiesGroup(8, 5) + for row in range(5): + for column in range(8): + enemy = Enemy(row, column) + enemy.rect.x = 250 + (column * 80) + enemy.rect.y = self.enemyPosition + (row * 45) + enemies.add(enemy) + + self.enemies = enemies + + def make_enemies_shoot(self): + if (time.get_ticks() - self.timer) > 500 and self.enemies: + enemy = self.enemies.random_bottom() + self.enemyBullets.add( + Bullet(enemy.rect.x + 14, enemy.rect.y + 20, 1, 5, + 'enemylaser', 'center')) + self.allSprites.add(self.enemyBullets) + self.timer = time.get_ticks() + + def calculate_score(self, row): + scores = {0: 30, + 1: 20, + 2: 20, + 3: 10, + 4: 10, + 5: choice([50, 100, 150, 300]) + } + + score = scores[row] + self.score += score + return score + + def create_main_menu(self): + self.enemy1 = IMAGES['enemy3_1'] + self.enemy1 = transform.scale(self.enemy1, (40, 40)) + self.enemy2 = IMAGES['enemy2_2'] + self.enemy2 = transform.scale(self.enemy2, (40, 40)) + self.enemy3 = IMAGES['enemy1_2'] + self.enemy3 = transform.scale(self.enemy3, (40, 40)) + self.enemy4 = IMAGES['mystery'] + self.enemy4 = transform.scale(self.enemy4, (80, 40)) + self.screen.blit(self.enemy1, (400, 750)) + self.screen.blit(self.enemy2, (400, 800)) + self.screen.blit(self.enemy3, (400, 850)) + self.screen.blit(self.enemy4, (375, 900)) + self.startText = Text(FONT, 40, "Press X to start", WHITE, 275, 1100) + self.startText.draw(self.screen) + + def check_collisions(self): + sprite.groupcollide(self.bullets, self.enemyBullets, True, True) + + for enemy in sprite.groupcollide(self.enemies, self.bullets, + True, True).keys(): + self.sounds['invaderkilled'].play() + self.calculate_score(enemy.row) + EnemyExplosion(enemy, self.explosionsGroup) + self.gameTimer = time.get_ticks() + + for mystery in sprite.groupcollide(self.mysteryGroup, self.bullets, + True, True).keys(): + mystery.mysteryEntered.stop() + self.sounds['mysterykilled'].play() + score = self.calculate_score(mystery.row) + MysteryExplosion(mystery, score, self.explosionsGroup) + newShip = Mystery() + self.allSprites.add(newShip) + self.mysteryGroup.add(newShip) + + for player in sprite.groupcollide(self.playerGroup, self.enemyBullets, + True, True).keys(): + if self.life3.alive(): + self.life3.kill() + elif self.life2.alive(): + self.life2.kill() + elif self.life1.alive(): + self.life1.kill() + else: + self.gameOver = True + self.startGame = False + self.sounds['shipexplosion'].play() + ShipExplosion(player, self.explosionsGroup) + self.makeNewShip = True + self.shipTimer = time.get_ticks() + self.shipAlive = False + + if self.enemies.bottom >= 1540: + sprite.groupcollide(self.enemies, self.playerGroup, True, True) + if not self.player.alive() or self.enemies.bottom >= 1600: + self.gameOver = True + self.startGame = False + + sprite.groupcollide(self.bullets, self.allBlockers, True, True) + sprite.groupcollide(self.enemyBullets, self.allBlockers, True, True) + if self.enemies.bottom >= BLOCKERS_POSITION: + sprite.groupcollide(self.enemies, self.allBlockers, False, True) + + def create_new_ship(self, createShip, currentTime): + if createShip and (currentTime - self.shipTimer > 900): + self.player = Ship() + self.allSprites.add(self.player) + self.playerGroup.add(self.player) + self.makeNewShip = False + self.shipAlive = True + + def create_game_over(self, currentTime): + global ROUND + ROUND = 0 + self.screen.blit(self.background, (0, 0)) + passed = currentTime - self.timer + if passed < 750: + self.gameOverText.draw(self.screen) + elif 750 < passed < 1500: + self.screen.blit(self.background, (0, 0)) + elif 1500 < passed < 2250: + self.gameOverText.draw(self.screen) + elif 2250 < passed < 2750: + self.screen.blit(self.background, (0, 0)) + elif 3000 < passed < 6750: + self.gameOverText.draw(self.screen) + self.finalScoreText2 = Text(FONT, 50, str(self.score), YELLOW, 550, 810) + self.finalScoreText.draw(self.screen) + self.finalScoreText2.draw(self.screen) + elif passed > 7000: + self.finalScoreText.draw(self.screen) + self.finalScoreText2.draw(self.screen) + self.goBackText = Text(FONT, 50, "Press circle to play again", WHITE, 100, 1000) + self.goBackText.draw(self.screen) + + + + # with open(os.path.join("leaderboard.json"), 'r+') as file: + # leaderboard = json.load(file) + + # input = NameInput(self.screen) + for e in event.get(): + if self.should_exit(e): + sys.exit() + elif self.should_reset(e) and passed > 7000: + self.mainScreen = True + # elif e.type == JOYBUTTONUP: + # input.handle_input(e.button) + + def main(self): + global ROUND + while True: + if self.mainScreen: + self.screen.blit(self.background, (0, 0)) + self.titleText.draw(self.screen) + self.titleText2.draw(self.screen) + self.titleText3.draw(self.screen) + self.enemy1Text.draw(self.screen) + self.enemy2Text.draw(self.screen) + self.enemy3Text.draw(self.screen) + self.enemy4Text.draw(self.screen) + self.create_main_menu() + + for e in event.get(): + if self.should_exit(e): + sys.exit() + if e.type == KEYUP or e.type == JOYBUTTONUP: + # Only create blockers on a new game, not a new round + self.allBlockers = sprite.Group(self.make_blockers(0), + self.make_blockers(1), + self.make_blockers(2), + self.make_blockers(3)) + self.livesGroup.add(self.life1, self.life2, self.life3) + self.reset(0) + self.startGame = True + self.mainScreen = False + elif self.startGame: + if not self.enemies and not self.explosionsGroup: + currentTime = time.get_ticks() + if currentTime - self.gameTimer < 3000: + self.screen.blit(self.background, (0, 0)) + self.scoreText2 = Text(FONT, 35, str(self.score), + YELLOW, 450, 600) + self.scoreText.draw(self.screen) + self.scoreText2.draw(self.screen) + self.nextRoundText.draw(self.screen) + self.livesText.draw(self.screen) + self.livesGroup.update() + self.check_input() + if currentTime - self.gameTimer > 3000: + # Move enemies closer to bottom + self.enemyPosition += ENEMY_MOVE_DOWN + self.reset(self.score) + self.gameTimer += 3000 + else: + currentTime = time.get_ticks() + self.play_main_music(currentTime) + self.screen.blit(self.background, (0, 0)) + self.allBlockers.update(self.screen) + self.scoreText2 = Text(FONT, 35, str(self.score), YELLOW, + 450, 600) + self.scoreText.draw(self.screen) + self.scoreText2.draw(self.screen) + self.livesText.draw(self.screen) + self.check_input() + self.enemies.update(currentTime) + self.allSprites.update(self.keys, self.buttons, currentTime) + self.explosionsGroup.update(currentTime) + self.check_collisions() + self.create_new_ship(self.makeNewShip, currentTime) + self.make_enemies_shoot() + + elif self.gameOver: + currentTime = time.get_ticks() + # Reset enemy starting position + self.enemyPosition = ENEMY_DEFAULT_POSITION + self.create_game_over(currentTime) + + display.update() + self.clock.tick(60) + + +if __name__ == '__main__': + game = SpaceInvaders() + game.main()