Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,12 @@


# import Pygame specific objects, functions and functionality
from src.GUI.gameloop import GUI


class Launcher:
def __init__(self) -> None:
pass
from src.game_manager import GameStateManager


if __name__ == "__main__":
# version choice is disabled for debugging reasons
game = GUI()
game = GameStateManager()
game.run()

# print(
Expand Down
5 changes: 4 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
"""Could be usefull if we ever make the decision to create a pip package for this project, as for now it is commented out."""
"""
Could be usefull if we ever make the decision to create a pip package for this project,
as for now it is commented out.
"""

# from setuptools import setup

Expand Down
Empty file removed src/GUI/__init__.py
Empty file.
151 changes: 0 additions & 151 deletions src/GUI/gameloop.py

This file was deleted.

Empty file removed src/__init__.py
Empty file.
86 changes: 86 additions & 0 deletions src/game_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
"""
main game loop
structure of the game, using a stack of states
"""


import sys
import pygame

from src.settings import SCREEN_WIDTH, SCREEN_HEIGHT, FPS

# import basestate for typehint
from src.states.base_state import BaseState
from src.states.game_running import GameRunning


class GameStateManager:
"""
Manages the main game loop and the structure of the game using a stack of states.

This class is responsible for:
- Initializing Pygame and setting up the main screen.
- Managing a stack of game states, allowing for seamless transitions (e.g., from gameplay to paused state).
- Handling Pygame events and delegating them to the active state.
- Running the main game loop with controlled frame rate.
"""
def __init__(self) -> None:

# init pygame
pygame.init()
self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("PySeas")

self.clock = pygame.Clock()
self.running = True
self.events: list[pygame.event.Event] = []
self.states_stack: list[BaseState] = []

# instanciate the initial state
self.states_stack.append(GameRunning(self))

def __str__(self) -> str:
"""
return a string representing the stack
e.g. : >MainMenu>GameRunning>Paused
"""
stack_repr:str = ""
for state in self.states_stack:
stack_repr += '>' + str(state)
return stack_repr

def enter_state(self, state: BaseState) -> None:
"""
append state to the stack
"""
self.states_stack.append(state)

def exit_state(self) -> BaseState:
"""
pop and return the last state
"""
if len(self.states_stack) == 0:
raise ValueError("the stack is empty")
return self.states_stack.pop()

def _handle_events(self):
self.events = pygame.event.get()
for event in self.events:
match event.type:
case pygame.QUIT:
pygame.quit()
sys.exit()

def run(self) -> None:
"""main loop of the game"""
while self.running:
self._handle_events()

# give the pygame events to each states
# to ensure that pygame.event.get() is only called once per frame
self.states_stack[-1].update(self.events)

self.states_stack[-1].render(self.screen)

# magic value, use a FPS const in settings or delta time
self.clock.tick(FPS)
File renamed without changes.
2 changes: 1 addition & 1 deletion src/GUI/inventory_gui.py → src/inventory_gui.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Dict, Tuple
import pygame
from src.GUI.inventory import Inventory
from src.inventory import Inventory


class InventoryGUI:
Expand Down
1 change: 1 addition & 0 deletions src/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

SCREEN_WIDTH, SCREEN_HEIGHT = 1280, 720
TILE_SIZE = 16
FPS = 60


if not getattr(pygame, "IS_CE", False):
Expand Down
4 changes: 2 additions & 2 deletions src/sprites.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pygame
from pygame import FRect
from src.settings import TILE_SIZE, SCREEN_HEIGHT, SCREEN_WIDTH
from src.GUI.inventory import Inventory
from src.inventory import Inventory


# class Entity(pygame.sprite.Sprite):
Expand Down Expand Up @@ -152,7 +152,7 @@ def __init__(
There is a known typing error related to missing type parameters for the generic type 'Group' in pygame.
You may see warnings like:
- src\\sprites.py:107: error: Missing type parameters for generic type 'Group' [type-arg]
- src\\GUI\\gameloop.py:45: error: Missing type parameters for generic type 'SpriteGroup' [type-arg]
- src\\GUI\\game_manager.py:45: error: Missing type parameters for generic type 'SpriteGroup' [type-arg]

These errors can be ignored for now, as they are related to type annotations in pygame's codebase.
"""
Expand Down
33 changes: 33 additions & 0 deletions src/states/base_state.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""
Represents a base example state in the game.
Each state must implement:
- `update`: A method that loops through and handles events.
- `render`: A method responsible for drawing the state on the given surface.
"""
from abc import ABC, abstractmethod
import pygame


class BaseState(ABC):
"""
using an abstract class to ensure each state has the right methods
"""
def __init__(self, game_state_manager) -> None:
self.game_state_manager = game_state_manager

def __str__(self):
return self.__class__.__name__

@abstractmethod
def update(self, events): # return self
"""
update current state
handle events
and return current state or another one
"""

@abstractmethod
def render(self, screen: pygame.Surface) -> None:
"""
render current state on a given surface
"""
Loading
Loading