A state machine for organizing different in-game screens in python.
This library supports python versions 3.8 - 3.14.
Create and activate a virtual environment in your workspace (optional) and run the following command-
pip install game_state
Note: This package does not have any dependancy on
pygame, hence you will need to install them separately on your own. This gives you the freedom to work withpygame,pygame-ceor any of it's forks.
This is an example of creating two screens. One displaying green colour and the other blue with a player.
import pygame
from game_state import State, StateManager
from game_state.utils import MISSING
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
speed = 200
pygame.init()
pygame.display.init()
pygame.display.set_caption("Game State Example")
class MyBaseState(State["MyBaseState"]):
screen: pygame.Surface = MISSING
class MainMenuState(MyBaseState, state_name="MainMenu"):
def process_event(self, event: pygame.event.Event) -> None:
if event.type == pygame.QUIT:
self.manager.is_running = False
if event.type == pygame.KEYDOWN and event.key == pygame.K_w:
self.manager.change_state("Game")
def process_update(self, *args: float) -> None:
self.screen.fill(GREEN)
pygame.display.update()
class GameState(MyBaseState, state_name="Game"):
def __init__(self) -> None:
self.player_x: float = 250.0
def process_event(self, event: pygame.event.Event) -> None:
if event.type == pygame.QUIT:
self.manager.is_running = False
if event.type == pygame.KEYDOWN and event.key == pygame.K_w:
self.manager.change_state("MainMenu")
def process_update(self, *args: float) -> None:
dt = args[0]
self.screen.fill(BLUE)
# Player movement-
pressed = pygame.key.get_pressed()
if pressed[pygame.K_a]:
self.player_x -= speed * dt
if pressed[pygame.K_d]:
self.player_x += speed * dt
pygame.draw.rect(
self.screen,
"red",
(
self.player_x,
100,
50,
50,
),
)
pygame.display.update()
def main() -> None:
screen = pygame.display.set_mode((500, 600))
state_manager = StateManager[MyBaseState](
bound_state_type=MyBaseState, screen=screen
)
state_manager.load_states(MainMenuState, GameState)
state_manager.change_state("MainMenu")
clock = pygame.time.Clock()
while state_manager.is_running:
dt = clock.tick(60) / 1000
for event in pygame.event.get():
state_manager.current_state.process_event(event)
state_manager.current_state.process_update(dt)
if __name__ == "__main__":
main()You can have a look at the game state guide for a more detailed explaination.
- Guide & API Reference: https://game-state.readthedocs.io/en/stable/
- PyPI Page: https://pypi.org/project/game-state/
- Github Page: https://github.com/Jiggly-Balls/game-state/