pneuma-pygame/game/level/level.py

188 lines
7.2 KiB
Python
Raw Normal View History

import os
import pygame
2023-10-04 02:37:28 +00:00
from random import choice
from configs.system.window_config import TILESIZE
from utils.debug import debug
from utils.resource_loader import import_csv_layout, import_folder
from interface.ui import UI
from interface.upgrade import Upgrade
from entities.observer import Observer
from entities.player import Player
2023-10-04 02:37:28 +00:00
from entities.enemy import Enemy
from .terrain import Tile
from .camera import Camera
class Level:
def __init__(self):
# General Settings
self.game_paused = False
# Get display surface
self.display_surface = pygame.display.get_surface()
# Sprite Group setup
self.visible_sprites = Camera()
self.obstacle_sprites = pygame.sprite.Group()
self.attack_sprites = pygame.sprite.Group()
self.attackable_sprites = pygame.sprite.Group()
# Sprite setup and entity generation
self.create_map()
# UI setup
self.ui = UI()
2023-11-13 12:34:22 +00:00
# self.upgrade = Upgrade(self.player)
2023-10-04 02:37:28 +00:00
self.get_players_enemies()
self.get_distance_direction()
def create_map(self):
script_dir = os.path.dirname(os.path.abspath(__file__))
asset_path = os.path.join(
script_dir, '../..', 'assets')
layouts = {
'boundary': import_csv_layout(f"{asset_path}/map/FloorBlocks.csv"),
'grass': import_csv_layout(f"{asset_path}/map/Grass.csv"),
'objects': import_csv_layout(f"{asset_path}/map/Objects.csv"),
'entities': import_csv_layout(f"{asset_path}/map/Entities.csv")
}
graphics = {
'grass': import_folder(f"{asset_path}/graphics/grass"),
'objects': import_folder(f"{asset_path}/graphics/objects")
}
for style, layout in layouts.items():
for row_index, row in enumerate(layout):
for col_index, col in enumerate(row):
if col != '-1':
x = col_index * TILESIZE
y = row_index * TILESIZE
if style == 'boundary':
Tile((x, y), [self.obstacle_sprites], 'invisible')
if style == 'grass':
random_grass_image = choice(graphics['grass'])
Tile((x, y), [self.visible_sprites, self.obstacle_sprites,
self.attackable_sprites], 'grass', random_grass_image)
if style == 'objects':
surf = graphics['objects'][int(col)]
Tile((x, y), [self.visible_sprites,
self.obstacle_sprites], 'object', surf)
if style == 'entities':
# The numbers represent their IDs in .csv files generated from TILED.
if col == '395':
self.observer = Observer(
(x, y), [self.visible_sprites])
2023-11-13 12:34:22 +00:00
elif col == '400':
# Player Generation
2023-11-13 12:34:22 +00:00
Player(
(x, y), [self.visible_sprites], self.obstacle_sprites, self.visible_sprites, self.attack_sprites, self.attackable_sprites, 'tank')
elif col == '401':
# Player Generation
Player(
(x, y), [self.visible_sprites], self.obstacle_sprites, self.visible_sprites, self.attack_sprites, self.attackable_sprites, 'warrior')
elif col == '402':
# Player Generation
Player(
(x, y), [self.visible_sprites], self.obstacle_sprites, self.visible_sprites, self.attack_sprites, self.attackable_sprites, 'mage')
else:
2023-10-04 02:37:28 +00:00
# Monster Generation
if col == '390':
monster_name = 'bamboo'
elif col == '391':
monster_name = 'spirit'
elif col == '392':
monster_name = 'raccoon'
else:
monster_name = 'squid'
Enemy(monster_name, (x, y), [
self.visible_sprites, self.attackable_sprites], self.visible_sprites, self.obstacle_sprites)
def get_players_enemies(self):
self.player_sprites = [sprite for sprite in self.visible_sprites.sprites(
) if hasattr(sprite, 'sprite_type') and sprite.sprite_type in ('player')]
self.enemy_sprites = [sprite for sprite in self.visible_sprites.sprites(
) if hasattr(sprite, 'sprite_type') and sprite.sprite_type in ('enemy')]
def get_distance_direction(self):
for player in self.player_sprites:
player.distance_direction_from_enemy = []
for enemy in self.enemy_sprites:
enemy.distance_direction_from_player = []
for player in self.player_sprites:
player_vector = pygame.math.Vector2(player.rect.center)
for enemy in self.enemy_sprites:
enemy_vector = pygame.math.Vector2(enemy.rect.center)
distance = (player_vector - enemy_vector).magnitude()
if distance > 0:
direction = (player_vector - enemy_vector).normalize()
else:
direction = pygame.math.Vector2()
enemy.distance_direction_from_player.append(
(distance, direction, player))
player.distance_direction_from_enemy.append(
(distance, -direction, enemy))
def apply_damage_to_player(self):
for enemy in self.enemy_sprites:
for distance, _, player in enemy.distance_direction_from_player:
if distance < enemy.stats.attack_radius and player._input.combat.vulnerable:
player.stats.health -= enemy.stats.attack
player._input.combat.vulnerable = False
player._input.combat.hurt_time = pygame.time.get_ticks()
def toggle_menu(self):
self.game_paused = not self.game_paused
2023-10-04 02:37:28 +00:00
def run(self, who='observer'):
# Draw the game
2023-10-04 02:37:28 +00:00
if who == 'observer':
self.visible_sprites.custom_draw(self.observer)
self.ui.display(self.observer)
elif who == 'player':
self.visible_sprites.custom_draw(self.player)
self.ui.display(self.player)
2023-11-13 12:34:22 +00:00
debug('v0.6')
if not self.game_paused:
# Update the game
2023-10-04 02:37:28 +00:00
for player in self.player_sprites:
player.attack_logic()
self.get_players_enemies()
self.get_distance_direction()
self.apply_damage_to_player()
self.visible_sprites.update()
2023-10-04 02:37:28 +00:00
# self.visible_sprites.enemy_update(self.player)
# self.player_attack_logic()
else:
2023-11-13 12:34:22 +00:00
debug('PAUSED')
2023-11-13 12:34:22 +00:00
for player in self.player_sprites:
if player.stats.health <= 0:
player.kill()