import pygame from pygame import mixer import random import math from bisect import insort import button import os.path pygame.init() screen = pygame.display.set_mode((1000, 700)) pygame.display.set_caption("Space Invaders") icon = pygame.image.load("ICON.png") pygame.display.set_icon(icon) space = pygame.image.load('SPACE.jpg') hangar = pygame.image.load('HANGAR.jpg') mixer.music.load("music/background.mp3") mixer.music.play(-1) font = pygame.font.Font("KodeMono-Medium.ttf", 32) smaller_font = pygame.font.Font("KodeMono-Medium.ttf", 24) over_font = pygame.font.Font("KodeMono-Medium.ttf", 96) TEXT_COL = (255, 255, 255) SCORE_FILE_NAME = "score.scr" new_game_img = pygame.image.load("new_game.png") difficulty_img = pygame.image.load("difficulty.png") best_score_img = pygame.image.load("best_score.png") back_img = pygame.image.load("back.png") difficulty_easy_img = pygame.image.load("difficulty_easy.png") difficulty_medium_img = pygame.image.load("difficulty_medium.png") difficulty_hard_img = pygame.image.load("difficulty_hard.png") difficulty_insane_img = pygame.image.load("difficulty_insane.png") new_game_button = button.Button(400, 320, new_game_img, 1) difficulty_button = button.Button(400, 410, difficulty_img, 1) best_score_button = button.Button(400, 500, best_score_img, 1) back_button = button.Button(400, 580, back_img, 1) difficulty_buttons = [ button.Button(290, 150, difficulty_easy_img, 1), button.Button(510, 150, difficulty_medium_img, 1), button.Button(290, 250, difficulty_hard_img, 1), button.Button(510, 250, difficulty_insane_img, 1) ] scene = "menu" game_paused = False game_lost = False # difficulty difficulty = 0 #starts the game all over again def reset_enemies(difficulty): # create enemies and thier parameters enemies = [] num_of_enemies = 8 + difficulty*2 for i in range(num_of_enemies): #tempX is made to randomly choose starting direction tempX = 0.4 if random.randint(0, 1): tempX *= -1 # if diificulty if higher than 1, make enemies also move by Y axis if difficulty > 1: tempY = random.randint(0, 40*difficulty)/1000 else: tempY = 0 enemies.append({ "X": random.randint(0, 930), "Y": random.randint(0, 30), "X_change": tempX, "Y_change": tempY }) return enemies # draw some text with given parameters def draw_text(text, font, text_col, x, y): text = font.render(text, True, text_col) screen.blit(text, (x, y)) # print best score def print_best_score(best_score): draw_text("Best score", font, TEXT_COL, 380, 150) for i, item in enumerate(best_score[::-1]): text = str(i+1)+". " + str(item) draw_text(text, smaller_font, TEXT_COL, 360, 220+i*40) #check if enemy collides with the bullet def is_collision(enemyX, enemyY, bulletX, bulletY): distance = math.sqrt(math.pow(enemyX-bulletX, 2) + math.pow(enemyY-bulletY, 2)) if distance < 30: return True return False # game over def game_over_text(): over_text = over_font.render("GAME OVER", True, TEXT_COL) screen.blit(over_text, (180, 300)) def show_score(x, y): score = font.render("Score : "+ str(score_val), True, TEXT_COL) screen.blit(score, (x, y)) def shoot_bullet(x, y): global bullet_state bullet_state = "fire" screen.blit(bullet_image, (x + 17, y + 10)) def player(x, y): screen.blit(player_image, (x, y)) def enemy(x, y): screen.blit(enemy_image, (x, y)) def update_score_table(scores): if os.path.isfile(SCORE_FILE_NAME): with open(SCORE_FILE_NAME, "w") as f: f.write(" ".join(list(map(str, scores)))) else: with open(SCORE_FILE_NAME, "x") as f: f.write(" ".join(list(map(str, scores)))) def read_score_table(): if not os.path.isfile(SCORE_FILE_NAME): update_score_table([0, 0, 0, 0]) with open(SCORE_FILE_NAME) as f: return [int(score) for score in f.read().split()] def add_score(score): current = read_score_table() current.append(score) current.sort() updated = current[1:5] print(score, updated) update_score_table(updated) #scoreboard for each mode individually score_val = 0 textX = 10 textY = 10 #player data playerX = 450 playerY = 580 player_image = pygame.image.load("SPACESHIP.png") playerX_change = 0 #bullet data bullet_image = pygame.image.load("BULLET.png") bulletX = 0 bulletY = 560 bulletY_change = 20 bullet_state = "ready" #enemy data enemy_image = pygame.image.load("ENEMY.png") enemies = reset_enemies(difficulty) num_of_enemies = len(enemies) #Game loop running = True while running: # choose what scene is active match scene: # menu scenes case "menu": screen.blit(hangar, (0, 0)) # if any of buttons is pressed, change the scene if new_game_button.draw(screen): scene = "game" if difficulty_button.draw(screen): scene = "difficulty" if best_score_button.draw(screen): scene = "best_score" case "best_score": screen.blit(hangar, (0, 0)) print_best_score(read_score_table()) # if pressed, go back to menu if back_button.draw(screen): scene = "menu" case "difficulty": screen.blit(hangar, (0, 0)) draw_text("Choose the difficulty", font, TEXT_COL, 350, 50) # if any of buttons pressed, difficutly is assigned for i in range(0, len(difficulty_buttons)): if difficulty_buttons[i].draw(screen): difficulty = i scene = "menu" enemies = reset_enemies(difficulty) if back_button.draw(screen): scene = "menu" # game scene case "game": #background screen.blit(space, (0, 0)) #works only when the game is not paused if not game_paused: # spaceship (player) movement playerX += playerX_change if playerX <= 2: playerX = 2 elif playerX >= 928: playerX = 928 # enemy for i, enem in enumerate(enemies): #Game over when enemies reach the spaceship if enem["Y"] > 520: for j in range(num_of_enemies): enemies[j]["Y"] = 2000 game_over_text() add_score(score_val) score_val = 0 #if game is lost, print some text like wanna start again? press R to continue game_lost = True draw_text('Press "R" to return to menu', font, TEXT_COL, 270, 600) break # enemy movement enemies[i]["X"] += enemies[i]["X_change"] enemies[i]["Y"] += enemies[i]["Y_change"] if enemies[i]["X"] <= 2: enemies[i]["X_change"] = 0.4 enemies[i]["Y"] += 50 elif enemies[i]["X"] >= 928: enemies[i]["X_change"] = -0.4 enemies[i]["Y"] += 50 #Collision check collision = is_collision(enem["X"], enem["Y"], bulletX, bulletY) if collision: explosion_Sound = mixer.Sound("explosion.wav") explosion_Sound.play() bulletY = 560 bullet_state = "ready" score_val += 1 enemies[i]["X"] = random.randint(0, 930) enemies[i]["Y"] = random.randint(0, 30) enemy(enem["X"], enem["Y"]) #bullet movement if bulletY <= 0: bulletY = 560 bullet_state = "ready" if bullet_state == "fire": shoot_bullet(bulletX, bulletY) bulletY -= 2.5 # score, enemy and player update draw_text("Press TAB to pause", smaller_font, TEXT_COL, 750, 10) show_score(textX, textY) for i, enem in enumerate(enemies): enemy(enem["X"], enem["Y"]) player(playerX, playerY) else: #display menu match difficulty: case 0: temp = "easy" case 1: temp = "mid" case 2: temp = "hard" case 3: temp = "insane" print_best_score(read_score_table()) draw_text("Press TAB to resume", smaller_font, TEXT_COL, 350, 550) case _: screen.blit(space, (0, 0)) #event loop for event in pygame.event.get(): if scene == "game": # player movement with left and right arrows. When key is unpressed, stop the movement if event.type == pygame.KEYDOWN: if event.key == pygame.K_TAB: if game_paused: game_paused = False else: game_paused = True # if game is over, then you can restart it by pressing the R key if game_lost and event.key == pygame.K_r: scene = "menu" game_lost = False if event.key == pygame.K_LEFT: playerX_change = -1.2 if event.key == pygame.K_RIGHT: playerX_change = 1.2 if event.key == pygame.K_SPACE: if bullet_state == "ready": bullet_sound = mixer.Sound("Laser.wav") bullet_sound.play() bulletX = playerX shoot_bullet(bulletX, bulletY) # stop ship from moving if event.type == pygame.KEYUP: if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT: playerX_change = 0 #stop when event is quit if event.type == pygame.QUIT: running = False pygame.display.update()