mini-arcade-core 0.6.1__tar.gz → 0.7.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mini_arcade_core-0.6.1 → mini_arcade_core-0.7.4}/PKG-INFO +2 -1
- {mini_arcade_core-0.6.1 → mini_arcade_core-0.7.4}/pyproject.toml +2 -2
- {mini_arcade_core-0.6.1 → mini_arcade_core-0.7.4}/src/mini_arcade_core/__init__.py +3 -0
- mini_arcade_core-0.7.4/src/mini_arcade_core/backend.py +171 -0
- {mini_arcade_core-0.6.1 → mini_arcade_core-0.7.4}/src/mini_arcade_core/game.py +57 -1
- mini_arcade_core-0.7.4/src/mini_arcade_core/scene.py +95 -0
- mini_arcade_core-0.6.1/src/mini_arcade_core/backend.py +0 -75
- mini_arcade_core-0.6.1/src/mini_arcade_core/scene.py +0 -40
- {mini_arcade_core-0.6.1 → mini_arcade_core-0.7.4}/LICENSE +0 -0
- {mini_arcade_core-0.6.1 → mini_arcade_core-0.7.4}/README.md +0 -0
- {mini_arcade_core-0.6.1 → mini_arcade_core-0.7.4}/src/mini_arcade_core/entity.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mini-arcade-core
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.4
|
|
4
4
|
Summary: Tiny scene-based game loop core for small arcade games.
|
|
5
5
|
License: Copyright (c) 2025 Santiago Rincón
|
|
6
6
|
|
|
@@ -34,6 +34,7 @@ Provides-Extra: dev
|
|
|
34
34
|
Requires-Dist: black (>=24.10,<25.0) ; extra == "dev"
|
|
35
35
|
Requires-Dist: isort (>=5.13,<6.0) ; extra == "dev"
|
|
36
36
|
Requires-Dist: mypy (>=1.5,<2.0) ; extra == "dev"
|
|
37
|
+
Requires-Dist: pillow (<12)
|
|
37
38
|
Requires-Dist: pylint (>=3.3,<4.0) ; extra == "dev"
|
|
38
39
|
Requires-Dist: pytest (>=8.3,<9.0) ; extra == "dev"
|
|
39
40
|
Requires-Dist: pytest-cov (>=6.0,<7.0) ; extra == "dev"
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "mini-arcade-core"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.7.4"
|
|
8
8
|
description = "Tiny scene-based game loop core for small arcade games."
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Santiago Rincon", email = "rincores@gmail.com" },
|
|
@@ -12,7 +12,7 @@ authors = [
|
|
|
12
12
|
readme = "README.md"
|
|
13
13
|
license = { file = "LICENSE" }
|
|
14
14
|
requires-python = ">=3.9,<3.12"
|
|
15
|
-
dependencies = []
|
|
15
|
+
dependencies = ["pillow (<12)"]
|
|
16
16
|
|
|
17
17
|
[project.optional-dependencies]
|
|
18
18
|
dev = [
|
|
@@ -21,7 +21,10 @@ def run_game(initial_scene_cls: type[Scene], config: GameConfig | None = None):
|
|
|
21
21
|
Convenience helper to bootstrap and run a game with a single scene.
|
|
22
22
|
|
|
23
23
|
:param initial_scene_cls: The Scene subclass to instantiate as the initial scene.
|
|
24
|
+
:type initial_scene_cls: type[Scene]
|
|
25
|
+
|
|
24
26
|
:param config: Optional GameConfig to customize game settings.
|
|
27
|
+
:type config: GameConfig | None
|
|
25
28
|
"""
|
|
26
29
|
game = Game(config or GameConfig())
|
|
27
30
|
scene = initial_scene_cls(game)
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Backend interface for rendering and input.
|
|
3
|
+
This is the only part of the code that talks to SDL/pygame directly.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from enum import Enum, auto
|
|
10
|
+
from typing import Iterable, Protocol
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class EventType(Enum):
|
|
14
|
+
"""
|
|
15
|
+
High-level event types understood by the core.
|
|
16
|
+
|
|
17
|
+
:cvar UNKNOWN: Unknown/unhandled event.
|
|
18
|
+
:cvar QUIT: User requested to quit the game.
|
|
19
|
+
:cvar KEYDOWN: A key was pressed.
|
|
20
|
+
:cvar KEYUP: A key was released.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
UNKNOWN = auto()
|
|
24
|
+
QUIT = auto()
|
|
25
|
+
KEYDOWN = auto()
|
|
26
|
+
KEYUP = auto()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass(frozen=True)
|
|
30
|
+
class Event:
|
|
31
|
+
"""
|
|
32
|
+
Core event type.
|
|
33
|
+
|
|
34
|
+
For now we only care about:
|
|
35
|
+
- type: what happened
|
|
36
|
+
- key: integer key code (e.g. ESC = 27), or None if not applicable
|
|
37
|
+
|
|
38
|
+
:ivar type (EventType): The type of event.
|
|
39
|
+
:ivar key (int | None): The key code associated with the event, if any.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
type: EventType
|
|
43
|
+
key: int | None = None
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Backend(Protocol):
|
|
47
|
+
"""
|
|
48
|
+
Interface that any rendering/input backend must implement.
|
|
49
|
+
|
|
50
|
+
mini-arcade-core only talks to this protocol, never to SDL/pygame directly.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def init(self, width: int, height: int, title: str) -> None:
|
|
54
|
+
"""
|
|
55
|
+
Initialize the backend and open a window.
|
|
56
|
+
Should be called once before the main loop.
|
|
57
|
+
|
|
58
|
+
:param width: Width of the window in pixels.
|
|
59
|
+
:type width: int
|
|
60
|
+
|
|
61
|
+
:param height: Height of the window in pixels.
|
|
62
|
+
:type height: int
|
|
63
|
+
|
|
64
|
+
:param title: Title of the window.
|
|
65
|
+
:type title: str
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
def poll_events(self) -> Iterable[Event]:
|
|
69
|
+
"""
|
|
70
|
+
Return all pending events since last call.
|
|
71
|
+
Concrete backends will translate their native events into core Event objects.
|
|
72
|
+
|
|
73
|
+
:return: An iterable of Event objects.
|
|
74
|
+
:rtype: Iterable[Event]
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
def set_clear_color(self, r: int, g: int, b: int) -> None:
|
|
78
|
+
"""
|
|
79
|
+
Set the background/clear color used by begin_frame.
|
|
80
|
+
|
|
81
|
+
:param r: Red component (0-255).
|
|
82
|
+
:type r: int
|
|
83
|
+
|
|
84
|
+
:param g: Green component (0-255).
|
|
85
|
+
:type g: int
|
|
86
|
+
|
|
87
|
+
:param b: Blue component (0-255).
|
|
88
|
+
:type b: int
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
def begin_frame(self) -> None:
|
|
92
|
+
"""
|
|
93
|
+
Prepare for drawing a new frame (e.g. clear screen).
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
def end_frame(self) -> None:
|
|
97
|
+
"""
|
|
98
|
+
Present the frame to the user (swap buffers).
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
# Justification: Simple drawing API for now
|
|
102
|
+
# pylint: disable=too-many-arguments,too-many-positional-arguments
|
|
103
|
+
def draw_rect(
|
|
104
|
+
self,
|
|
105
|
+
x: int,
|
|
106
|
+
y: int,
|
|
107
|
+
w: int,
|
|
108
|
+
h: int,
|
|
109
|
+
color: tuple[int, int, int] = (255, 255, 255),
|
|
110
|
+
) -> None:
|
|
111
|
+
"""
|
|
112
|
+
Draw a filled rectangle in some default color.
|
|
113
|
+
We'll keep this minimal for now; later we can extend with colors/sprites.
|
|
114
|
+
|
|
115
|
+
:param x: X position of the rectangle's top-left corner.
|
|
116
|
+
:type x: int
|
|
117
|
+
|
|
118
|
+
:param y: Y position of the rectangle's top-left corner.
|
|
119
|
+
:type y: int
|
|
120
|
+
|
|
121
|
+
:param w: Width of the rectangle.
|
|
122
|
+
:type w: int
|
|
123
|
+
|
|
124
|
+
:param h: Height of the rectangle.
|
|
125
|
+
:type h: int
|
|
126
|
+
|
|
127
|
+
:param color: RGB color tuple.
|
|
128
|
+
:type color: tuple[int, int, int]
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
# pylint: enable=too-many-arguments,too-many-positional-arguments
|
|
132
|
+
|
|
133
|
+
def draw_text(
|
|
134
|
+
self,
|
|
135
|
+
x: int,
|
|
136
|
+
y: int,
|
|
137
|
+
text: str,
|
|
138
|
+
color: tuple[int, int, int] = (255, 255, 255),
|
|
139
|
+
) -> None:
|
|
140
|
+
"""
|
|
141
|
+
Draw text at the given position in a default font and color.
|
|
142
|
+
|
|
143
|
+
Backends may ignore advanced styling for now; this is just to render
|
|
144
|
+
simple labels like menu items, scores, etc.
|
|
145
|
+
|
|
146
|
+
:param x: X position of the text's top-left corner.
|
|
147
|
+
:type x: int
|
|
148
|
+
|
|
149
|
+
:param y: Y position of the text's top-left corner.
|
|
150
|
+
:type y: int
|
|
151
|
+
|
|
152
|
+
:param text: The text string to draw.
|
|
153
|
+
:type text: str
|
|
154
|
+
|
|
155
|
+
:param color: RGB color tuple.
|
|
156
|
+
:type color: tuple[int, int, int]
|
|
157
|
+
"""
|
|
158
|
+
|
|
159
|
+
def capture_frame(self, path: str | None = None) -> bytes | None:
|
|
160
|
+
"""
|
|
161
|
+
Capture the current frame.
|
|
162
|
+
If `path` is provided, save to that file (e.g. PNG).
|
|
163
|
+
Returns raw bytes (PNG) or None if unsupported.
|
|
164
|
+
|
|
165
|
+
:param path: Optional file path to save the screenshot.
|
|
166
|
+
:type path: str | None
|
|
167
|
+
|
|
168
|
+
:return: Raw image bytes if no path given, else None.
|
|
169
|
+
:rtype: bytes | None
|
|
170
|
+
"""
|
|
171
|
+
raise NotImplementedError
|
|
@@ -4,10 +4,15 @@ Game core module defining the Game class and configuration.
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
+
import os
|
|
7
8
|
from dataclasses import dataclass
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from pathlib import Path
|
|
8
11
|
from time import perf_counter, sleep
|
|
9
12
|
from typing import TYPE_CHECKING
|
|
10
13
|
|
|
14
|
+
from PIL import Image # type: ignore[import]
|
|
15
|
+
|
|
11
16
|
from .backend import Backend
|
|
12
17
|
|
|
13
18
|
if TYPE_CHECKING: # avoid runtime circular import
|
|
@@ -32,7 +37,7 @@ class GameConfig:
|
|
|
32
37
|
title: str = "Mini Arcade Game"
|
|
33
38
|
fps: int = 60
|
|
34
39
|
background_color: tuple[int, int, int] = (0, 0, 0)
|
|
35
|
-
backend:
|
|
40
|
+
backend: Backend | None = None
|
|
36
41
|
|
|
37
42
|
|
|
38
43
|
class Game:
|
|
@@ -84,6 +89,9 @@ class Game:
|
|
|
84
89
|
backend = self.backend
|
|
85
90
|
backend.init(self.config.width, self.config.height, self.config.title)
|
|
86
91
|
|
|
92
|
+
br, bg, bb = self.config.background_color
|
|
93
|
+
backend.set_clear_color(br, bg, bb)
|
|
94
|
+
|
|
87
95
|
self.change_scene(initial_scene)
|
|
88
96
|
|
|
89
97
|
self._running = True
|
|
@@ -113,3 +121,51 @@ class Game:
|
|
|
113
121
|
|
|
114
122
|
if self._current_scene is not None:
|
|
115
123
|
self._current_scene.on_exit()
|
|
124
|
+
|
|
125
|
+
@staticmethod
|
|
126
|
+
def _convert_bmp_to_image(bmp_path: str, out_path: str) -> bool:
|
|
127
|
+
"""
|
|
128
|
+
Convert a BMP file to another image format using Pillow.
|
|
129
|
+
|
|
130
|
+
:param bmp_path: Path to the input BMP file.
|
|
131
|
+
:type bmp_path: str
|
|
132
|
+
|
|
133
|
+
:param out_path: Path to the output image file.
|
|
134
|
+
:type out_path: str
|
|
135
|
+
|
|
136
|
+
:return: True if conversion was successful, False otherwise.
|
|
137
|
+
:rtype: bool
|
|
138
|
+
"""
|
|
139
|
+
try:
|
|
140
|
+
img = Image.open(bmp_path)
|
|
141
|
+
img.save(out_path) # Pillow chooses format from extension
|
|
142
|
+
return True
|
|
143
|
+
except Exception:
|
|
144
|
+
return False
|
|
145
|
+
|
|
146
|
+
def screenshot(
|
|
147
|
+
self, label: str | None = None, directory: str = "screenshots"
|
|
148
|
+
) -> str | None:
|
|
149
|
+
"""
|
|
150
|
+
Ask backend to save a screenshot. Returns the file path or None.
|
|
151
|
+
|
|
152
|
+
:param label: Optional label to include in the filename.
|
|
153
|
+
:type label: str | None
|
|
154
|
+
|
|
155
|
+
:param directory: Directory to save screenshots in.
|
|
156
|
+
:type directory: str
|
|
157
|
+
|
|
158
|
+
:return: The file path of the saved screenshot, or None on failure.
|
|
159
|
+
:rtype: str | None
|
|
160
|
+
"""
|
|
161
|
+
os.makedirs(directory, exist_ok=True)
|
|
162
|
+
stamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
163
|
+
label = label or "shot"
|
|
164
|
+
filename = f"{stamp}_{label}"
|
|
165
|
+
bmp_path = os.path.join(directory, f"{filename}.bmp")
|
|
166
|
+
|
|
167
|
+
if self.backend.capture_frame(bmp_path):
|
|
168
|
+
out_path = Path(directory) / f"{filename}.png"
|
|
169
|
+
self._convert_bmp_to_image(bmp_path, str(out_path))
|
|
170
|
+
return str(out_path)
|
|
171
|
+
return None
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base class for game scenes (states/screens).
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from abc import ABC, abstractmethod
|
|
8
|
+
from typing import Callable, List
|
|
9
|
+
|
|
10
|
+
from mini_arcade_core.backend import Backend
|
|
11
|
+
|
|
12
|
+
from .game import Game
|
|
13
|
+
|
|
14
|
+
OverlayFunc = Callable[[Backend], None]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Scene(ABC):
|
|
18
|
+
"""Base class for game scenes (states/screens)."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, game: Game):
|
|
21
|
+
"""
|
|
22
|
+
:param game: Reference to the main Game object.
|
|
23
|
+
:type game: Game
|
|
24
|
+
"""
|
|
25
|
+
self.game = game
|
|
26
|
+
# overlays drawn on top of the scene
|
|
27
|
+
self._overlays: List[OverlayFunc] = []
|
|
28
|
+
|
|
29
|
+
def add_overlay(self, overlay: OverlayFunc) -> None:
|
|
30
|
+
"""
|
|
31
|
+
Register an overlay (drawn every frame, after entities).
|
|
32
|
+
|
|
33
|
+
:param overlay: A callable that takes a Backend and draws on it.
|
|
34
|
+
:type overlay: OverlayFunc
|
|
35
|
+
"""
|
|
36
|
+
self._overlays.append(overlay)
|
|
37
|
+
|
|
38
|
+
def remove_overlay(self, overlay: OverlayFunc) -> None:
|
|
39
|
+
"""
|
|
40
|
+
Unregister a previously added overlay.
|
|
41
|
+
|
|
42
|
+
:param overlay: The overlay to remove.
|
|
43
|
+
:type overlay: OverlayFunc
|
|
44
|
+
"""
|
|
45
|
+
if overlay in self._overlays:
|
|
46
|
+
self._overlays.remove(overlay)
|
|
47
|
+
|
|
48
|
+
def clear_overlays(self) -> None:
|
|
49
|
+
"""Clear all registered overlays."""
|
|
50
|
+
self._overlays.clear()
|
|
51
|
+
|
|
52
|
+
def draw_overlays(self, surface: Backend) -> None:
|
|
53
|
+
"""
|
|
54
|
+
Call all overlays. Scenes should call this at the end of draw().
|
|
55
|
+
|
|
56
|
+
:param surface: The backend surface to draw on.
|
|
57
|
+
:type surface: Backend
|
|
58
|
+
"""
|
|
59
|
+
for overlay in self._overlays:
|
|
60
|
+
overlay(surface)
|
|
61
|
+
|
|
62
|
+
@abstractmethod
|
|
63
|
+
def on_enter(self):
|
|
64
|
+
"""Called when the scene becomes active."""
|
|
65
|
+
|
|
66
|
+
@abstractmethod
|
|
67
|
+
def on_exit(self):
|
|
68
|
+
"""Called when the scene is replaced."""
|
|
69
|
+
|
|
70
|
+
@abstractmethod
|
|
71
|
+
def handle_event(self, event: object):
|
|
72
|
+
"""
|
|
73
|
+
Handle input / events (e.g. pygame.Event).
|
|
74
|
+
|
|
75
|
+
:param event: The event to handle.
|
|
76
|
+
:type event: object
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
@abstractmethod
|
|
80
|
+
def update(self, dt: float):
|
|
81
|
+
"""
|
|
82
|
+
Update game logic. ``dt`` is the delta time in seconds.
|
|
83
|
+
|
|
84
|
+
:param dt: Time delta in seconds.
|
|
85
|
+
:type dt: float
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
@abstractmethod
|
|
89
|
+
def draw(self, surface: object):
|
|
90
|
+
"""
|
|
91
|
+
Render to the main surface.
|
|
92
|
+
|
|
93
|
+
:param surface: The backend surface to draw on.
|
|
94
|
+
:type surface: object
|
|
95
|
+
"""
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Backend interface for rendering and input.
|
|
3
|
-
This is the only part of the code that talks to SDL/pygame directly.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
from __future__ import annotations
|
|
7
|
-
|
|
8
|
-
from dataclasses import dataclass
|
|
9
|
-
from enum import Enum, auto
|
|
10
|
-
from typing import Iterable, Protocol
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class EventType(Enum):
|
|
14
|
-
"""High-level event types understood by the core."""
|
|
15
|
-
|
|
16
|
-
UNKNOWN = auto()
|
|
17
|
-
QUIT = auto()
|
|
18
|
-
KEYDOWN = auto()
|
|
19
|
-
KEYUP = auto()
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@dataclass(frozen=True)
|
|
23
|
-
class Event:
|
|
24
|
-
"""
|
|
25
|
-
Core event type.
|
|
26
|
-
|
|
27
|
-
For now we only care about:
|
|
28
|
-
- type: what happened
|
|
29
|
-
- key: integer key code (e.g. ESC = 27), or None if not applicable
|
|
30
|
-
|
|
31
|
-
:ivar type (EventType): The type of event.
|
|
32
|
-
:ivar key (int | None): The key code associated with the event, if any.
|
|
33
|
-
"""
|
|
34
|
-
|
|
35
|
-
type: EventType
|
|
36
|
-
key: int | None = None
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class Backend(Protocol):
|
|
40
|
-
"""
|
|
41
|
-
Interface that any rendering/input backend must implement.
|
|
42
|
-
|
|
43
|
-
mini-arcade-core only talks to this protocol, never to SDL/pygame directly.
|
|
44
|
-
"""
|
|
45
|
-
|
|
46
|
-
def init(self, width: int, height: int, title: str) -> None:
|
|
47
|
-
"""
|
|
48
|
-
Initialize the backend and open a window.
|
|
49
|
-
|
|
50
|
-
Should be called once before the main loop.
|
|
51
|
-
"""
|
|
52
|
-
|
|
53
|
-
def poll_events(self) -> Iterable[Event]:
|
|
54
|
-
"""
|
|
55
|
-
Return all pending events since last call.
|
|
56
|
-
|
|
57
|
-
Concrete backends will translate their native events into core Event objects.
|
|
58
|
-
"""
|
|
59
|
-
|
|
60
|
-
def begin_frame(self) -> None:
|
|
61
|
-
"""
|
|
62
|
-
Prepare for drawing a new frame (e.g. clear screen).
|
|
63
|
-
"""
|
|
64
|
-
|
|
65
|
-
def end_frame(self) -> None:
|
|
66
|
-
"""
|
|
67
|
-
Present the frame to the user (swap buffers).
|
|
68
|
-
"""
|
|
69
|
-
|
|
70
|
-
def draw_rect(self, x: int, y: int, w: int, h: int) -> None:
|
|
71
|
-
"""
|
|
72
|
-
Draw a filled rectangle in some default color.
|
|
73
|
-
|
|
74
|
-
We'll keep this minimal for now; later we can extend with colors/sprites.
|
|
75
|
-
"""
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Base class for game scenes (states/screens).
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
from __future__ import annotations
|
|
6
|
-
|
|
7
|
-
from abc import ABC, abstractmethod
|
|
8
|
-
|
|
9
|
-
from .game import Game
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class Scene(ABC):
|
|
13
|
-
"""Base class for game scenes (states/screens)."""
|
|
14
|
-
|
|
15
|
-
def __init__(self, game: Game):
|
|
16
|
-
"""
|
|
17
|
-
:param game: Reference to the main Game object.
|
|
18
|
-
:type game: Game
|
|
19
|
-
"""
|
|
20
|
-
self.game = game
|
|
21
|
-
|
|
22
|
-
@abstractmethod
|
|
23
|
-
def on_enter(self):
|
|
24
|
-
"""Called when the scene becomes active."""
|
|
25
|
-
|
|
26
|
-
@abstractmethod
|
|
27
|
-
def on_exit(self):
|
|
28
|
-
"""Called when the scene is replaced."""
|
|
29
|
-
|
|
30
|
-
@abstractmethod
|
|
31
|
-
def handle_event(self, event: object):
|
|
32
|
-
"""Handle input / events (e.g. pygame.Event)."""
|
|
33
|
-
|
|
34
|
-
@abstractmethod
|
|
35
|
-
def update(self, dt: float):
|
|
36
|
-
"""Update game logic. ``dt`` is the delta time in seconds."""
|
|
37
|
-
|
|
38
|
-
@abstractmethod
|
|
39
|
-
def draw(self, surface: object):
|
|
40
|
-
"""Render to the main surface."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|