2024-04-23 20:14:24 -04:00
|
|
|
import random
|
|
|
|
import sys
|
|
|
|
import time
|
|
|
|
import arcade
|
2024-04-26 09:16:45 -04:00
|
|
|
import Score
|
2024-04-23 20:14:24 -04:00
|
|
|
|
|
|
|
from Bullet import Bullet
|
|
|
|
from Alien import Alien
|
|
|
|
|
|
|
|
DEBUG = True
|
|
|
|
SLOW = False
|
|
|
|
|
|
|
|
SLOW_SPEED = 0.01
|
|
|
|
|
|
|
|
SCREEN_SCALE = 3
|
|
|
|
|
|
|
|
SCREEN_HEIGHT = 256 * SCREEN_SCALE
|
|
|
|
SCREEN_WIDTH = 224 * SCREEN_SCALE
|
|
|
|
SCREEN_TITLE = "Space Invaders"
|
|
|
|
|
|
|
|
PLAYER_SPEED = 1
|
|
|
|
|
|
|
|
PLAYER_BOUNDS = 32
|
|
|
|
ALIEN_BOUNDS = 16
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MyGame(arcade.Window):
|
|
|
|
""" Main application class"""
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
|
|
|
|
|
|
|
|
self.activeBullet = False
|
|
|
|
|
|
|
|
|
|
|
|
self.wall_list = None
|
|
|
|
self.player_list = None
|
|
|
|
|
|
|
|
self.Won = False
|
|
|
|
self.Score = 0
|
|
|
|
|
|
|
|
self.bullet = None
|
|
|
|
self.aliens = [[Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien],
|
|
|
|
[Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien],
|
|
|
|
[Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien],
|
|
|
|
[Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien],
|
|
|
|
[Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien, Alien]]
|
|
|
|
|
|
|
|
self.alienCounterY = 4
|
|
|
|
self.alienCounterX = 0
|
|
|
|
self.alienChangeDir = 0
|
|
|
|
self.alienCurrentDir = -1
|
|
|
|
self.movedown = False
|
2024-04-26 09:45:31 -04:00
|
|
|
self.current_player_texture_index = 0
|
2024-04-23 20:14:24 -04:00
|
|
|
|
|
|
|
self.player_sprite = None
|
|
|
|
|
|
|
|
self.movePlayer = 0
|
|
|
|
if DEBUG:
|
|
|
|
arcade.set_background_color(arcade.color.BLUE)
|
|
|
|
else:
|
|
|
|
arcade.set_background_color(arcade.csscolor.BLACK)
|
|
|
|
|
|
|
|
self.i = 0
|
|
|
|
|
|
|
|
def setup(self):
|
|
|
|
"""start / restart game"""
|
|
|
|
|
|
|
|
self.scene = arcade.Scene()
|
|
|
|
|
|
|
|
self.scene.add_sprite_list("Players")
|
|
|
|
self.scene.add_sprite_list("Walls", use_spatial_hash=True)
|
|
|
|
|
|
|
|
self.player_list = arcade.SpriteList()
|
|
|
|
self.wall_list = arcade.SpriteList(use_spatial_hash=True)
|
|
|
|
self.rend = 0
|
|
|
|
self.lives = 3
|
|
|
|
self.level = 0
|
2024-04-26 09:16:45 -04:00
|
|
|
self.score = None
|
2024-04-23 20:14:24 -04:00
|
|
|
# self.overlay_color = (0,255,0,128)
|
|
|
|
self.player_sprite_death = None
|
|
|
|
self.somethingalsi = True
|
2024-04-26 09:09:32 -04:00
|
|
|
self.death_textures = None
|
2024-04-23 20:14:24 -04:00
|
|
|
|
|
|
|
# set up the player
|
|
|
|
image_source = "assets/Sprites/Player/Player.png"
|
|
|
|
self.player_sprite = arcade.Sprite(image_source, SCREEN_SCALE)
|
|
|
|
self.player_sprite.center_x = 32 * SCREEN_SCALE
|
|
|
|
self.player_sprite.center_y = (32 + 4) * SCREEN_SCALE
|
|
|
|
self.player_list.append(self.player_sprite)
|
|
|
|
|
|
|
|
|
|
|
|
# Create Left Boundry
|
|
|
|
if DEBUG == True:
|
|
|
|
wall = arcade.SpriteSolidColor(1, SCREEN_HEIGHT, arcade.color.RED)
|
|
|
|
else:
|
|
|
|
wall = arcade.SpriteSolidColor(0, SCREEN_HEIGHT, arcade.color.BLACK)
|
|
|
|
wall.center_x = (PLAYER_BOUNDS - 8) * SCREEN_SCALE
|
|
|
|
wall.center_y = SCREEN_HEIGHT / 2
|
|
|
|
self.wall_list.append(wall)
|
|
|
|
# Create Right Boundry
|
|
|
|
if DEBUG == True:
|
|
|
|
wall = arcade.SpriteSolidColor(1, SCREEN_HEIGHT, arcade.color.RED)
|
|
|
|
else:
|
|
|
|
wall = arcade.SpriteSolidColor(0, SCREEN_HEIGHT, arcade.color.BLACK)
|
|
|
|
wall.center_x = (224 - PLAYER_BOUNDS + 8) * SCREEN_SCALE
|
|
|
|
wall.center_y = SCREEN_HEIGHT / 2
|
|
|
|
self.wall_list.append(wall)
|
|
|
|
|
|
|
|
if DEBUG == True:
|
|
|
|
wall = arcade.SpriteSolidColor(1, SCREEN_HEIGHT, arcade.color.GREEN)
|
|
|
|
else:
|
|
|
|
wall = arcade.SpriteSolidColor(0, SCREEN_HEIGHT, arcade.color.BLACK)
|
|
|
|
wall.center_x = (ALIEN_BOUNDS - 8) * SCREEN_SCALE
|
|
|
|
wall.center_y = SCREEN_HEIGHT / 2
|
|
|
|
self.wall_list.append(wall)
|
|
|
|
# Create Right Boundry
|
|
|
|
if DEBUG == True:
|
|
|
|
wall = arcade.SpriteSolidColor(1, SCREEN_HEIGHT, arcade.color.GREEN)
|
|
|
|
else:
|
|
|
|
wall = arcade.SpriteSolidColor(0, SCREEN_HEIGHT, arcade.color.BLACK)
|
|
|
|
wall.center_x = (224 - ALIEN_BOUNDS + 8) * SCREEN_SCALE
|
|
|
|
wall.center_y = SCREEN_HEIGHT / 2
|
|
|
|
self.wall_list.append(wall)
|
|
|
|
|
|
|
|
# Aliens
|
|
|
|
for b in range (0,5,1):
|
|
|
|
for a in range(0, 11, 1):
|
|
|
|
if b == 0:
|
|
|
|
alienType = "SA"
|
|
|
|
elif b == 1 or b == 2:
|
|
|
|
alienType = "MA"
|
|
|
|
else:
|
|
|
|
alienType = "LA"
|
|
|
|
aliena = Alien(16 * (a+1) + 16, 200 - (16 * (b+1)), SCREEN_SCALE, DEBUG,alienType)
|
|
|
|
# aliena.update(None,None,None)
|
|
|
|
self.aliens[b][a] = aliena
|
|
|
|
|
2024-04-26 09:16:45 -04:00
|
|
|
self.score = Score(SCREEN_SCALE,DEBUG)
|
|
|
|
|
2024-04-23 20:14:24 -04:00
|
|
|
def collisionCheck(self, x1, y1, x2, y2, rx, ry):
|
|
|
|
if abs(x1 - x2) <= rx and abs(y1 - y2) <= ry:
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
|
|
|
def on_key_press(self, key, modifiers):
|
|
|
|
|
|
|
|
if key == arcade.key.SPACE and self.activeBullet == False:
|
|
|
|
self.bullet = Bullet(SCREEN_SCALE, DEBUG, self.player_sprite.center_x, self.player_sprite.center_y)
|
|
|
|
self.activeBullet = True
|
|
|
|
if key == arcade.key.LEFT:
|
|
|
|
self.movePlayer = -PLAYER_SPEED * SCREEN_SCALE
|
|
|
|
elif key == arcade.key.RIGHT:
|
|
|
|
self.movePlayer = PLAYER_SPEED * SCREEN_SCALE
|
|
|
|
|
|
|
|
|
|
|
|
def on_key_release(self, key, modifiers):
|
|
|
|
if key == arcade.key.LEFT and self.movePlayer == -PLAYER_SPEED * SCREEN_SCALE:
|
|
|
|
self.movePlayer = 0
|
|
|
|
elif key == arcade.key.RIGHT and self.movePlayer == PLAYER_SPEED * SCREEN_SCALE:
|
|
|
|
self.movePlayer = 0
|
|
|
|
|
2024-04-26 09:09:32 -04:00
|
|
|
def load_death_animation(self):
|
|
|
|
self.death_textures = []
|
|
|
|
for i in range(0,5):
|
|
|
|
|
|
|
|
texture = arcade.load_texture("assets/Sprites/Player/PlayerDeath1.png")
|
|
|
|
self.death_textures.append(texture)
|
|
|
|
texture = arcade.load_texture("assets/Sprites/Player/PlayerDeath2.png")
|
|
|
|
self.death_textures.append(texture)
|
|
|
|
|
|
|
|
def play_death_animation(self):
|
2024-04-26 09:45:31 -04:00
|
|
|
if self.current_player_texture_index < len(self.death_textures):
|
|
|
|
self.player_sprite.set_texture(self.current_player_texture_index)
|
|
|
|
self.current_player_texture_index += 1
|
2024-04-26 09:09:32 -04:00
|
|
|
|
2024-04-23 20:14:24 -04:00
|
|
|
def on_draw(self):
|
|
|
|
self.clear()
|
|
|
|
|
|
|
|
# try:
|
|
|
|
# self.player_sprite_death.draw(pixelated=True)
|
|
|
|
# except Exception as e:
|
|
|
|
# pass
|
|
|
|
|
|
|
|
# Render player bullet if it exists
|
|
|
|
try:
|
|
|
|
self.bullet.bullet_sprite.draw(pixelated=True)
|
|
|
|
except Exception as e:
|
|
|
|
if DEBUG:
|
|
|
|
self.rend += 1
|
|
|
|
if self.rend >= 20:
|
|
|
|
print(e)
|
|
|
|
self.rend = 0
|
|
|
|
|
|
|
|
# Render alien bullets if they exist and render aliens
|
|
|
|
try:
|
|
|
|
for alienx in self.aliens:
|
|
|
|
for alien in alienx:
|
|
|
|
try:
|
|
|
|
alien.bullet.bullet_sprite.draw(pixelated=True)
|
|
|
|
except Exception as e:
|
|
|
|
pass
|
|
|
|
alien.alien_sprite.draw(pixelated=True)
|
|
|
|
except Exception as e:
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.player_list.draw(pixelated=True)
|
|
|
|
self.wall_list.draw(pixelated=True)
|
|
|
|
def KillBullet(self):
|
|
|
|
self.bullet = None
|
|
|
|
self.activeBullet = False
|
|
|
|
|
|
|
|
def respawn(self):
|
2024-04-26 09:09:32 -04:00
|
|
|
# for alienRow in self.aliens:
|
|
|
|
# for alien in alienRow:
|
|
|
|
# alien.bullet = None
|
2024-04-23 20:14:24 -04:00
|
|
|
self.player_sprite.center_x = 32*SCREEN_SCALE
|
|
|
|
time.sleep(2)
|
|
|
|
def death(self):
|
|
|
|
if self.lives > 0:
|
|
|
|
self.somethingalsi = False
|
2024-04-26 09:09:32 -04:00
|
|
|
self.load_death_animation()
|
|
|
|
self.play_death_animation()
|
|
|
|
self.respawn()
|
2024-04-23 20:14:24 -04:00
|
|
|
else:
|
|
|
|
if DEBUG:
|
|
|
|
print(str(self.Score))
|
|
|
|
sys.exit()
|
|
|
|
|
|
|
|
def update(self, delta_time):
|
|
|
|
|
|
|
|
if self.somethingalsi:
|
|
|
|
# Picking numbers to possibly spawn an alien bullet
|
|
|
|
testx = random.randint(0, 5 + 100 - self.level)
|
|
|
|
testy = random.randint(0, 11 + 100 - self.level)
|
|
|
|
|
|
|
|
|
|
|
|
# Checking if player bullet is off-screen, if so, set bullet to None, else, update bullet
|
|
|
|
try:
|
|
|
|
if self.bullet.getY() >= SCREEN_HEIGHT:
|
|
|
|
self.KillBullet()
|
|
|
|
|
|
|
|
if self.bullet != None:
|
|
|
|
self.bullet.update()
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
self.error = e
|
|
|
|
|
|
|
|
# Run the update method for each alien's bullet that exists in the self.aliens list
|
|
|
|
try:
|
|
|
|
for alienx in self.aliens:
|
|
|
|
for alien in alienx:
|
|
|
|
try:
|
|
|
|
alien.bullet.update()
|
|
|
|
except Exception as e:
|
|
|
|
pass
|
|
|
|
except Exception as e:
|
|
|
|
pass
|
|
|
|
|
|
|
|
# Checks if the alien's bullet is below -50, if so, set alien's bullet to None
|
|
|
|
# Checks to see if testx and testy == self.alien[testx],[testy]. if yes: spawn new alien bullet
|
|
|
|
try:
|
|
|
|
for indexx, alienx in enumerate(self.aliens):
|
|
|
|
for index, alien in enumerate(alienx):
|
|
|
|
try:
|
|
|
|
alien.checkBullet()
|
|
|
|
if indexx == testx and index == testy:
|
|
|
|
alien.spawnBullet()
|
|
|
|
except Exception as e:
|
|
|
|
pass
|
|
|
|
except Exception as e:
|
|
|
|
pass
|
|
|
|
|
|
|
|
if self.alienCounterY < 0:
|
|
|
|
# Reset the X and Y counter variables
|
|
|
|
self.alienCounterY = len(self.aliens) - 1
|
|
|
|
self.alienCounterX = 0
|
|
|
|
# Alien Movement
|
|
|
|
if self.Won == False:
|
|
|
|
#Left - Right Movement
|
|
|
|
|
|
|
|
if self.alienCounterX <= len(self.aliens[self.alienCounterY]) - 1:
|
|
|
|
x = self.aliens[self.alienCounterY][self.alienCounterX].getX()
|
|
|
|
|
|
|
|
# Right Alien Bound Check
|
|
|
|
if x <= ALIEN_BOUNDS * SCREEN_SCALE + SCREEN_SCALE:
|
|
|
|
self.alienChangeDir = 1
|
|
|
|
# Left Alien Bound Check
|
|
|
|
elif x >= SCREEN_WIDTH - ALIEN_BOUNDS * SCREEN_SCALE - SCREEN_SCALE:
|
|
|
|
self.alienChangeDir = -1
|
|
|
|
|
|
|
|
# Update current alien
|
|
|
|
self.aliens[self.alienCounterY][self.alienCounterX].update(True, self.alienCurrentDir, self.movedown)
|
|
|
|
|
|
|
|
# Move the X counter variable to the next alien
|
|
|
|
self.alienCounterX += 1
|
|
|
|
|
|
|
|
# If an exeption is reached, it is likely that the X counter is out of bounds
|
|
|
|
# which means we need to go to the next row of aliens
|
|
|
|
else:
|
|
|
|
|
|
|
|
# Reset X counter
|
|
|
|
self.alienCounterX = 0
|
|
|
|
|
|
|
|
# Decrease Y counter so that we move to the next row of aliens
|
|
|
|
self.alienCounterY -= 1
|
|
|
|
|
|
|
|
# if we go outside the minimum index of our aliens list, which means we reached the
|
|
|
|
# very end of the list of aliens, raise an exception so that the except block runs
|
|
|
|
if self.alienCounterY < 0:
|
|
|
|
|
|
|
|
# Reset the X and Y counter variables
|
|
|
|
self.alienCounterY = len(self.aliens) - 1
|
|
|
|
self.alienCounterX = 0
|
|
|
|
|
|
|
|
# if the aliens are at the right alien bound
|
|
|
|
if self.alienChangeDir == -1:
|
|
|
|
|
|
|
|
if self.alienChangeDir != self.alienCurrentDir:
|
|
|
|
self.movedown = True
|
|
|
|
else:
|
|
|
|
self.movedown = False
|
|
|
|
self.alienCurrentDir = -1
|
|
|
|
|
|
|
|
# Reset alienChangeDir
|
|
|
|
self.alienChangeDir = 0
|
|
|
|
|
|
|
|
# if the aliens are at the left alien bound
|
|
|
|
elif self.alienChangeDir == 1:
|
|
|
|
if self.alienChangeDir != self.alienCurrentDir:
|
|
|
|
self.movedown = True
|
|
|
|
else:
|
|
|
|
self.movedown = False
|
|
|
|
self.alienCurrentDir = 1
|
|
|
|
self.alienChangeDir = 0
|
|
|
|
else:
|
|
|
|
self.alienChangeDir = 0
|
|
|
|
# if DEBUG:
|
|
|
|
# print(e)
|
|
|
|
if len(self.aliens) == 0:
|
|
|
|
self.Won = True
|
|
|
|
# except Exception as e:
|
|
|
|
# if DEBUG:
|
|
|
|
# print(e)
|
|
|
|
|
|
|
|
print("You Won!")
|
|
|
|
sys.exit()
|
|
|
|
# Check to see if any aliens are colliding with a player's bullet
|
|
|
|
for alienRow in self.aliens:
|
|
|
|
if alienRow == []:
|
|
|
|
self.aliens.remove(alienRow)
|
|
|
|
for alien in alienRow:
|
|
|
|
try:
|
|
|
|
# Check for alien colliding with player bullet
|
|
|
|
if self.collisionCheck(alien.getX(), alien.getY(), self.bullet.getX(), self.bullet.getY(),
|
|
|
|
alien.getSizeX(), alien.getSizeY()):
|
|
|
|
|
|
|
|
# For Scoring Points
|
|
|
|
type = alien.getType()
|
|
|
|
if type == "SA":
|
|
|
|
self.Score += 40
|
|
|
|
elif type == "MA":
|
|
|
|
self.Score += 20
|
|
|
|
elif type == "LA":
|
|
|
|
self.Score += 10
|
|
|
|
alienRow.remove(alien)
|
|
|
|
if DEBUG:
|
|
|
|
print(str(self.Score))
|
|
|
|
|
|
|
|
# Kill player bullet that hit the alien
|
|
|
|
self.KillBullet()
|
|
|
|
except Exception as e:
|
|
|
|
pass
|
|
|
|
try:
|
|
|
|
# Check for player colliding with alien bullet
|
|
|
|
if self.collisionCheck(self.player_sprite.center_x, self.player_sprite.center_y, alien.bullet.getX(), alien.bullet.getY(),
|
|
|
|
7 * SCREEN_SCALE, 5 * SCREEN_SCALE):
|
|
|
|
|
|
|
|
self.lives -= 1
|
|
|
|
|
|
|
|
self.death()
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
if self.player_sprite.center_x >= 193 * SCREEN_SCALE and self.movePlayer == PLAYER_SPEED * SCREEN_SCALE:
|
|
|
|
self.movePlayer = 0
|
|
|
|
|
|
|
|
elif self.player_sprite.center_x <= (PLAYER_BOUNDS - 2) * SCREEN_SCALE and self.movePlayer == -PLAYER_SPEED * SCREEN_SCALE:
|
|
|
|
self.movePlayer = 0
|
|
|
|
|
|
|
|
else:
|
|
|
|
self.player_sprite.center_x += self.movePlayer
|
|
|
|
|
|
|
|
|
|
|
|
if SLOW:
|
|
|
|
time.sleep(SLOW_SPEED)
|
|
|
|
|
|
|
|
else:
|
2024-04-26 09:09:32 -04:00
|
|
|
self.death()
|
2024-04-23 20:14:24 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
window = MyGame()
|
|
|
|
window.setup()
|
|
|
|
arcade.run()
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|
|
|
|
|
|
|
|
|