spacegame/main.py

324 lines
10 KiB
Python

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()