You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
5.5 KiB

"""
ICE WALKER GAME RUNNER
The main file that runs the game itself
"""
import objects
import json
import pyxel
import pathlib
CELL_SIZE = 8
GRID_X = 11
GRID_Y = 6
WIN_X = CELL_SIZE*GRID_X
WIN_Y = CELL_SIZE*GRID_Y
def load_file_json(lvl: int) -> list:
"""
:param lvl: (int) The id of the level to load
:return: (list) The loaded level from the file
Reads the corresponding level file and returns its loaded content
"""
file = open(f"lvl/{lvl}.json", "r", encoding="utf-8")
decoder = json.JSONDecoder()
return decoder.decode(file.read())
def load_file(lvl: int) -> list:
"""
:param lvl: (int) The id of the level to load
:return: (list) The loaded level from the file
Reads the corresponding level file and returns its loaded content
"""
file = open(f"lvl_bin/{lvl}.dat", "rb")
content = file.read()
res = []
mem = []
for v in content:
if int(v) == 255:
res.append(mem)
mem = []
else:
mem.append(int(v))
return res
def can_load(lvl: int) -> bool:
"""
:param lvl: (int) The id of the file to check for
:return: (bool) Returns if the level file exists and can be loaded
Tests if a level can be loaded, returns the result as a boolean
"""
path = pathlib.Path(f"lvl_bin/{lvl}.dat")
return path.is_file()
class LevelManager:
"""
This class is responsible for handling game data
"""
def __init__(self):
self.current_level = 0
self.cache = []
def load_level(self, lvl: int):
"""
:param lvl: (int) The id of the level to load
Loads the specified level and stores it into the cache
"""
if can_load(lvl):
self.cache = load_file(lvl)
self.current_level = lvl
def load_collection_from_cache(self, collection: objects.Collection) -> objects.Player | None:
"""
:param collection: (Collection) The collection to load the objects into
:return: The player object created by this method
Loads the level elements using the loaded cache, returns the new player instance
"""
new_player = None
for y in range(len(self.cache)):
for x in range(len(self.cache[y])):
element_id = self.cache[y][x]
elt = objects.get_type_from_id(element_id)
if elt:
new = elt()
new.position = objects.V2(x, y)
collection.add(new)
if element_id == 3:
new_player = new
return new_player
class Game:
"""
This class manages the game runtime
"""
def __init__(self):
self.level = None # An instance of the LevelManager class
self.main_collection = None # An instance of Collection, usually the main one
self.player = None # The current instance of the Player object
def _upd(self):
if self.player:
if pyxel.btnp(pyxel.KEY_R): # Reset the current level
self.main_collection.clear_all()
self.player = self.level.load_collection_from_cache(self.main_collection)
direction = objects.V2()
if pyxel.btnp(pyxel.KEY_Z): # Determine move direction
direction.Y = -1
elif pyxel.btnp(pyxel.KEY_S):
direction.Y = 1
elif pyxel.btnp(pyxel.KEY_Q):
direction.X = -1
elif pyxel.btnp(pyxel.KEY_D):
direction.X = 1
if not direction.is_zero(): # Handles the actual movement and collisions
new_pos, colliders = self.main_collection.ray_cast(self.player.position, direction, self.player)
self.player.position = new_pos
for v in colliders:
v.touched(self.player)
if self.main_collection.exits == 0: # Handles when the level was cleared
self.level.load_level(self.level.current_level + 1)
self.main_collection.clear_all()
new_player = self.level.load_collection_from_cache(self.main_collection)
self.player = new_player
def _display(self):
pyxel.cls(0)
for v in self.main_collection.get_objects(): # Render all active objects
if isinstance(v, objects.MapObject):
v.draw()
elif isinstance(v, objects.Collection) and v.visible: # Render embedded collections, if visible
for embed_v in v.get_objects():
embed_v.draw()
def run(self, lvl_m: LevelManager, main_c: objects.Collection):
"""
:param lvl_m: (LevelManager) The instance of LevelManager to assign with the game instance
:param main_c: (Collection) The primary collection containing the entirety of the game
Initializes and runs the game
"""
self.level = lvl_m
self.main_collection = main_c
pyxel.init(WIN_X, WIN_Y, title="ice_walker")
pyxel.run(self._upd, self._display)
if __name__ == "__main__":
main_collection = objects.Collection()
level = LevelManager() # Load the first level of the game
level.load_level(1)
player = level.load_collection_from_cache(main_collection)
game = Game() # Initializes the game engine
game.player = player
game.run(level, main_collection)