Skip to content
Snippets Groups Projects
world.py 4.21 KiB
"""This module contains the World class."""
import pygame as pg
from turret import Turret
from enemy import Zombie
import sound


class World:
    """Class for the world object."""
    def __init__(self):
        """Initializes the world object."""
        # Constants
        BLACK = (0, 0, 0)
        WHITE = (255, 255, 255)
        self.window_resolution = (1920, 1080)

        self.waypoints = (
            ( 175,    0),
            ( 180,  425),
            ( 830,  440),
            ( 830, 1040),
            ( 175, 1040),
            ( 175,  690),
            (1680,  690),
            (1685,  220)
        )

        # Pygame initialization
        pg.init()
        self.window = pg.display.set_mode(self.window_resolution, pg.FULLSCREEN | pg.SCALED)
        self.window.fill(BLACK)
        
        self.texture_path = 'assets/images/test_map.png'
        self.texture = pg.image.load(self.texture_path).convert_alpha()

        # Game state variables
        self.current_round = 0
        self.round_active = False
        self.request_to_start_round = False
        self.round_start_time = 0
        self.round_spawn_times = []

        # Game entities
        self.enemies = []
        self.turrets = []
        self.active_tower = 0
        #Groups
        self.turret_group = []

        # Player stats
        self.money = 1000
        self.player_health = 100
    
    def generate_enemy_spawn_times(self, round_index: int) -> list[tuple[any, int]]:
        """
        Returns a list of tuples containing enemy object and time of spawn.

        Parameters:
            round_index:
                The index determines which enemies are spawned.

        Returns:
            enemies:
                Tuple of enemy object and time of spawn. 
        """
        enemies = []
        if round_index <= 10:
            for i in range(round_index * 5):
                enemies.append((Zombie(100 + 10 * 1.05 ** round_index), 8 * i / (round_index + 3)))
        return enemies

    def turret_spawn(self, mouse_pos):
        temp_turret = Turret(self.texture , mouse_pos)
        if self.active_tower == 0 or self.money < temp_turret.cost:
            return None
        collision = False
        if mouse_pos[0] < 1920 and mouse_pos[1] < 1080:
            collision = any(temp_turret.rect.colliderect(sprite.rect) for sprite in self.turret_group)
            if not collision:
                self.turret_group.append(temp_turret)
                sound.turret_placement.play()
                self.money -= temp_turret.cost
    
    def turret_attacks(self, dt: float):
        for turret in self.turret_group:
            # Find the nearest enemy for the turret
            target = turret.find_nearest_enemy(self.enemies)

            if target is not None:
                # Rotate the turret to face the targets
                turret.face_at_the_current_target(target)
                turret.time_since_last_attack += dt

                # Attack the target if the cooldown has passed
                if turret.time_since_last_attack >= turret.attack_cooldown:
                    target.hp -= turret.attack_damage
                    sound.bullet_sound.play()

                    # Check if the target is dead
                    if target.hp <= 0:
                        self.enemies.remove(target)
                        self.money += target.reward_on_death
                        sound.play_zombie_groan()
                        sound.coin_sound.play()

                    # Attack timer
                    turret.time_since_last_attack = 0


    def draw(self):
        """Draws the world elements to the passed surface."""
        self.window.blit(self.texture, (0, 0))
        for enemy in self.enemies:
            enemy.draw(self.window, self.waypoints)
        
        for turret in self.turret_group:
            turret.draw(self.window)

    def draw_debug(self):
        """
        Draws debug information about the world.
        
        Draws lines between the waypoints.
        """
        for i in range(len(self.waypoints) - 1):
            pg.draw.line(self.window, (0, 255, 0),
                         self.waypoints[i], self.waypoints[i + 1], 5)
        for point in self.waypoints:
            pg.draw.circle(self.window, (255, 0, 0), point, 10)