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

155 lines
6.5 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.InvisibleElement import InvisibleElement
from level.elements.static.VacuumCleanerElement import VacuumCleanerElement
from level.elements.static.GoalDoorReceiverLevelElement import GoalDoorReceiverLevelElement
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 physics.sprites.PlayerSprite import PlayerSprite
from sprite.PositionScale import PositionScale
from sprite.SpritesheetManager import SpritesheetManager
TILES = {
'#': SimpleBlockLevelElement,
'+': SimpleBlockLevelElement,
'-': SimpleBlockLevelElement,
'l': SimpleBlockLevelElement,
'r': SimpleBlockLevelElement,
'~': SimpleBlockLevelElement,
'|': SimpleBlockLevelElement,
'P': ButtonInputLevelElement,
'L': LeverInputLevelElement,
'G': GateReceiverLevelElement,
'D': GoalDoorReceiverLevelElement,
'M': PushableBoxLevelElement,
'q': BouncingBallLevelElement,
'S': SpikeLevelElement,
's': SpikeLevelElement,
'<': SpikeLevelElement,
'>': SpikeLevelElement,
'A': VacuumCleanerElement,
'i': InvisibleElement
}
BACK_LAYER = [
]
FRONT_LAYER = [
'M'
]
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] = {}
self.level_screen_manager = None
def load_level(self, level: Level):
# create a wall of InvisibleElement around the level left and right
# block_left = SimpleBlockLevelElement({'name': '#', 'position': (30, 300)}, self, self.level_screen_manager)
# block_left.load(self.sprite_manager, self.spritesheet_manager, level)
# self.blocks.append(block_left)
# self.sprite_manager.add_ui_element(DrawLayers.OBJECTS_BACK, block_left)
for i in range(0, 100):
block_left = InvisibleElement({'name': 'i', 'position': (-16, i * 32)}, self, self.level_screen_manager)
block_left.load(self.sprite_manager, self.spritesheet_manager, level)
self.blocks.append(block_left)
self.sprite_manager.add_ui_element(DrawLayers.OBJECTS_BACK, block_left)
for i in range(0, 100):
block_right = InvisibleElement({'name': 'i', 'position':
(ConstantsParser.CONFIG.block_size[0] * ConstantsParser.CONFIG.level_size[0] + 4, i * 32)},
self, self.level_screen_manager)
block_right.load(self.sprite_manager, self.spritesheet_manager, level)
self.blocks.append(block_right)
self.sprite_manager.add_ui_element(DrawLayers.OBJECTS_BACK, block_right)
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
layer = DrawLayers.OBJECTS
if name in TILES:
element = TILES[name](tile, self, self.level_screen_manager)
if name in BACK_LAYER:
layer = DrawLayers.OBJECTS_BACK
elif name in FRONT_LAYER:
layer = DrawLayers.OBJECTS_FRONT
elif name == 'C':
ghost_character = PlayerSprite(self.spritesheet_manager.get_sheet("ghost_character"))
ghost_character.position_scale = PositionScale((position[0], position[1]), (1, 1))
layer = DrawLayers.PLAYER
self.blocks.append(ghost_character)
self.sprite_manager.add_ui_element(layer, ghost_character)
elif not name == '':
print(f"Unknown tile at {position}: {name}")
element = UnknownTileLevelElement(tile, self , self.level_screen_manager)
if element:
self.blocks.append(element)
self.sprite_manager.add_ui_element(layer, 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
self.blocks = []