diff --git a/__pycache__/enemy.cpython-313.pyc b/__pycache__/enemy.cpython-313.pyc deleted file mode 100644 index ca96a84..0000000 Binary files a/__pycache__/enemy.cpython-313.pyc and /dev/null differ diff --git a/__pycache__/player.cpython-313.pyc b/__pycache__/player.cpython-313.pyc deleted file mode 100644 index 9166951..0000000 Binary files a/__pycache__/player.cpython-313.pyc and /dev/null differ diff --git a/__pycache__/settings.cpython-313.pyc b/__pycache__/settings.cpython-313.pyc deleted file mode 100644 index 5232d6d..0000000 Binary files a/__pycache__/settings.cpython-313.pyc and /dev/null differ diff --git a/enemy.py b/enemy.py deleted file mode 100644 index 2fe4b2c..0000000 --- a/enemy.py +++ /dev/null @@ -1,26 +0,0 @@ -from settings import SCREEN_HEIGHT, SCREEN_WIDTH -import random -import pygame -from pygame.locals import ( - RLEACCEL,) -class Enemy(pygame.sprite.Sprite): - def __init__(self): - super(Enemy, self).__init__() - self.surf= pygame.image.load("sprites/Enemy_Sprite.png").convert() - self.surf.set_colorkey((0, 0, 0), RLEACCEL) - #self.surf = pygame.Surface((24, 10)) - #self.surf.fill((255, 0, 0)) - self.rect = self.surf.get_rect( - center=( - random.uniform(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100), - random.uniform(0, SCREEN_HEIGHT), - ) - ) - self.speed = random.uniform(4,10) - - - - def update(self): - self.rect.move_ip(-self.speed, 0) - if self.rect.right < 0: - self.kill() \ No newline at end of file diff --git a/main.py b/main.py index d4e43f9..6a6c4f6 100644 --- a/main.py +++ b/main.py @@ -1,178 +1,230 @@ import pygame -from player import Player -from enemy import Enemy -from settings import SCREEN_HEIGHT, SCREEN_WIDTH +import random +import math -from pygame.locals import ( - RLEACCEL, - K_UP, - K_DOWN, - K_LEFT, - K_RIGHT, - K_ESCAPE, - KEYDOWN, - QUIT, - K_SPACE, - K_f, - K_RETURN, -) +# ----------------------------- +# Settings +# ----------------------------- +SCREEN_WIDTH = 1280 +SCREEN_HEIGHT = 720 +FPS = 80 +NUM_ENEMIES = 14 -pygame.mixer.init() +# ----------------------------- +# Initialize Pygame +# ----------------------------- pygame.init() - -pygame.font.init() -my_font = pygame.font.SysFont('Comic Sans MS', 30) - -pygame.mixer.music.load("sounds/aura.mp3") - -collision_sound = pygame.mixer.Sound("sounds/dead.ogg") +pygame.mixer.init() # Initialize mixer for music screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) - -ADDENEMY = pygame.USEREVENT + 1 -pygame.time.set_timer(ADDENEMY, 1000) - -running = True -game_started = False - -# Initialize player, enemy, and sprite groups -player = Player() -enemy = Enemy() -enemies = pygame.sprite.Group() -all_sprites = pygame.sprite.Group() - -all_sprites.add(player) -all_sprites.add(enemy) -enemies.add(enemy) - -bg1 = pygame.transform.scale(pygame.image.load("sprites/Day.city.png").convert(), (SCREEN_WIDTH, SCREEN_HEIGHT)) - +pygame.display.set_caption("Polarity Field") clock = pygame.time.Clock() +font = pygame.font.SysFont(None, 36) -# Start screen loop -while not game_started: - for event in pygame.event.get(): - if event.type == KEYDOWN: - if event.key == K_SPACE: - game_started = True # Start the game when Space is pressed - if event.key == K_f: - game_started = True # Start the game when F is pressed (optional) - elif event.type == QUIT: - running = False - game_started = True # Exit the loop if quit event occurs +# ----------------------------- +# Load background music +# ----------------------------- +pygame.mixer.music.load("sprites/music.ogg") +pygame.mixer.music.set_volume(0.5) +pygame.mixer.music.play(-1) # Loop indefinitely - screen.fill((0, 0, 0)) - text = my_font.render("Start", True, (255, 255, 255)) - screen.blit(text, ( - (SCREEN_WIDTH - text.get_width()) / 2, - (SCREEN_HEIGHT - text.get_height()) / 2, - )) - text = my_font.render("Press Space to Start", True, (255, 255, 255)) - screen.blit(text, ( - (SCREEN_WIDTH - text.get_width()) / 2, - (SCREEN_HEIGHT - text.get_height() - 200) - )) - - pygame.display.flip() - clock.tick(30) # Limit FPS to 30 +# ----------------------------- +# Load sprites AFTER display is ready +# ----------------------------- +player_surf = pygame.image.load("sprites/orb_purple.png").convert_alpha() +player_surf = pygame.transform.scale(player_surf, (60, 60)) +player_rect = player_surf.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)) +player_polarity = 1 +player_lives = 3 -pygame.mixer.music.play(loops=-1, fade_ms=1000) +enemies = [] +for _ in range(NUM_ENEMIES): + polarity = random.choice([1, -1]) + if polarity == 1: + surf = pygame.image.load("sprites/orb_red.png").convert_alpha() + else: + surf = pygame.image.load("sprites/orb_blue.png").convert_alpha() + surf = pygame.transform.scale(surf, (50, 50)) + # Spawn 500 pixels away from player + while True: + x = random.randint(0, SCREEN_WIDTH) + y = random.randint(0, SCREEN_HEIGHT) + dx = x - player_rect.centerx + dy = y - player_rect.centery + dist = math.hypot(dx, dy) + if dist >= 500: + break -# Main game loop + rect = surf.get_rect(center=(x, y)) + speed_x = 0 # stationary until game starts + speed_y = 0 + enemies.append({ + "surf": surf, + "rect": rect, + "polarity": polarity, + "speed_x": speed_x, + "speed_y": speed_y + }) + +# ----------------------------- +# Score & cooldown +# ----------------------------- +score = 0 +hit_cooldown = 0 +game_started = False # Game begins only after first movement + +# ----------------------------- +# Main loop +# ----------------------------- +running = True while running: - screen.fill((0, 0, 0)) # Background color - screen.blit(bg1, (0, 0)) # Draw the background image - + clock.tick(FPS) + screen.fill((20, 20, 20)) + # ----------------------------- + # Events + # ----------------------------- for event in pygame.event.get(): - if event.type == KEYDOWN: - if event.key == K_ESCAPE: - running = False # Quit on Escape - elif event.key == K_RETURN: # Press Enter to restart - # Reset the game state - player.kill() # Remove player from all_sprites - enemy.kill() # Remove enemy from all_sprites - enemies.empty() # Empty enemies group - all_sprites.empty() # Empty all_sprites group + if event.type == pygame.QUIT: + running = False + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_ESCAPE: + running = False + if event.key == pygame.K_SPACE and game_started: + player_polarity *= -1 - # Reinitialize player, enemies, and all sprites - player = Player() - enemy = Enemy() - enemies.add(enemy) - all_sprites.add(player) - all_sprites.add(enemy) + # ----------------------------- + # Player movement + # ----------------------------- + keys = pygame.key.get_pressed() + dx = dy = 0 + if keys[pygame.K_w] or keys[pygame.K_UP]: + dy -= 6 + if keys[pygame.K_s] or keys[pygame.K_DOWN]: + dy += 6 + if keys[pygame.K_a] or keys[pygame.K_LEFT]: + dx -= 6 + if keys[pygame.K_d] or keys[pygame.K_RIGHT]: + dx += 6 - # Reset background and re-enter game loop - continue # Restart game loop from the beginning + # Start game on first movement + if not game_started and (dx != 0 or dy != 0): + game_started = True + # Activate enemy movement now + for enemy in enemies: + enemy["speed_x"] = random.uniform(-3, 3) + enemy["speed_y"] = random.uniform(-3, 3) - elif event.type == QUIT: - running = False # Quit on window close + player_rect.move_ip(dx, dy) + player_rect.clamp_ip(pygame.Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)) + moved = dx != 0 or dy != 0 - elif event.type == ADDENEMY: - # Add a new enemy each second - new_enemy = Enemy() - enemies.add(new_enemy) - all_sprites.add(new_enemy) + # ----------------------------- + # Enemy updates & scoring (only if game started) + # ----------------------------- + if game_started: + for enemy in enemies: + # Polarity effect + if enemy["polarity"] == player_polarity: # repel + if enemy["rect"].centerx < player_rect.centerx: + enemy["rect"].x -= 4 + else: + enemy["rect"].x += 4 + if enemy["rect"].centery < player_rect.centery: + enemy["rect"].y -= 4 + else: + enemy["rect"].y += 4 + else: # attract + if enemy["rect"].centerx < player_rect.centerx: + enemy["rect"].x += 4 + else: + enemy["rect"].x -= 4 + if enemy["rect"].centery < player_rect.centery: + enemy["rect"].y += 4 + else: + enemy["rect"].y -= 4 - pressed_keys = pygame.key.get_pressed() + # Random drift + enemy["rect"].x += enemy["speed_x"] * 0.3 + enemy["rect"].y += enemy["speed_y"] * 0.3 - player.update(pressed_keys) - enemies.update() + # Bounce on screen edges + if enemy["rect"].left < 0 or enemy["rect"].right > SCREEN_WIDTH: + enemy["speed_x"] *= -1 + if enemy["rect"].top < 0 or enemy["rect"].bottom > SCREEN_HEIGHT: + enemy["speed_y"] *= -1 - # Render all sprites - for entity in all_sprites: - screen.blit(entity.surf, entity.rect) + # Prevent stacking + for other in enemies: + if other != enemy: + dx_sep = enemy["rect"].centerx - other["rect"].centerx + dy_sep = enemy["rect"].centery - other["rect"].centery + dist_sep = math.hypot(dx_sep, dy_sep) + min_dist = 30 + if dist_sep < min_dist and dist_sep != 0: + push_x = (dx_sep / dist_sep) * (min_dist - dist_sep) / 2 + push_y = (dy_sep / dist_sep) * (min_dist - dist_sep) / 2 + enemy["rect"].move_ip(push_x, push_y) + other["rect"].move_ip(-push_x, -push_y) - # Check for collisions between player and enemies - if pygame.sprite.spritecollideany(player, enemies): - player.kill() # Remove player when it collides with an enemy - pygame.time.delay(250) # Wait a bit before showing the game over screen + # Collision + if hit_cooldown == 0 and player_rect.colliderect(enemy["rect"]): + player_lives -= 1 + hit_cooldown = FPS + for e in enemies: + dx_push = e["rect"].centerx - player_rect.centerx + dy_push = e["rect"].centery - player_rect.centery + e["rect"].move_ip(dx_push//2, dy_push//2) - pygame.mixer.stop + # Draw enemy + screen.blit(enemy["surf"], enemy["rect"]) - collision_sound.play() - # Game Over screen after collision - screen.fill((0, 0, 0)) # Clear the screen with a black background - - text = my_font.render("Game Over", True, (255, 0, 0)) - screen.blit(text, ( - (SCREEN_WIDTH - text.get_width()) / 2, - (SCREEN_HEIGHT - text.get_height()) / 2 - )) + # Update score + if moved: + score += 1 - text = my_font.render("Press Enter to Restart", True, (255, 255, 255)) - screen.blit(text, ( - (SCREEN_WIDTH - text.get_width()) / 2, - (SCREEN_HEIGHT - text.get_height()) / 2 + 50, - )) + # Update cooldown + if hit_cooldown > 0: + hit_cooldown -= 1 - text = my_font.render("Press Escape to Quit", True, (255, 255, 255)) - screen.blit(text, ( - (SCREEN_WIDTH - text.get_width()) / 2, - (SCREEN_HEIGHT - text.get_height()) / 2 +100, - )) + # ----------------------------- + # Draw player + # ----------------------------- + screen.blit(player_surf, player_rect) - pygame.display.flip() + # ----------------------------- + # Draw HUD + # ----------------------------- + hud = font.render(f"Lives: {player_lives} Score: {score}", True, (255, 255, 255)) + screen.blit(hud, (20, 20)) - # Wait for the player to press Enter to restart or Escape to quit - waiting_for_input = True - while waiting_for_input: - for event in pygame.event.get(): - if event.type == KEYDOWN: - if event.key == K_RETURN: - waiting_for_input = False # Player pressed Enter to restart - if event.key == K_ESCAPE: - running = False # Player pressed Escape to quit - waiting_for_input = False - elif event.type == QUIT: - waiting_for_input = False - running = False + # ----------------------------- + # Check for game over + # ----------------------------- + if player_lives <= 0: + running = False - pygame.display.flip() # Update the screen + pygame.display.flip() - clock.tick(60) # Limit FPS to 60 +# ----------------------------- +# Game Over screen +# ----------------------------- +screen.fill((20, 20, 20)) +game_over_text = font.render("GAME OVER", True, (255, 0, 0)) +score_text = font.render(f"Final Score: {score}", True, (255, 255, 255)) + +# Center text +screen.blit(game_over_text, (SCREEN_WIDTH//2 - game_over_text.get_width()//2, SCREEN_HEIGHT//2 - 40)) +screen.blit(score_text, (SCREEN_WIDTH//2 - score_text.get_width()//2, SCREEN_HEIGHT//2 + 10)) + +pygame.display.flip() + +# Wait until the player closes the window +game_over = True +while game_over: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + game_over = False -pygame.mixer.music.stop() -pygame.mixer.quit() pygame.quit() diff --git a/player.py b/player.py deleted file mode 100644 index 0e56427..0000000 --- a/player.py +++ /dev/null @@ -1,41 +0,0 @@ -import pygame -from settings import SCREEN_HEIGHT, SCREEN_WIDTH -from pygame.locals import ( - RLEACCEL, - K_UP, - K_DOWN, - K_LEFT, - K_RIGHT, - K_ESCAPE, - KEYDOWN, - QUIT, -) - - -class Player(pygame.sprite.Sprite): - def __init__(self): - super().__init__() - self.surf = pygame.transform.scale( - pygame.image.load("sprites/Heart1.png").convert(), - (50, 66)) - self.surf.set_colorkey((0, 0, 0), RLEACCEL) - self.rect= self.surf.get_rect() - #self.surf = pygame.Surface((40, 40)) - def update(self, pressed_keys): - if pressed_keys[K_UP]: - self.rect.move_ip(0, -4) - if pressed_keys[K_DOWN]: - self.rect.move_ip(0, 4) - if pressed_keys[K_LEFT]: - self.rect.move_ip(-4, 0) - if pressed_keys[K_RIGHT]: - self.rect.move_ip(4, 0) - - if self.rect.left < 0: - self.rect.left = 0 - if self.rect.right > SCREEN_WIDTH: - self.rect.right = SCREEN_WIDTH - if self.rect.top <= 0: - self.rect.top = 0 - if self.rect.bottom >= SCREEN_HEIGHT: - self.rect.bottom = SCREEN_HEIGHT diff --git a/settings.py b/settings.py deleted file mode 100644 index 63c5ac3..0000000 --- a/settings.py +++ /dev/null @@ -1,2 +0,0 @@ -SCREEN_WIDTH = 1920 -SCREEN_HEIGHT = 1080 \ No newline at end of file diff --git a/sounds/aura.mp3 b/sounds/aura.mp3 deleted file mode 100644 index 3075854..0000000 Binary files a/sounds/aura.mp3 and /dev/null differ diff --git a/sounds/dead.ogg b/sounds/dead.ogg deleted file mode 100644 index 990a7e0..0000000 Binary files a/sounds/dead.ogg and /dev/null differ diff --git a/sprites/Bandit.png b/sprites/Bandit.png deleted file mode 100644 index a6646b1..0000000 Binary files a/sprites/Bandit.png and /dev/null differ diff --git a/sprites/Day.city.png b/sprites/Day.city.png deleted file mode 100644 index 5fb29e2..0000000 Binary files a/sprites/Day.city.png and /dev/null differ diff --git a/sprites/Enemy_Sprite.png b/sprites/Enemy_Sprite.png deleted file mode 100644 index 53b6f35..0000000 Binary files a/sprites/Enemy_Sprite.png and /dev/null differ diff --git a/sprites/Graveyard.png b/sprites/Graveyard.png deleted file mode 100644 index fe3e37d..0000000 Binary files a/sprites/Graveyard.png and /dev/null differ diff --git a/sprites/Heart1.png b/sprites/Heart1.png deleted file mode 100644 index 3b6e37b..0000000 Binary files a/sprites/Heart1.png and /dev/null differ diff --git a/sprites/Player2.png b/sprites/Player2.png deleted file mode 100644 index eb2c2f4..0000000 Binary files a/sprites/Player2.png and /dev/null differ diff --git a/sprites/Player_Sprite.png b/sprites/Player_Sprite.png deleted file mode 100644 index fc71c3c..0000000 Binary files a/sprites/Player_Sprite.png and /dev/null differ diff --git a/sprites/jack.png b/sprites/jack.png deleted file mode 100644 index 7d777d5..0000000 Binary files a/sprites/jack.png and /dev/null differ diff --git a/sprites/music.ogg b/sprites/music.ogg new file mode 100644 index 0000000..bb7ab71 Binary files /dev/null and b/sprites/music.ogg differ diff --git a/sprites/orb_blue.png b/sprites/orb_blue.png new file mode 100644 index 0000000..945eb2c Binary files /dev/null and b/sprites/orb_blue.png differ diff --git a/sprites/orb_purple.png b/sprites/orb_purple.png new file mode 100644 index 0000000..d5fa95b Binary files /dev/null and b/sprites/orb_purple.png differ diff --git a/sprites/orb_red.png b/sprites/orb_red.png new file mode 100644 index 0000000..7e5d41f Binary files /dev/null and b/sprites/orb_red.png differ diff --git a/sprites/portal/tile000.png b/sprites/portal/tile000.png deleted file mode 100644 index 745ec54..0000000 Binary files a/sprites/portal/tile000.png and /dev/null differ diff --git a/sprites/portal/tile001.png b/sprites/portal/tile001.png deleted file mode 100644 index a480301..0000000 Binary files a/sprites/portal/tile001.png and /dev/null differ diff --git a/sprites/portal/tile002.png b/sprites/portal/tile002.png deleted file mode 100644 index d6f459c..0000000 Binary files a/sprites/portal/tile002.png and /dev/null differ diff --git a/sprites/portal/tile003.png b/sprites/portal/tile003.png deleted file mode 100644 index 2cd4481..0000000 Binary files a/sprites/portal/tile003.png and /dev/null differ diff --git a/sprites/portal/tile004.png b/sprites/portal/tile004.png deleted file mode 100644 index e932089..0000000 Binary files a/sprites/portal/tile004.png and /dev/null differ diff --git a/sprites/portal/tile005.png b/sprites/portal/tile005.png deleted file mode 100644 index 592527d..0000000 Binary files a/sprites/portal/tile005.png and /dev/null differ diff --git a/sprites/portal/tile006.png b/sprites/portal/tile006.png deleted file mode 100644 index bf6d313..0000000 Binary files a/sprites/portal/tile006.png and /dev/null differ diff --git a/sprites/portal/tile007.png b/sprites/portal/tile007.png deleted file mode 100644 index 6aa410b..0000000 Binary files a/sprites/portal/tile007.png and /dev/null differ diff --git a/sprites/portal/tile008.png b/sprites/portal/tile008.png deleted file mode 100644 index 805672e..0000000 Binary files a/sprites/portal/tile008.png and /dev/null differ diff --git a/sprites/portal/tile009.png b/sprites/portal/tile009.png deleted file mode 100644 index 8c14037..0000000 Binary files a/sprites/portal/tile009.png and /dev/null differ diff --git a/sprites/portal/tile010.png b/sprites/portal/tile010.png deleted file mode 100644 index 75f885a..0000000 Binary files a/sprites/portal/tile010.png and /dev/null differ diff --git a/sprites/portal/tile011.png b/sprites/portal/tile011.png deleted file mode 100644 index 1d281d6..0000000 Binary files a/sprites/portal/tile011.png and /dev/null differ diff --git a/sprites/portal/tile012.png b/sprites/portal/tile012.png deleted file mode 100644 index cb63f0b..0000000 Binary files a/sprites/portal/tile012.png and /dev/null differ diff --git a/sprites/portal/tile013.png b/sprites/portal/tile013.png deleted file mode 100644 index fb5de3d..0000000 Binary files a/sprites/portal/tile013.png and /dev/null differ diff --git a/sprites/portal/tile014.png b/sprites/portal/tile014.png deleted file mode 100644 index 7992f6a..0000000 Binary files a/sprites/portal/tile014.png and /dev/null differ diff --git a/sprites/portal/tile015.png b/sprites/portal/tile015.png deleted file mode 100644 index ee6ede1..0000000 Binary files a/sprites/portal/tile015.png and /dev/null differ