sep-pm-platformer/project/level/elements/LoadedLevel.py

104 lines
4.0 KiB
Python

from typing import Optional
from level.Level import Level
from level.elements.dynamic.BouncingBallLevelElement import BouncingBallLevelElement
from level.elements.dynamic.PushableBoxLevelElement import PushableBoxLevelElement
from level.elements.static.SpikeLevelElement import SpikeLevelElement
from level.elements.static.ButtonInputLevelElement import ButtonInputLevelElement
from level.elements.static.GateReceiverLevelElement import GateReceiverLevelElement
from level.elements.LevelElement import LevelElement
from level.elements.static.LeverInputLevelElement import LeverInputLevelElement
from level.elements.static.SimpleBlockLevelElement import SimpleBlockLevelElement
from level.elements.static.UnknownTileLevelElement import UnknownTileLevelElement
from physics import ConstantsParser
from physics.SpriteManager import SpriteManager, DrawLayers
from sprite.SpritesheetManager import SpritesheetManager
TILES = {
'#': SimpleBlockLevelElement,
'+': SimpleBlockLevelElement,
'-': SimpleBlockLevelElement,
'l': SimpleBlockLevelElement,
'r': SimpleBlockLevelElement,
'~': SimpleBlockLevelElement,
'|': SimpleBlockLevelElement,
'P': ButtonInputLevelElement,
'L': LeverInputLevelElement,
'G': GateReceiverLevelElement,
'M': PushableBoxLevelElement,
'q': BouncingBallLevelElement,
'S': SpikeLevelElement,
's': SpikeLevelElement,
'<': SpikeLevelElement,
'>': SpikeLevelElement
}
class LoadedLevel:
def __init__(self, sprite_manager: SpriteManager, spritesheet_manager: SpritesheetManager):
self.sprite_manager = sprite_manager
self.spritesheet_manager = spritesheet_manager
self.blocks = []
self.elements_by_id: dict[str, LevelElement] = {}
def load_level(self, level: Level):
for row_number, row in enumerate(level.tiles):
for tile_number, tile in enumerate(row):
world_position = (tile_number, row_number)
position = (tile_number * ConstantsParser.CONFIG.block_size[0],
row_number * ConstantsParser.CONFIG.block_size[1])
tile['world_position'] = world_position
tile['position'] = position
name = tile['name']
element = None
if name in TILES:
element = TILES[name](tile, self)
elif not name == '':
print(f"Unknown tile at {position}: {name}")
element = UnknownTileLevelElement(tile, self)
if element:
self.blocks.append(element)
self.sprite_manager.add_ui_element(DrawLayers.OBJECTS, element)
element.load(self.sprite_manager, self.spritesheet_manager, level)
self.elements_by_id[element.id] = element
if isinstance(element, SimpleBlockLevelElement):
if self.is_surrounded_by_blocks(world_position, level.tiles):
element.is_collider = False
element.register_collisions = False
# self.sprite_manager.remove_ui_element(element)
def get_element_by_id(self, search_id: str) -> Optional[LevelElement]:
if search_id in self.elements_by_id:
return self.elements_by_id[search_id]
return None
def is_surrounded_by_blocks(self, position, tiles):
for i in range(-1, 2):
for j in range(-1, 2):
if i == 0 and j == 0:
continue
if position[0] + i < 0 or position[0] + i >= len(tiles[0]):
continue
if position[1] + j < 0 or position[1] + j >= len(tiles):
continue
tile = tiles[position[1] + j][position[0] + i]
if not tile['name'] in ['#', '+', '-', 'l', 'r', '~', '|']:
return False
return True
def destroy_level(self):
for block in self.blocks:
self.sprite_manager.remove_ui_element(block)
del self.blocks