Spaceinvader v1
BIN
pygame/space_invaders/source/assets/background.jpg
Normal file
|
After Width: | Height: | Size: 274 KiB |
BIN
pygame/space_invaders/source/assets/images/explosionblue.png
Normal file
|
After Width: | Height: | Size: 272 B |
BIN
pygame/space_invaders/source/assets/images/explosiongreen.png
Normal file
|
After Width: | Height: | Size: 287 B |
BIN
pygame/space_invaders/source/assets/images/explosionpurple.png
Normal file
|
After Width: | Height: | Size: 272 B |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 692 B |
|
After Width: | Height: | Size: 706 B |
|
After Width: | Height: | Size: 743 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 842 B |
BIN
pygame/space_invaders/source/assets/sprites/enemies/mystery.png
Normal file
|
After Width: | Height: | Size: 299 B |
|
After Width: | Height: | Size: 159 B |
|
After Width: | Height: | Size: 80 B |
BIN
pygame/space_invaders/source/assets/sprites/playership.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
pygame/space_invaders/source/fonts/space_invaders.ttf
Normal file
257
pygame/space_invaders/source/space_invaders.py
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
# Author - Kristiāns Francis Cagulis
|
||||||
|
# Date - 06.03.2022
|
||||||
|
# Title - Space invaders
|
||||||
|
# TODO: Add score system
|
||||||
|
# TODO: Add enemy movement in groups
|
||||||
|
|
||||||
|
import pygame
|
||||||
|
from random import randrange, choice
|
||||||
|
from os.path import abspath, dirname, join
|
||||||
|
|
||||||
|
WIDTH, HEIGHT = 800, 800
|
||||||
|
|
||||||
|
WINDOW = pygame.display.set_mode((WIDTH, HEIGHT))
|
||||||
|
pygame.display.set_caption("Space Invaders")
|
||||||
|
pygame.font.init()
|
||||||
|
|
||||||
|
# paths
|
||||||
|
BASE_PATH = abspath(dirname(__file__))
|
||||||
|
SPRITE_PATH = join(BASE_PATH, "assets", "sprites")
|
||||||
|
ENEMY_PATH = join(SPRITE_PATH, "enemies")
|
||||||
|
FONT = join(BASE_PATH, "fonts", "space_invaders.ttf")
|
||||||
|
|
||||||
|
# load sprites
|
||||||
|
SPACESHIP = pygame.image.load(join(SPRITE_PATH, "playership.png")) # player
|
||||||
|
PLAYER_MISSILE = pygame.image.load(join(SPRITE_PATH, "missiles", "playermissile.png")) # player missile
|
||||||
|
|
||||||
|
# enemies
|
||||||
|
ENEMY_1 = pygame.transform.scale(pygame.image.load(join(ENEMY_PATH, "enemy1", "enemy1_1.png")), (40, 35))
|
||||||
|
ENEMY_2 = pygame.transform.scale(pygame.image.load(join(ENEMY_PATH, "enemy2", "enemy2_1.png")), (40, 35))
|
||||||
|
ENEMY_3 = pygame.transform.scale(pygame.image.load(join(ENEMY_PATH, "enemy3", "enemy3_1.png")), (40, 35))
|
||||||
|
ENEMY_MISSILE = pygame.image.load(join(SPRITE_PATH, "missiles", "enemymissile.png")) # enemy missile
|
||||||
|
|
||||||
|
# background
|
||||||
|
BACKGROUND = pygame.transform.scale(pygame.image.load(join(BASE_PATH, "assets", "background.jpg")), (WIDTH, HEIGHT))
|
||||||
|
|
||||||
|
# colors (R, G, B)
|
||||||
|
BLUE = (16, 16, 69)
|
||||||
|
WHITE = (255, 255, 255)
|
||||||
|
RED = (188, 2, 5)
|
||||||
|
|
||||||
|
|
||||||
|
class Missile:
|
||||||
|
|
||||||
|
def __init__(self, x: int, y: int, img) -> None:
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
self.img = img
|
||||||
|
self.mask = pygame.mask.from_surface(self.img)
|
||||||
|
|
||||||
|
def draw(self, window) -> None:
|
||||||
|
window.blit(self.img, (self.x, self.y))
|
||||||
|
|
||||||
|
def move(self, velocity: int) -> None:
|
||||||
|
self.y += velocity
|
||||||
|
|
||||||
|
def off_screen(self, height: int) -> bool:
|
||||||
|
return not (self.y <= height and self.y >= 0)
|
||||||
|
|
||||||
|
def collision(self, object) -> bool:
|
||||||
|
return collide(self, object)
|
||||||
|
|
||||||
|
|
||||||
|
class Ship:
|
||||||
|
COOLDOWN = 30
|
||||||
|
|
||||||
|
def __init__(self, x: int, y: int, lives: int = 5) -> None:
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
self.lives = lives
|
||||||
|
self.ship_img = None
|
||||||
|
self.missile_img = None
|
||||||
|
self.missiles = []
|
||||||
|
self.cooldown_counter = 0
|
||||||
|
|
||||||
|
def draw(self, window) -> None:
|
||||||
|
window.blit(self.ship_img, (self.x, self.y))
|
||||||
|
for missile in self.missiles:
|
||||||
|
missile.draw(WINDOW)
|
||||||
|
|
||||||
|
def move_missiles(self, velocity: int, object) -> None:
|
||||||
|
self.cooldown()
|
||||||
|
for missile in self.missiles:
|
||||||
|
missile.move(velocity)
|
||||||
|
if missile.off_screen(HEIGHT):
|
||||||
|
self.missiles.remove(missile)
|
||||||
|
elif missile.collision(object):
|
||||||
|
object.lives -= 1
|
||||||
|
self.missiles.remove(missile)
|
||||||
|
|
||||||
|
def cooldown(self) -> None:
|
||||||
|
if self.cooldown_counter >= self.COOLDOWN:
|
||||||
|
self.cooldown_counter = 0
|
||||||
|
elif self.cooldown_counter > 0:
|
||||||
|
self.cooldown_counter += 1
|
||||||
|
|
||||||
|
def shoot(self) -> None:
|
||||||
|
if self.cooldown_counter == 0:
|
||||||
|
missile = Missile(self.x + self.get_width() / 2 - 5 / 2, self.y, self.missile_img) # missile spawn offset
|
||||||
|
self.missiles.append(missile)
|
||||||
|
self.cooldown_counter = 1
|
||||||
|
|
||||||
|
def get_width(self) -> int:
|
||||||
|
return self.ship_img.get_width()
|
||||||
|
|
||||||
|
def get_height(self) -> int:
|
||||||
|
return self.ship_img.get_height()
|
||||||
|
|
||||||
|
|
||||||
|
class Player(Ship):
|
||||||
|
|
||||||
|
def __init__(self, x: int, y: int, lives: int = 5) -> None:
|
||||||
|
super().__init__(x, y, lives)
|
||||||
|
self.ship_img = SPACESHIP
|
||||||
|
self.missile_img = PLAYER_MISSILE
|
||||||
|
self.mask = pygame.mask.from_surface(self.ship_img)
|
||||||
|
self.max_lives = lives
|
||||||
|
|
||||||
|
def move_missiles(self, velocity: int, objects: list) -> None:
|
||||||
|
self.cooldown()
|
||||||
|
for missile in self.missiles:
|
||||||
|
missile.move(velocity)
|
||||||
|
if missile.off_screen(HEIGHT):
|
||||||
|
self.missiles.remove(missile)
|
||||||
|
else:
|
||||||
|
for object in objects:
|
||||||
|
if missile.collision(object):
|
||||||
|
objects.remove(object)
|
||||||
|
if missile in self.missiles:
|
||||||
|
self.missiles.remove(missile)
|
||||||
|
|
||||||
|
|
||||||
|
class Enemy(Ship):
|
||||||
|
COLOR_MAP = {
|
||||||
|
"magenta": ENEMY_1,
|
||||||
|
"cyan": ENEMY_2,
|
||||||
|
"lime": ENEMY_3,
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, x: int, y: int, color: str) -> None:
|
||||||
|
super().__init__(x, y)
|
||||||
|
self.ship_img = self.COLOR_MAP[color]
|
||||||
|
self.missile_img = ENEMY_MISSILE
|
||||||
|
self.mask = pygame.mask.from_surface(self.ship_img)
|
||||||
|
|
||||||
|
def move(self, velocity: int) -> None:
|
||||||
|
self.y += velocity
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
run = True
|
||||||
|
lost = False
|
||||||
|
lost_count = 0
|
||||||
|
FPS = 60
|
||||||
|
level = 0
|
||||||
|
|
||||||
|
enemies = []
|
||||||
|
wave_length = 5
|
||||||
|
player_velocity = 7
|
||||||
|
enemy_velocity = 2
|
||||||
|
missile_velocity = 5
|
||||||
|
|
||||||
|
player = Player(300, 650)
|
||||||
|
|
||||||
|
clock = pygame.time.Clock()
|
||||||
|
|
||||||
|
def redraw_window() -> None:
|
||||||
|
WINDOW.blit(BACKGROUND, (0, 0))
|
||||||
|
# draw text
|
||||||
|
lives_label = set_font(50).render(f"Lives: {player.lives}", 1, WHITE)
|
||||||
|
level_label = set_font(50).render(f"Level: {level}", 1, WHITE)
|
||||||
|
WINDOW.blit(lives_label, (10, 10))
|
||||||
|
WINDOW.blit(level_label, (WIDTH - level_label.get_width() - 10, 10))
|
||||||
|
|
||||||
|
for enemy in enemies:
|
||||||
|
enemy.draw(WINDOW)
|
||||||
|
|
||||||
|
player.draw(WINDOW)
|
||||||
|
|
||||||
|
if lost:
|
||||||
|
lost_label = set_font(60).render("You lost!", 1, RED)
|
||||||
|
WINDOW.blit(lost_label, (WIDTH / 2 - lost_label.get_width() / 2, 350))
|
||||||
|
|
||||||
|
pygame.display.update()
|
||||||
|
|
||||||
|
while run:
|
||||||
|
clock.tick(FPS)
|
||||||
|
redraw_window()
|
||||||
|
|
||||||
|
if player.lives <= 0:
|
||||||
|
lost = True
|
||||||
|
lost_count += 1
|
||||||
|
|
||||||
|
# stop game
|
||||||
|
if lost:
|
||||||
|
if lost_count > FPS * 3:
|
||||||
|
run = False
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if len(enemies) == 0:
|
||||||
|
level += 1
|
||||||
|
wave_length += 5
|
||||||
|
for i in range(wave_length):
|
||||||
|
enemy = Enemy(randrange(50, WIDTH - 100), randrange(-1500, -100), choice(["magenta", "cyan", "lime"]))
|
||||||
|
enemies.append(enemy)
|
||||||
|
|
||||||
|
for event in pygame.event.get():
|
||||||
|
# quit game
|
||||||
|
if event.type == pygame.QUIT:
|
||||||
|
quit()
|
||||||
|
|
||||||
|
keys = pygame.key.get_pressed()
|
||||||
|
|
||||||
|
# move left
|
||||||
|
if (keys[pygame.K_a] or keys[pygame.K_LEFT]) and (player.x - player_velocity > 0):
|
||||||
|
player.x -= player_velocity
|
||||||
|
# move right
|
||||||
|
if (keys[pygame.K_d] or keys[pygame.K_RIGHT]) and (player.x + player_velocity + player.get_width() < WIDTH):
|
||||||
|
player.x += player_velocity
|
||||||
|
# shoot
|
||||||
|
if keys[pygame.K_SPACE]:
|
||||||
|
player.shoot()
|
||||||
|
|
||||||
|
for enemy in enemies[:]:
|
||||||
|
enemy.move(enemy_velocity)
|
||||||
|
enemy.move_missiles(missile_velocity, player)
|
||||||
|
|
||||||
|
if randrange(0, 2 * 60) == 1:
|
||||||
|
enemy.shoot()
|
||||||
|
|
||||||
|
if collide(enemy, player) or (enemy.y + enemy.get_height() > HEIGHT):
|
||||||
|
player.lives -= 1
|
||||||
|
enemies.remove(enemy)
|
||||||
|
|
||||||
|
player.move_missiles(-missile_velocity, enemies)
|
||||||
|
|
||||||
|
|
||||||
|
# lambda functions
|
||||||
|
set_font = lambda size, font=FONT: pygame.font.Font(font, size) # sets font size
|
||||||
|
collide = lambda obj1, obj2: obj1.mask.overlap(obj2.mask, (obj2.x - obj1.x, obj2.y - obj1.y)) != None # checks if 2 objects collide/overlap
|
||||||
|
|
||||||
|
|
||||||
|
def main_menu() -> None:
|
||||||
|
while True:
|
||||||
|
WINDOW.blit(BACKGROUND, (0, 0))
|
||||||
|
title_label = set_font(50).render("Press any key to start...", 1, WHITE)
|
||||||
|
WINDOW.blit(title_label, (WIDTH / 2 - title_label.get_width() / 2, HEIGHT / 2 - title_label.get_height() / 2))
|
||||||
|
pygame.display.update()
|
||||||
|
for event in pygame.event.get():
|
||||||
|
if event.type == pygame.QUIT:
|
||||||
|
quit()
|
||||||
|
if event.type == pygame.KEYDOWN:
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main_menu()
|
||||||
121
pygame/space_invaders/source/space_invaders_old.py
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
# Author - Kristiāns Francis Cagulis
|
||||||
|
# Date - 25.02.2022
|
||||||
|
# Title - Space invaders
|
||||||
|
|
||||||
|
import pygame
|
||||||
|
import math
|
||||||
|
import random
|
||||||
|
|
||||||
|
BLUE = (16, 16, 69)
|
||||||
|
|
||||||
|
# init game
|
||||||
|
pygame.init()
|
||||||
|
pygame.display.set_caption("Space invaders")
|
||||||
|
|
||||||
|
# 32x32 game icon
|
||||||
|
icon = pygame.image.load("icons/space_invader_enemy_icon.png")
|
||||||
|
pygame.display.set_icon(icon)
|
||||||
|
# 64x64 player icon
|
||||||
|
player = pygame.image.load("icons/space_shuttle_player_icon.png")
|
||||||
|
player_x = 370
|
||||||
|
player_y = 480
|
||||||
|
player_x_change = 0
|
||||||
|
|
||||||
|
# 64x64 enemy icon
|
||||||
|
enemy = pygame.image.load("icons/space_invader_enemy_icon.png")
|
||||||
|
enemy_x = random.randint(0, 736)
|
||||||
|
enemy_y = random.randint(50, 150)
|
||||||
|
enemy_x_change = .2
|
||||||
|
enemy_y_change = 10
|
||||||
|
|
||||||
|
|
||||||
|
# missile
|
||||||
|
missile = pygame.image.load("icons/fireball_icon.png")
|
||||||
|
missile_x = 0
|
||||||
|
missile_y = 480 # player_y
|
||||||
|
missile_x_change = 0
|
||||||
|
missile_y_change = .50
|
||||||
|
missile_state = "ready"
|
||||||
|
|
||||||
|
screen = pygame.display.set_mode((800, 600))
|
||||||
|
|
||||||
|
|
||||||
|
def display_player(x, y):
|
||||||
|
screen.blit(player, (x, y))
|
||||||
|
|
||||||
|
|
||||||
|
def display_enemy(x, y):
|
||||||
|
screen.blit(enemy, (x, y))
|
||||||
|
|
||||||
|
|
||||||
|
def display_missile(x, y):
|
||||||
|
global missile_state
|
||||||
|
missile_state = "fire"
|
||||||
|
screen.blit(missile, (x + 16, y - 10))
|
||||||
|
|
||||||
|
|
||||||
|
def is_collision(enemy_x, enemy_y, missile_x, missile_y):
|
||||||
|
distance = math.sqrt(math.pow(enemy_x - missile_x, 2) + math.pow(enemy_y - missile_y, 2))
|
||||||
|
if distance < 27:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
running = True
|
||||||
|
|
||||||
|
while running:
|
||||||
|
screen.fill(BLUE)
|
||||||
|
|
||||||
|
# change player pos
|
||||||
|
for event in pygame.event.get():
|
||||||
|
if event.type == pygame.QUIT:
|
||||||
|
running = False
|
||||||
|
if event.type == pygame.KEYDOWN:
|
||||||
|
if event.key == pygame.K_LEFT:
|
||||||
|
player_x_change = -.5
|
||||||
|
if event.key == pygame.K_RIGHT:
|
||||||
|
player_x_change = .5
|
||||||
|
if event.key == pygame.K_SPACE:
|
||||||
|
if missile_state == "ready":
|
||||||
|
missile_x = player_x
|
||||||
|
# missile_state = "fire"
|
||||||
|
display_missile(missile_x, missile_y)
|
||||||
|
|
||||||
|
if event.type == pygame.KEYUP:
|
||||||
|
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
|
||||||
|
player_x_change = 0
|
||||||
|
|
||||||
|
# player pos
|
||||||
|
if player_x + player_x_change > 0 and player_x + player_x_change < 736:
|
||||||
|
player_x += player_x_change
|
||||||
|
|
||||||
|
enemy_x += enemy_x_change
|
||||||
|
enemy_y += enemy_y_change
|
||||||
|
|
||||||
|
# enemy pos
|
||||||
|
if enemy_x >= 736:
|
||||||
|
enemy_x_change = -.2
|
||||||
|
elif enemy_x <= 0:
|
||||||
|
enemy_x_change = .2
|
||||||
|
if enemy_y >= 336:
|
||||||
|
enemy_y_change = -.1
|
||||||
|
elif enemy_y <= 50:
|
||||||
|
enemy_y_change = .1
|
||||||
|
|
||||||
|
collision = is_collision(enemy_x, enemy_y, missile_x, missile_y)
|
||||||
|
if collision:
|
||||||
|
missile_y = 480
|
||||||
|
missile_state = "ready"
|
||||||
|
# score ...
|
||||||
|
|
||||||
|
display_enemy(enemy_x, enemy_y)
|
||||||
|
|
||||||
|
if missile_y <= 0:
|
||||||
|
missile_state = "ready"
|
||||||
|
if missile_state == "fire":
|
||||||
|
display_missile(missile_x, missile_y)
|
||||||
|
missile_y -= missile_y_change
|
||||||
|
|
||||||
|
display_player(player_x, player_y)
|
||||||
|
pygame.display.update()
|
||||||