Skip to content

Commit

Permalink
Merge branch 'main' into unstable-main
Browse files Browse the repository at this point in the history
  • Loading branch information
plbrault authored May 5, 2024
2 parents 8a7e280 + 892ab3f commit 01bed39
Show file tree
Hide file tree
Showing 64 changed files with 514 additions and 312 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pipenv run auto <script.py> [args]
pipenv run auto --help
```

See `automated_example.py` for more info on API.
See `automated_skeleton.py` for more info on API.

**Build web version without running:**

Expand Down
6 changes: 3 additions & 3 deletions automated_skeleton.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@
the list of events generated by the game objects (processes, pages, etc...)
and expects another list of action events to be returned
see `src/lib/event_manager.py` for more info on events generated
see `src/event_manager.py` for more info on events generated
This skeleton implementation keeps a duplicate state from the game,
it gets updated with each event and then calls the scheduler function
to generate events back to the game
"""
from dataclasses import dataclass
from dataclasses import dataclass, field

#
# A copy of the game's state
Expand Down Expand Up @@ -334,7 +334,7 @@ def schedule(self):
# it expects a callable `run_os`
#
# it receives a list of events generated from processes/pages
# see `src/lib/event_manager` for generated events
# see `src/event_manager.py` for generated events
#
# it should return a list of events to happen
#
Expand Down
44 changes: 10 additions & 34 deletions src/auto.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
"""Entrypoint to run game with automated script
"""
Entry point to run the game with an automated script.
This just runs the Game scene, with the difficulty and script
provided from the command line.
"""

import asyncio
from os import path
import sys
import argparse

import pygame

from engine.game_manager import GameManager
from engine.window_config import WindowConfig
from scenes.game import Game
from scene_manager import scene_manager
from game_info import TITLE
from window_size import WINDOW_SIZE
import difficulty_levels
Expand Down Expand Up @@ -117,38 +116,15 @@ def compile_auto_script(source_file):
source_filename, difficulty_config = parse_arguments()
compiled_script = compile_auto_script(source_filename)

pygame.init()
pygame.font.init()

screen = pygame.display.set_mode(WINDOW_SIZE)

icon = pygame.image.load(path.join('assets', 'icon.png'))
pygame.display.set_caption(TITLE)
pygame.display.set_icon(icon)

scenes = {}

game_scene = Game(screen, scenes, difficulty_config, compiled_script, True)
scenes['game'] = game_scene

game_scene.start()

clock = pygame.time.Clock()

FPS = 60

async def main():
game_manager = GameManager()
game_manager.window_config = WindowConfig(WINDOW_SIZE, TITLE, path.join('assets', 'icon.png'))

while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()

scene_manager.current_scene.update(scene_manager.current_scene.current_time, [])
scene_manager.current_scene.render()
game_scene = Game(difficulty_config, compiled_script, True)

clock.tick(FPS)
game_manager.add_scene(game_scene)
game_manager.startup_scene = game_scene

await asyncio.sleep(0)
await game_manager.play(ignore_events=True)

asyncio.run(main())
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 2 additions & 1 deletion src/lib/game_event_type.py → src/engine/game_event_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
GameEventType = Enum('GameEventType', [
'KEY_UP',
'MOUSE_LEFT_CLICK',
'MOUSE_LEFT_DRAG'
'MOUSE_LEFT_DRAG',
'QUIT'
])
138 changes: 138 additions & 0 deletions src/engine/game_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import asyncio
from typing import Union

import pygame

from engine.game_event import GameEvent
from engine.game_event_type import GameEventType
from engine.scene import Scene
from engine.scene_manager import SceneManager
from engine.window_config import WindowConfig


_LEFT_MOUSE_BUTTON = 1

class GameManager():
window_config: WindowConfig
fps = 60

@property
def startup_scene(self):
return self._startup_scene

@startup_scene.setter
def startup_scene(self, value : Union[Scene, str]):
if isinstance(value, Scene):
if not self._scene_manager.get_scene(value.name):
raise ValueError('Startup scene first needs to be added with `add_scene`.')
self._startup_scene = value
elif isinstance(value, str):
scene = not self._scene_manager.get_scene(value)
if scene is None:
raise ValueError('Startup scene first needs to be added with `add_scene`.')
self._startup_scene = scene

def __init__(self):
self._current_scene = None
self._scenes = None
self._screen = None
self._scene_manager = SceneManager()
self._startup_scene = None

self._mouse_down = False
self._shift_down = False

@property
def current_scene(self):
return self._current_scene

def _init_pygame(self):
pygame.init()
pygame.font.init()

def _init_screen(self):
if self.window_config is None:
raise ValueError('Property `window_config` needs to be set.')
self._screen = pygame.display.set_mode(self.window_config.size)
icon = pygame.image.load(self.window_config.icon_path)
pygame.display.set_caption(self.window_config.title)
pygame.display.set_icon(icon)
self._scene_manager.screen = self._screen

def add_scene(self, scene: Scene):
self._scene_manager.add_scene(scene)

def _get_events(self):
events = []
mouse_event_added = False
mouse_drag_event = None

for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN and event.button == _LEFT_MOUSE_BUTTON:
self._mouse_down = True
elif event.type == pygame.QUIT:
events.append(GameEvent(GameEventType.QUIT, {}))
elif event.type == pygame.MOUSEBUTTONUP and event.button == _LEFT_MOUSE_BUTTON:
self._mouse_down = False
if mouse_event_added and mouse_drag_event:
events.remove(mouse_drag_event)
mouse_event_added = False
mouse_drag_event = None
if not mouse_event_added:
events.append(
GameEvent(
GameEventType.MOUSE_LEFT_CLICK, {
'position': event.pos}))
mouse_event_added = True
elif event.type == pygame.KEYDOWN:
if pygame.key.name(event.key).endswith('shift'):
self._shift_down = True
elif event.type == pygame.KEYUP:
if pygame.key.name(event.key).endswith('shift'):
self._shift_down = False
events.append(
GameEvent(
GameEventType.KEY_UP, {
'key': pygame.key.name(
event.key), 'shift': self._shift_down}))
elif event.type == pygame.MOUSEMOTION and self._mouse_down and not mouse_event_added:
event = GameEvent(GameEventType.MOUSE_LEFT_DRAG, {'position': event.pos})
events.append(event)
mouse_event_added = True
mouse_drag_event = event
return events

async def _main_loop(self, ignore_events=False):
clock = pygame.time.Clock()

while True:
events = self._get_events()
for event in events:
if event.type == GameEventType.QUIT:
return

if ignore_events:
events = []

scene = self._scene_manager.current_scene

scene.update(self._scene_manager.current_scene.current_time, events)
if scene != self._scene_manager.current_scene:
scene = self._scene_manager.current_scene
self._scene_manager.current_scene.update(
self._scene_manager.current_scene.current_time, []
)

scene.render()

clock.tick(self.fps)

await asyncio.sleep(0)

async def play(self, ignore_events=False):
self._init_pygame()
self._init_screen()
if self.startup_scene is None:
raise ValueError('Property `startup_scene` needs to be set.')
self._scene_manager.start_scene(self.startup_scene)
await self._main_loop(ignore_events)
File renamed without changes.
File renamed without changes.
23 changes: 12 additions & 11 deletions src/lib/scene.py → src/engine/scene.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
from abc import ABC, abstractmethod

import pygame

from lib.ui.color import Color
from scene_manager import scene_manager
from ui.color import Color


class Scene(ABC):
def __init__(self, screen, scenes, background_color=Color.BLACK):
self._screen = screen
self._scenes = scenes
self._background_color = background_color
scene_manager = None
screen: pygame.Surface
background_color = Color.BLACK

def __init__(self, name):
self._name = name
self._is_started = False
self._scene_objects = []

def start(self):
scene_manager.start_scene(self)
@property
def name(self):
return self._name

@property
def current_time(self):
Expand All @@ -30,9 +31,9 @@ def update(self, current_time, events):
pass

def render(self):
self._screen.fill(self._background_color)
self.screen.fill(self.background_color)

for game_object in self._scene_objects:
game_object.render(self._screen)
game_object.render(self.screen)

pygame.display.flip()
43 changes: 43 additions & 0 deletions src/engine/scene_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from typing import Union

from pygame import Surface

from engine.scene import Scene

class SceneManager():
def __init__(self):
self._current_scene = None
self._scenes = {}
self._screen = None

@property
def current_scene(self):
return self._current_scene

@property
def screen(self):
return self._screen

@screen.setter
def screen(self, value: Surface):
self._screen = value
for scene in self._scenes.values():
scene.screen = value

def add_scene(self, scene: Scene):
self._scenes[scene.name] = scene
self._scenes[scene.name].scene_manager = self

def get_scene(self, scene_name: str):
if scene_name not in self._scenes:
return None
return self._scenes[scene_name]

def start_scene(self, scene: Union[Scene, str]):
scene_name = None
if isinstance(scene, Scene):
scene_name = scene.name
else:
scene_name = scene
self._scenes[scene_name].setup()
self._current_scene = self._scenes[scene_name]
7 changes: 7 additions & 0 deletions src/engine/window_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from dataclasses import dataclass

@dataclass
class WindowConfig:
size: tuple[int,int]
title: str
icon_path: str
File renamed without changes.
2 changes: 1 addition & 1 deletion src/game_objects/about_dialog.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from lib.game_object import GameObject
from engine.game_object import GameObject
from game_objects.button import Button
from game_objects.views.about_dialog_view import AboutDialogView

Expand Down
4 changes: 2 additions & 2 deletions src/game_objects/button.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from lib.game_event_type import GameEventType
from lib.game_object import GameObject
from engine.game_event_type import GameEventType
from engine.game_object import GameObject
from game_objects.views.button_view import ButtonView


Expand Down
2 changes: 1 addition & 1 deletion src/game_objects/cpu.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from lib.game_object import GameObject
from engine.game_object import GameObject
from game_objects.views.cpu_view import CpuView


Expand Down
8 changes: 5 additions & 3 deletions src/game_objects/custom_settings_dialog.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from lib.constants import (
from constants import (
MIN_CPU_COUNT, MAX_CPU_COUNT, MIN_PROCESSES_AT_STARTUP,
MAX_PROCESSES_AT_STARTUP, MIN_RAM_ROWS, MAX_RAM_ROWS
)
from lib.game_object import GameObject
from engine.game_object import GameObject
from difficulty_levels import default_difficulty
from game_objects.button import Button
from game_objects.option_selector import OptionSelector
Expand Down Expand Up @@ -74,7 +74,9 @@ def config(self):
0.05,
'io_probability': [
0, 0.01, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5
][self._io_probability_selector.selected_option_id]
][self._io_probability_selector.selected_option_id],
'graceful_termination_probability':
default_difficulty['config']['graceful_termination_probability'],
}
return config

Expand Down
2 changes: 1 addition & 1 deletion src/game_objects/difficulty_selection_label.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from lib.game_object import GameObject
from engine.game_object import GameObject
from game_objects.views.difficulty_selection_label_view import DifficultySelectionLabelView


Expand Down
2 changes: 1 addition & 1 deletion src/game_objects/game_over_dialog.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from lib.game_object import GameObject
from engine.game_object import GameObject
from game_objects.button import Button
from game_objects.views.game_over_dialog_view import GameOverDialogView

Expand Down
Loading

0 comments on commit 01bed39

Please sign in to comment.