Simple plateformer game playing
This commit is contained in:
+145
@@ -0,0 +1,145 @@
|
||||
"""
|
||||
Represents the main game class.
|
||||
This class is responsible for managing the game's logic.
|
||||
It offers to set a callback function that will be called when waiting for a player input.
|
||||
It provides the gameState object to access the current state of the game.
|
||||
It provides the Map object to access the map.
|
||||
It provides some stopGame conditions to stop the game like the max number of moves or the player score.
|
||||
It provides public methods to start, stop and reset the game.
|
||||
It provides public methods to change the current map.
|
||||
"""
|
||||
|
||||
from game.blocks.block import Block
|
||||
from game.gameState import GameState
|
||||
from game.map import Map
|
||||
from colorama import Style
|
||||
|
||||
|
||||
class Game:
|
||||
def __init__(self, map: Map, gameState: GameState):
|
||||
self.map = map
|
||||
self.gameState = gameState
|
||||
self.waitingForInputCallback = None
|
||||
|
||||
def set_waiting_for_input_callback(self, callback):
|
||||
self.waitingForInputCallback = callback
|
||||
|
||||
def set_position_update_callback(self, callback):
|
||||
self.positionUpdateCallback = callback
|
||||
|
||||
def _position_update(self):
|
||||
if self.positionUpdateCallback:
|
||||
self.positionUpdateCallback()
|
||||
|
||||
def start_game(self):
|
||||
self.gameState.set_stop_game(False)
|
||||
|
||||
# Spawn the player at the spawn point
|
||||
spawn_point_position = self.map.get_first_block_type_position('spawn_point')
|
||||
if spawn_point_position is None:
|
||||
raise ValueError("No spawn point found in the map.")
|
||||
self.gameState.set_player_position(spawn_point_position)
|
||||
|
||||
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()
|
||||
|
||||
# Try to move the player according to his velocity
|
||||
block_at_velocity = self._get_block_at_velocity()
|
||||
if not block_at_velocity or not block_at_velocity.solid:
|
||||
velocity_position = self.get_position_at_velocity() # TODO : optimize
|
||||
if velocity_position:
|
||||
self.gameState.set_player_position(velocity_position)
|
||||
if block_at_velocity:
|
||||
block_at_velocity.on_collision(self.gameState) # Do something when the player is on the block, like add score or stop the game
|
||||
# Check if the player is on a solid block
|
||||
player_position = self.gameState.get_player_position()
|
||||
block_at_player_position = self.map.get_block_at(player_position[0], player_position[1] + 1)
|
||||
if block_at_player_position and block_at_player_position.solid:
|
||||
self.gameState.set_player_velocity(-1) # Stop the player from falling
|
||||
|
||||
self._update_player_velocity()
|
||||
|
||||
|
||||
def _update_player_velocity(self):
|
||||
current_velocity = self.gameState.playerVelocity
|
||||
if current_velocity == -1: # If no velocity, then the player is not moving, so we don't need to update the velocity
|
||||
return
|
||||
|
||||
if current_velocity == "down": # Falling straight down → Still falling except if the player is on a block
|
||||
if not self._get_block_at_velocity() == None and self._get_block_at_velocity().solid: # If block at where the player is going is solid, then the player will stop falling
|
||||
self.gameState.set_player_velocity(-1)
|
||||
return
|
||||
|
||||
if current_velocity is "up": # Going up → Going down
|
||||
self.gameState.set_player_velocity("down")
|
||||
return
|
||||
|
||||
if current_velocity in ["left_down", "right_down"]:
|
||||
self.gameState.set_player_velocity("down")
|
||||
return
|
||||
|
||||
if current_velocity in ["left", "right"]:
|
||||
self.gameState.set_player_velocity(current_velocity + "_down")
|
||||
block_at_velocity = self._get_block_at_velocity()
|
||||
if not block_at_velocity == None and block_at_velocity.solid: # If block at where the player is going is solid, then the player will fall down
|
||||
self.gameState.set_player_velocity("down")
|
||||
return
|
||||
|
||||
if current_velocity in ["left_up", "right_up"]:
|
||||
self.gameState.set_player_velocity(current_velocity.replace("_up", "_down"))
|
||||
block_at_velocity = self._get_block_at_velocity()
|
||||
if not block_at_velocity == None and block_at_velocity.solid: # If block at where the player is going is solid, then the player will fall down
|
||||
self.gameState.set_player_velocity("down")
|
||||
return
|
||||
|
||||
def get_position_at_velocity(self) -> tuple | None:
|
||||
player_position = self.gameState.get_player_position()
|
||||
current_velocity = self.gameState.playerVelocity
|
||||
|
||||
if current_velocity == -1:
|
||||
return None
|
||||
|
||||
if current_velocity == "down":
|
||||
return (player_position[0], player_position[1] + 1)
|
||||
|
||||
if current_velocity == "left_down":
|
||||
return (player_position[0] - 1, player_position[1] + 1)
|
||||
|
||||
if current_velocity == "right_down":
|
||||
return (player_position[0] + 1, player_position[1] + 1)
|
||||
|
||||
if current_velocity == "left":
|
||||
return (player_position[0] - 1, player_position[1])
|
||||
|
||||
if current_velocity == "right":
|
||||
return (player_position[0] + 1, player_position[1])
|
||||
|
||||
if current_velocity == "left_up":
|
||||
return (player_position[0] - 1, player_position[1] - 1)
|
||||
|
||||
if current_velocity == "right_up":
|
||||
return (player_position[0] + 1, player_position[1] - 1)
|
||||
|
||||
return None
|
||||
|
||||
def _get_block_at_velocity(self) -> Block | None:
|
||||
position_at_velocity = self.get_position_at_velocity()
|
||||
if position_at_velocity is None:
|
||||
return None
|
||||
return self.map.get_block_at(position_at_velocity[0], position_at_velocity[1])
|
||||
|
||||
def stop_game(self):
|
||||
self.gameState.set_stop_game(True)
|
||||
|
||||
def to_string(self):
|
||||
"""
|
||||
Returns a string representation of the game state and map with player position.
|
||||
"""
|
||||
player_position = self.gameState.get_player_position()
|
||||
map_string_dict = self.map.to_string_dict()
|
||||
map_string_dict[player_position[1]][player_position[0]] = f'{Style.BRIGHT}🦧'
|
||||
return '\n'.join([''.join(character + Style.RESET_ALL for character in row) for row in map_string_dict])
|
||||
Reference in New Issue
Block a user