Spikes, better gameHandler, map width and height computed automatically & big peanut hard map

This commit is contained in:
2026-10-10 16:21:11 +02:00
parent 14a39b7154
commit 17f00ebca2
12 changed files with 131 additions and 37 deletions
+3 -1
View File
@@ -2,10 +2,12 @@ from .stoneBlock import StoneBlock
from .spawnPointBlock import SpawnPointBlock
from .finishBlock import FinishBlock
from .coinBlock import CoinBlock
from .spikesBlock import SpikesBlock
BLOCKS = [
StoneBlock,
SpawnPointBlock,
FinishBlock,
CoinBlock
CoinBlock,
SpikesBlock,
]
+1 -1
View File
@@ -16,8 +16,8 @@ class FinishBlock(Block):
return False
def on_collision(self, gameState: GameState):
gameState.set_stop_game(True)
gameState.set_game_won(True)
gameState.set_stop_game(True)
def to_string(self):
return "🏁"
+24
View File
@@ -0,0 +1,24 @@
import os
from game.blocks.block import Block
from game.gameState import GameState
class SpikesBlock(Block):
@property
def character(self):
return '^'
@property
def type(self):
return 'spikes'
@property
def solid(self):
return False
def on_collision(self, gameState: GameState):
gameState.set_game_won(False)
gameState.set_stop_game(True)
def to_string(self):
return "🔥"
+3 -2
View File
@@ -44,10 +44,9 @@ class Game:
if spawn_point_position is None:
raise ValueError("No spawn point found in the map.")
self.gameState.set_player_position(spawn_point_position)
self._position_update()
while not self.gameState.stopGame:
self._position_update() # Update the screen for example
if self.gameState.playerVelocity == -1 and self.waitingForInputCallback:
self.gameState.set_player_velocity(self.waitingForInputCallback())
self.gameState.add_move_count()
@@ -70,6 +69,8 @@ class Game:
self._update_player_velocity()
self._position_update() # Update the screen for example
if self.gameStopCallback and self.gameStopCallback(self.gameState):
self.gameState.set_stop_game(True)
break
+10 -6
View File
@@ -1,12 +1,14 @@
from abc import abstractmethod
from game.game import Game
class GameHandler:
def __init__(self, game: Game):
self.game = game
self.game.set_waiting_for_input_callback(self.on_input_request)
self.game.set_position_update_callback(self.on_position_update)
def __init__(self):
pass
@abstractmethod
def run(self) -> None:
pass
@abstractmethod
def on_position_update(self) -> None:
@@ -14,4 +16,6 @@ class GameHandler:
@abstractmethod
def on_input_request(self) -> str:
pass
pass
+39 -5
View File
@@ -1,14 +1,48 @@
from time import sleep
from game.game import Game
from game.handlers.gameHandler import GameHandler
from game.handlers.gameHandler import GameHandler
from game.game import Game
from game.gameState import GameState
from game.mapReader import MapReader
from game.mapSet import MapSet
class UserPlayerGameHandler(GameHandler):
KEYBOARD_INPUTS = ["w", "q", "a", "z", "e", "d", "c"]
def __init__(self, game: Game):
super().__init__(game)
def __init__(self):
super().__init__()
self.mapReader = MapReader()
self.mapSet = MapSet(self.mapReader, self.mapReader.get_map_names())
self.map = self._choose_map()
self.gameState = GameState()
self.game = Game(self.map, self.gameState)
self.game.set_waiting_for_input_callback(self.on_input_request)
self.game.set_position_update_callback(self.on_position_update)
def _choose_map(self):
"""
Prompt the user to choose a map from the available maps
"""
print("\nAvailable maps:")
for i, map_name in enumerate(self.mapReader.get_map_names()):
print(f"{i + 1}. {map_name.replace("_", " ").title()}")
while True:
try:
choice = int(input("Choose a map by number: ")) - 1
if 0 <= choice < len(self.mapReader.get_map_names()):
return self.mapSet.get_map(choice)
else:
print("Invalid choice. Please try again.")
except ValueError:
print("Invalid input. Please enter a number.")
def run(self) -> None:
"""
Run the game loop
"""
self.game.start_game()
print("Game over : You " + ("Won!" if self.game.gameState.gameWon else "Lost!"))
def on_position_update(self) -> None:
"""
+2 -2
View File
@@ -13,11 +13,11 @@ from game.blocks.block import Block
class Map:
def __init__(self, map_data: dict):
self.name = map_data.get('name', 'Unknown')
self.width = int(map_data.get('width', 0))
self.height = int(map_data.get('height', 0))
self.difficulty = float(map_data.get('difficulty', 0.0))
self.min_moves = map_data.get('min_moves', None)
self.layout = map_data.get('layout', [])
self.width = max(len(row) for row in self.layout) if self.layout else 0
self.height = len(self.layout) if self.layout else 0
def get_block_at(self, x, y) -> Block | None:
if 0 <= x < self.width and 0 <= y < self.height:
+13 -9
View File
@@ -27,13 +27,13 @@ class MapReader:
with open(map_path, 'rb') as f:
config = tomllib.load(f)
layout = config.get('layout', '')
map_data = {
'name': map_name,
'width': config.get('width', 0),
'height': config.get('height', 0),
'difficulty': config.get('difficulty', 0.0),
'layout': self._parse_layout(config.get('layout', ''))
'layout': self._parse_layout(layout)
}
if config.get('min_moves') is not None:
@@ -48,16 +48,20 @@ class MapReader:
def _parse_layout(self, mapString):
# Takes the blocks and translates their characters into the corresponding block objects.
block_characters_mapping = self._get_block_characters_mapping()
# Makes sure tthe width is consistent across all rows by padding with None if necessary.
block_mapping = self._get_block_characters_mapping()
layout = []
for line in mapString.strip().splitlines():
for line in mapString.splitlines():
row = []
for char in line:
block_class = block_characters_mapping.get(char)
block_class = block_mapping.get(char)
if block_class:
row.append(block_class())
else:
row.append(None)
row.append(None) # Unknown character, treat as empty space
layout.append(row)
return layout
max_width = max(len(row) for row in layout)
for row in layout:
while len(row) < max_width:
row.append(None) # Pad with None to ensure consistent width
return layout
+6
View File
@@ -10,6 +10,12 @@ class MapSet:
self.mapReader = mapReader
self.maps = [self.mapReader.read_map(name) for name in mapNames]
def get_map_by_name(self, name: str):
for map in self.maps:
if map.name == name:
return map
raise ValueError(f"Map with name '{name}' not found in the MapSet.")
def get_map(self, index: int):
if index < 0 or index >= len(self.maps):
raise IndexError("Map index out of range.")