pyguara 0.2.0__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.
- pyguara-0.2.0/.gitignore +181 -0
- pyguara-0.2.0/LICENSE +8 -0
- pyguara-0.2.0/PKG-INFO +167 -0
- pyguara-0.2.0/README.md +121 -0
- pyguara-0.2.0/pyguara/__init__.py +0 -0
- pyguara-0.2.0/pyguara/ai/ai_system.py +29 -0
- pyguara-0.2.0/pyguara/ai/blackboard.py +32 -0
- pyguara-0.2.0/pyguara/ai/components.py +76 -0
- pyguara-0.2.0/pyguara/ai/fsm.py +82 -0
- pyguara-0.2.0/pyguara/ai/pathfinding/astar.py +58 -0
- pyguara-0.2.0/pyguara/ai/pathfinding/core.py +29 -0
- pyguara-0.2.0/pyguara/ai/pathfinding/grid.py +72 -0
- pyguara-0.2.0/pyguara/ai/steering.py +55 -0
- pyguara-0.2.0/pyguara/app_scene.py +132 -0
- pyguara-0.2.0/pyguara/application/__init__.py +6 -0
- pyguara-0.2.0/pyguara/application/application.py +100 -0
- pyguara-0.2.0/pyguara/application/bootstrap.py +132 -0
- pyguara-0.2.0/pyguara/application/sandbox.py +116 -0
- pyguara-0.2.0/pyguara/audio/__init__.py +1 -0
- pyguara-0.2.0/pyguara/audio/audio_system.py +116 -0
- pyguara-0.2.0/pyguara/audio/backends/pygame/loaders.py +30 -0
- pyguara-0.2.0/pyguara/audio/backends/pygame/pygame_audio.py +185 -0
- pyguara-0.2.0/pyguara/audio/backends/pygame/types.py +37 -0
- pyguara-0.2.0/pyguara/audio/manager.py +248 -0
- pyguara-0.2.0/pyguara/common/components.py +316 -0
- pyguara-0.2.0/pyguara/common/constants.py +1 -0
- pyguara-0.2.0/pyguara/common/palette.py +43 -0
- pyguara-0.2.0/pyguara/common/types.py +311 -0
- pyguara-0.2.0/pyguara/config/__init__.py +14 -0
- pyguara-0.2.0/pyguara/config/events.py +39 -0
- pyguara-0.2.0/pyguara/config/manager.py +128 -0
- pyguara-0.2.0/pyguara/config/types.py +82 -0
- pyguara-0.2.0/pyguara/config/validation.py +76 -0
- pyguara-0.2.0/pyguara/di/__init__.py +34 -0
- pyguara-0.2.0/pyguara/di/container.py +369 -0
- pyguara-0.2.0/pyguara/di/decorators.py +56 -0
- pyguara-0.2.0/pyguara/di/exceptions.py +33 -0
- pyguara-0.2.0/pyguara/di/types.py +70 -0
- pyguara-0.2.0/pyguara/ecs/__init__.py +14 -0
- pyguara-0.2.0/pyguara/ecs/component.py +40 -0
- pyguara-0.2.0/pyguara/ecs/entity.py +158 -0
- pyguara-0.2.0/pyguara/ecs/manager.py +195 -0
- pyguara-0.2.0/pyguara/ecs/query_cache.py +197 -0
- pyguara-0.2.0/pyguara/editor/__init__.py +1 -0
- pyguara-0.2.0/pyguara/editor/drawers.py +187 -0
- pyguara-0.2.0/pyguara/editor/layer.py +165 -0
- pyguara-0.2.0/pyguara/editor/panels/assets.py +163 -0
- pyguara-0.2.0/pyguara/editor/panels/hierarchy.py +64 -0
- pyguara-0.2.0/pyguara/editor/panels/inspector.py +81 -0
- pyguara-0.2.0/pyguara/error/__init__.py +24 -0
- pyguara-0.2.0/pyguara/error/exceptions.py +107 -0
- pyguara-0.2.0/pyguara/error/handlers.py +110 -0
- pyguara-0.2.0/pyguara/error/types.py +27 -0
- pyguara-0.2.0/pyguara/events/__init__.py +1 -0
- pyguara-0.2.0/pyguara/events/dispatcher.py +161 -0
- pyguara-0.2.0/pyguara/events/input.py +50 -0
- pyguara-0.2.0/pyguara/events/lifecycle.py +31 -0
- pyguara-0.2.0/pyguara/events/protocols.py +92 -0
- pyguara-0.2.0/pyguara/events/types.py +40 -0
- pyguara-0.2.0/pyguara/events/window.py +20 -0
- pyguara-0.2.0/pyguara/graphics/__init__.py +1 -0
- pyguara-0.2.0/pyguara/graphics/animation_system.py +37 -0
- pyguara-0.2.0/pyguara/graphics/atlas.py +110 -0
- pyguara-0.2.0/pyguara/graphics/backends/headless_renderer.py +115 -0
- pyguara-0.2.0/pyguara/graphics/backends/pygame/loaders.py +27 -0
- pyguara-0.2.0/pyguara/graphics/backends/pygame/pygame_renderer.py +113 -0
- pyguara-0.2.0/pyguara/graphics/backends/pygame/pygame_window.py +75 -0
- pyguara-0.2.0/pyguara/graphics/backends/pygame/types.py +34 -0
- pyguara-0.2.0/pyguara/graphics/backends/pygame/ui_renderer.py +115 -0
- pyguara-0.2.0/pyguara/graphics/color.py +1 -0
- pyguara-0.2.0/pyguara/graphics/components/__init__.py +27 -0
- pyguara-0.2.0/pyguara/graphics/components/animation.py +312 -0
- pyguara-0.2.0/pyguara/graphics/components/camera.py +407 -0
- pyguara-0.2.0/pyguara/graphics/components/geometry.py +150 -0
- pyguara-0.2.0/pyguara/graphics/components/particles.py +387 -0
- pyguara-0.2.0/pyguara/graphics/components/sprite.py +32 -0
- pyguara-0.2.0/pyguara/graphics/pipeline/batch.py +99 -0
- pyguara-0.2.0/pyguara/graphics/pipeline/queue.py +37 -0
- pyguara-0.2.0/pyguara/graphics/pipeline/render_system.py +95 -0
- pyguara-0.2.0/pyguara/graphics/pipeline/viewport.py +147 -0
- pyguara-0.2.0/pyguara/graphics/protocols.py +318 -0
- pyguara-0.2.0/pyguara/graphics/spritesheet.py +79 -0
- pyguara-0.2.0/pyguara/graphics/types.py +66 -0
- pyguara-0.2.0/pyguara/graphics/window.py +80 -0
- pyguara-0.2.0/pyguara/input/__init__.py +21 -0
- pyguara-0.2.0/pyguara/input/binding.py +42 -0
- pyguara-0.2.0/pyguara/input/events.py +63 -0
- pyguara-0.2.0/pyguara/input/gamepad.py +358 -0
- pyguara-0.2.0/pyguara/input/keys.py +19 -0
- pyguara-0.2.0/pyguara/input/manager.py +196 -0
- pyguara-0.2.0/pyguara/input/types.py +114 -0
- pyguara-0.2.0/pyguara/log/__init__.py +19 -0
- pyguara-0.2.0/pyguara/log/events.py +31 -0
- pyguara-0.2.0/pyguara/log/handlers.py +75 -0
- pyguara-0.2.0/pyguara/log/logger.py +173 -0
- pyguara-0.2.0/pyguara/log/manager.py +68 -0
- pyguara-0.2.0/pyguara/log/types.py +30 -0
- pyguara-0.2.0/pyguara/persistence/manager.py +136 -0
- pyguara-0.2.0/pyguara/persistence/serializer.py +110 -0
- pyguara-0.2.0/pyguara/persistence/storage.py +99 -0
- pyguara-0.2.0/pyguara/persistence/types.py +77 -0
- pyguara-0.2.0/pyguara/physics/__init__.py +17 -0
- pyguara-0.2.0/pyguara/physics/backends/pymunk_impl.py +448 -0
- pyguara-0.2.0/pyguara/physics/collision_system.py +295 -0
- pyguara-0.2.0/pyguara/physics/components.py +63 -0
- pyguara-0.2.0/pyguara/physics/events.py +187 -0
- pyguara-0.2.0/pyguara/physics/joints.py +349 -0
- pyguara-0.2.0/pyguara/physics/materials.py +63 -0
- pyguara-0.2.0/pyguara/physics/physics_system.py +109 -0
- pyguara-0.2.0/pyguara/physics/protocols.py +138 -0
- pyguara-0.2.0/pyguara/physics/types.py +103 -0
- pyguara-0.2.0/pyguara/resources/data.py +69 -0
- pyguara-0.2.0/pyguara/resources/loader.py +43 -0
- pyguara-0.2.0/pyguara/resources/loaders/data_loader.py +40 -0
- pyguara-0.2.0/pyguara/resources/manager.py +368 -0
- pyguara-0.2.0/pyguara/resources/types.py +75 -0
- pyguara-0.2.0/pyguara/scene/base.py +83 -0
- pyguara-0.2.0/pyguara/scene/manager.py +55 -0
- pyguara-0.2.0/pyguara/scene/serializer.py +93 -0
- pyguara-0.2.0/pyguara/tools/base.py +80 -0
- pyguara-0.2.0/pyguara/tools/debugger.py +80 -0
- pyguara-0.2.0/pyguara/tools/event_monitor.py +83 -0
- pyguara-0.2.0/pyguara/tools/inspector.py +166 -0
- pyguara-0.2.0/pyguara/tools/manager.py +132 -0
- pyguara-0.2.0/pyguara/tools/performance.py +59 -0
- pyguara-0.2.0/pyguara/tools/shortcuts_panel.py +59 -0
- pyguara-0.2.0/pyguara/ui/__init__.py +27 -0
- pyguara-0.2.0/pyguara/ui/base.py +117 -0
- pyguara-0.2.0/pyguara/ui/components/__init__.py +27 -0
- pyguara-0.2.0/pyguara/ui/components/button.py +48 -0
- pyguara-0.2.0/pyguara/ui/components/canvas.py +29 -0
- pyguara-0.2.0/pyguara/ui/components/checkbox.py +60 -0
- pyguara-0.2.0/pyguara/ui/components/image.py +27 -0
- pyguara-0.2.0/pyguara/ui/components/label.py +35 -0
- pyguara-0.2.0/pyguara/ui/components/navbar.py +33 -0
- pyguara-0.2.0/pyguara/ui/components/panel.py +31 -0
- pyguara-0.2.0/pyguara/ui/components/progress_bar.py +36 -0
- pyguara-0.2.0/pyguara/ui/components/slider.py +84 -0
- pyguara-0.2.0/pyguara/ui/components/text.py +46 -0
- pyguara-0.2.0/pyguara/ui/components/text_input.py +77 -0
- pyguara-0.2.0/pyguara/ui/components/widget.py +25 -0
- pyguara-0.2.0/pyguara/ui/layout.py +87 -0
- pyguara-0.2.0/pyguara/ui/manager.py +58 -0
- pyguara-0.2.0/pyguara/ui/theme.py +37 -0
- pyguara-0.2.0/pyguara/ui/types.py +113 -0
- pyguara-0.2.0/pyproject.toml +289 -0
pyguara-0.2.0/.gitignore
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Unit test / coverage reports
|
|
36
|
+
htmlcov/
|
|
37
|
+
.tox/
|
|
38
|
+
.nox/
|
|
39
|
+
.coverage
|
|
40
|
+
.coverage.*
|
|
41
|
+
.cache
|
|
42
|
+
nosetests.xml
|
|
43
|
+
coverage.xml
|
|
44
|
+
*.cover
|
|
45
|
+
*.py,cover
|
|
46
|
+
.hypothesis/
|
|
47
|
+
.pytest_cache/
|
|
48
|
+
cover/
|
|
49
|
+
|
|
50
|
+
# Translations
|
|
51
|
+
*.mo
|
|
52
|
+
*.pot
|
|
53
|
+
|
|
54
|
+
# Django stuff:
|
|
55
|
+
*.log
|
|
56
|
+
local_settings.py
|
|
57
|
+
db.sqlite3
|
|
58
|
+
db.sqlite3-journal
|
|
59
|
+
|
|
60
|
+
# Flask stuff:
|
|
61
|
+
instance/
|
|
62
|
+
.webassets-cache
|
|
63
|
+
|
|
64
|
+
# Scrapy stuff:
|
|
65
|
+
.scrapy
|
|
66
|
+
|
|
67
|
+
# Sphinx documentation
|
|
68
|
+
docs/_build/
|
|
69
|
+
|
|
70
|
+
# PyBuilder
|
|
71
|
+
.pybuilder/
|
|
72
|
+
target/
|
|
73
|
+
|
|
74
|
+
# Jupyter Notebook
|
|
75
|
+
.ipynb_checkpoints
|
|
76
|
+
|
|
77
|
+
# IPython
|
|
78
|
+
profile_default/
|
|
79
|
+
ipython_config.py
|
|
80
|
+
|
|
81
|
+
# pyenv
|
|
82
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
83
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
84
|
+
# .python-version
|
|
85
|
+
|
|
86
|
+
# pipenv
|
|
87
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
88
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
89
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
90
|
+
# install all needed dependencies.
|
|
91
|
+
#Pipfile.lock
|
|
92
|
+
|
|
93
|
+
# poetry
|
|
94
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
95
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
96
|
+
# commonly ignored for libraries.
|
|
97
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
98
|
+
#poetry.lock
|
|
99
|
+
|
|
100
|
+
# pdm
|
|
101
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
102
|
+
#pdm.lock
|
|
103
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
104
|
+
# in version control.
|
|
105
|
+
# https://pdm.fming.dev/#use-with-ide
|
|
106
|
+
.pdm.toml
|
|
107
|
+
|
|
108
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
109
|
+
__pypackages__/
|
|
110
|
+
|
|
111
|
+
# Celery stuff
|
|
112
|
+
celerybeat-schedule
|
|
113
|
+
celerybeat.pid
|
|
114
|
+
|
|
115
|
+
# SageMath parsed files
|
|
116
|
+
*.sage.py
|
|
117
|
+
|
|
118
|
+
# Environments
|
|
119
|
+
.env
|
|
120
|
+
.venv
|
|
121
|
+
env/
|
|
122
|
+
venv/
|
|
123
|
+
ENV/
|
|
124
|
+
env.bak/
|
|
125
|
+
venv.bak/
|
|
126
|
+
|
|
127
|
+
# Spyder project settings
|
|
128
|
+
.spyderproject
|
|
129
|
+
.spyproject
|
|
130
|
+
|
|
131
|
+
# Rope project settings
|
|
132
|
+
.ropeproject
|
|
133
|
+
|
|
134
|
+
# mkdocs documentation
|
|
135
|
+
/site
|
|
136
|
+
|
|
137
|
+
# mypy
|
|
138
|
+
.mypy_cache/
|
|
139
|
+
.dmypy.json
|
|
140
|
+
dmypy.json
|
|
141
|
+
|
|
142
|
+
# Pyre type checker
|
|
143
|
+
.pyre/
|
|
144
|
+
|
|
145
|
+
# pytype static type analyzer
|
|
146
|
+
.pytype/
|
|
147
|
+
|
|
148
|
+
# Cython debug symbols
|
|
149
|
+
cython_debug/
|
|
150
|
+
|
|
151
|
+
# PyCharm
|
|
152
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
153
|
+
# be added to the global gitignore or merged into this project gitignore. For a PyCharm
|
|
154
|
+
# project, it is recommended to ignore these files.
|
|
155
|
+
.idea/
|
|
156
|
+
|
|
157
|
+
# UV specific
|
|
158
|
+
.uv/
|
|
159
|
+
|
|
160
|
+
# Project specific
|
|
161
|
+
*.profile
|
|
162
|
+
*.stats
|
|
163
|
+
*.prof
|
|
164
|
+
|
|
165
|
+
# Game specific
|
|
166
|
+
saves/
|
|
167
|
+
logs/
|
|
168
|
+
*.log
|
|
169
|
+
|
|
170
|
+
# Configuration runtime files
|
|
171
|
+
temp/
|
|
172
|
+
screenshots/
|
|
173
|
+
|
|
174
|
+
# OS specific
|
|
175
|
+
.DS_Store
|
|
176
|
+
.DS_Store?
|
|
177
|
+
._*
|
|
178
|
+
.Spotlight-V100
|
|
179
|
+
.Trashes
|
|
180
|
+
ehthumbs.db
|
|
181
|
+
Thumbs.db
|
pyguara-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
Copyright © 2026 Wedeueis Braz
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
5
|
+
|
|
6
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
7
|
+
|
|
8
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
pyguara-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyguara
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Python game engine featuring a event and data driven archictecture.
|
|
5
|
+
Author-email: Wedeueis Braz <wedeueisbraz@gmail.com>
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: 2d,action-rpg,data-driven,event-driven,game-engine
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Topic :: Games/Entertainment
|
|
14
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
15
|
+
Requires-Python: >=3.12
|
|
16
|
+
Requires-Dist: click>=8.1.7
|
|
17
|
+
Requires-Dist: dataclasses-json>=0.6.0
|
|
18
|
+
Requires-Dist: msgpack>=1.1.2
|
|
19
|
+
Requires-Dist: pillow>=12.1.0
|
|
20
|
+
Requires-Dist: pygame-ce>=2.5.6
|
|
21
|
+
Requires-Dist: pymunk>=7.2.0
|
|
22
|
+
Provides-Extra: benchmark
|
|
23
|
+
Requires-Dist: memory-profiler>=0.61.0; extra == 'benchmark'
|
|
24
|
+
Requires-Dist: py-spy>=0.3.0; extra == 'benchmark'
|
|
25
|
+
Requires-Dist: pytest-benchmark>=4.0.0; extra == 'benchmark'
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: build>=0.10.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: imgui>=2.0.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pillow>=11.3.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pre-commit>=3.0.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest-benchmark>=4.0.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: pytest-mock>=3.10.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: ruff>=0.14.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: syrupy>=4.9.1; extra == 'dev'
|
|
38
|
+
Requires-Dist: tox>=4.0.0; extra == 'dev'
|
|
39
|
+
Requires-Dist: twine>=4.0.0; extra == 'dev'
|
|
40
|
+
Provides-Extra: docs
|
|
41
|
+
Requires-Dist: mkdocs-material>=9.0.0; extra == 'docs'
|
|
42
|
+
Requires-Dist: mkdocs-mermaid2-plugin>=0.6.0; extra == 'docs'
|
|
43
|
+
Requires-Dist: mkdocs>=1.5.0; extra == 'docs'
|
|
44
|
+
Requires-Dist: pymdown-extensions>=10.0.0; extra == 'docs'
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
|
|
47
|
+
# PyGuara
|
|
48
|
+
|
|
49
|
+
**PyGuara** is a modern, modular, and high-performance 2D game engine for Python 3.12+. It features a robust Entity-Component-System (ECS) architecture, a native Dependency Injection (DI) container, and a decoupled event-driven design, making it suitable for scalable and maintainable game development.
|
|
50
|
+
|
|
51
|
+
> **Note:** This project is currently in **Pre-Alpha**. APIs are subject to change.
|
|
52
|
+
|
|
53
|
+
[](https://github.com/Wedeueis/pyguara/actions/workflows/ci.yml)
|
|
54
|
+
[](https://codecov.io/gh/Wedeueis/pyguara)
|
|
55
|
+
[](https://badge.fury.io/py/pyguara)
|
|
56
|
+
[](https://pypi.org/project/pyguara/)
|
|
57
|
+
[](https://github.com/astral-sh/ruff)
|
|
58
|
+
[](https://github.com/Wedeueis/pyguara/blob/main/LICENSE)
|
|
59
|
+
|
|
60
|
+
## 🚀 Key Features
|
|
61
|
+
|
|
62
|
+
* **⚡ Performance-First ECS**:
|
|
63
|
+
* Optimized `EntityManager` using **Inverted Indexes** for $O(1)$ component queries.
|
|
64
|
+
* Cache-friendly data layout designed to minimize Python overhead.
|
|
65
|
+
* **💉 Native Dependency Injection**:
|
|
66
|
+
* Built-in `DIContainer` supporting **Singleton**, **Transient**, and **Scoped** lifetimes.
|
|
67
|
+
* Automatic dependency resolution via Python type hints.
|
|
68
|
+
* **🎨 Decoupled Rendering Pipeline**:
|
|
69
|
+
* Backend-agnostic design (currently supporting `pygame-ce`).
|
|
70
|
+
* Support for **Z-sorting**, **Batching**, and efficient draw call management.
|
|
71
|
+
* **📢 Event-Driven Architecture**:
|
|
72
|
+
* Protocol-based event system for loose coupling between subsystems (Input, Physics, AI).
|
|
73
|
+
* **🤖 Integrated AI & Physics**:
|
|
74
|
+
* Built-in Finite State Machines (FSM), Steering Behaviors, and Blackboard patterns.
|
|
75
|
+
* Physics integration via `pymunk`.
|
|
76
|
+
|
|
77
|
+
## 🛠️ Installation
|
|
78
|
+
|
|
79
|
+
PyGuara requires **Python 3.12** or higher.
|
|
80
|
+
|
|
81
|
+
### Using `uv` (Recommended)
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Clone the repository
|
|
85
|
+
git clone https://github.com/Wedeueis/pyguara
|
|
86
|
+
cd pyguara
|
|
87
|
+
|
|
88
|
+
# Sync dependencies
|
|
89
|
+
uv sync
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Using `pip`
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
pip install -e .[dev]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## 🎮 Quick Start
|
|
99
|
+
|
|
100
|
+
To run the default example scene included with the engine:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
python main.py
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Creating a Basic Scene
|
|
107
|
+
|
|
108
|
+
Here is a minimal example of how to define a scene using PyGuara's ECS:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from pyguara.scene.base import Scene
|
|
112
|
+
from pyguara.common.components import Transform
|
|
113
|
+
from pyguara.graphics.components.sprite import Sprite
|
|
114
|
+
from pyguara.common.types import Vector2
|
|
115
|
+
|
|
116
|
+
class MyGameScene(Scene):
|
|
117
|
+
def on_enter(self) -> None:
|
|
118
|
+
print("Welcome to PyGuara!")
|
|
119
|
+
|
|
120
|
+
# Create an entity
|
|
121
|
+
player = self.entity_manager.create_entity("player")
|
|
122
|
+
|
|
123
|
+
# Add components
|
|
124
|
+
player.add_component(Transform(position=Vector2(100, 100)))
|
|
125
|
+
player.add_component(Sprite(texture_path="assets/player.png"))
|
|
126
|
+
|
|
127
|
+
def update(self, dt: float) -> None:
|
|
128
|
+
# Game logic goes here
|
|
129
|
+
pass
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## 🏗️ Architecture Overview
|
|
133
|
+
|
|
134
|
+
The codebase is organized to enforce separation of concerns:
|
|
135
|
+
|
|
136
|
+
* `pyguara/ecs/`: The core Entity-Component-System implementation.
|
|
137
|
+
* `pyguara/di/`: The Dependency Injection container.
|
|
138
|
+
* `pyguara/events/`: The event dispatching system.
|
|
139
|
+
* `pyguara/graphics/`: Rendering protocols, pipelines, and backends.
|
|
140
|
+
* `pyguara/physics/`: Physics engine integration (Pymunk).
|
|
141
|
+
* `pyguara/application/`: Application lifecycle and bootstrapping.
|
|
142
|
+
|
|
143
|
+
## 🤝 Contributing
|
|
144
|
+
|
|
145
|
+
Contributions are welcome! Please ensure you adhere to the project's code quality standards.
|
|
146
|
+
|
|
147
|
+
1. **Install development dependencies**:
|
|
148
|
+
```bash
|
|
149
|
+
uv sync --extra dev
|
|
150
|
+
```
|
|
151
|
+
2. **Run tests**:
|
|
152
|
+
```bash
|
|
153
|
+
pytest
|
|
154
|
+
```
|
|
155
|
+
3. **Run linters**:
|
|
156
|
+
```bash
|
|
157
|
+
ruff check .
|
|
158
|
+
mypy pyguara
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## 📄 License
|
|
162
|
+
|
|
163
|
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
|
164
|
+
|
|
165
|
+
## ✍️ Author
|
|
166
|
+
|
|
167
|
+
Developed by **Wedeueis Braz**.
|
pyguara-0.2.0/README.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# PyGuara
|
|
2
|
+
|
|
3
|
+
**PyGuara** is a modern, modular, and high-performance 2D game engine for Python 3.12+. It features a robust Entity-Component-System (ECS) architecture, a native Dependency Injection (DI) container, and a decoupled event-driven design, making it suitable for scalable and maintainable game development.
|
|
4
|
+
|
|
5
|
+
> **Note:** This project is currently in **Pre-Alpha**. APIs are subject to change.
|
|
6
|
+
|
|
7
|
+
[](https://github.com/Wedeueis/pyguara/actions/workflows/ci.yml)
|
|
8
|
+
[](https://codecov.io/gh/Wedeueis/pyguara)
|
|
9
|
+
[](https://badge.fury.io/py/pyguara)
|
|
10
|
+
[](https://pypi.org/project/pyguara/)
|
|
11
|
+
[](https://github.com/astral-sh/ruff)
|
|
12
|
+
[](https://github.com/Wedeueis/pyguara/blob/main/LICENSE)
|
|
13
|
+
|
|
14
|
+
## 🚀 Key Features
|
|
15
|
+
|
|
16
|
+
* **⚡ Performance-First ECS**:
|
|
17
|
+
* Optimized `EntityManager` using **Inverted Indexes** for $O(1)$ component queries.
|
|
18
|
+
* Cache-friendly data layout designed to minimize Python overhead.
|
|
19
|
+
* **💉 Native Dependency Injection**:
|
|
20
|
+
* Built-in `DIContainer` supporting **Singleton**, **Transient**, and **Scoped** lifetimes.
|
|
21
|
+
* Automatic dependency resolution via Python type hints.
|
|
22
|
+
* **🎨 Decoupled Rendering Pipeline**:
|
|
23
|
+
* Backend-agnostic design (currently supporting `pygame-ce`).
|
|
24
|
+
* Support for **Z-sorting**, **Batching**, and efficient draw call management.
|
|
25
|
+
* **📢 Event-Driven Architecture**:
|
|
26
|
+
* Protocol-based event system for loose coupling between subsystems (Input, Physics, AI).
|
|
27
|
+
* **🤖 Integrated AI & Physics**:
|
|
28
|
+
* Built-in Finite State Machines (FSM), Steering Behaviors, and Blackboard patterns.
|
|
29
|
+
* Physics integration via `pymunk`.
|
|
30
|
+
|
|
31
|
+
## 🛠️ Installation
|
|
32
|
+
|
|
33
|
+
PyGuara requires **Python 3.12** or higher.
|
|
34
|
+
|
|
35
|
+
### Using `uv` (Recommended)
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Clone the repository
|
|
39
|
+
git clone https://github.com/Wedeueis/pyguara
|
|
40
|
+
cd pyguara
|
|
41
|
+
|
|
42
|
+
# Sync dependencies
|
|
43
|
+
uv sync
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Using `pip`
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install -e .[dev]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 🎮 Quick Start
|
|
53
|
+
|
|
54
|
+
To run the default example scene included with the engine:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
python main.py
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Creating a Basic Scene
|
|
61
|
+
|
|
62
|
+
Here is a minimal example of how to define a scene using PyGuara's ECS:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from pyguara.scene.base import Scene
|
|
66
|
+
from pyguara.common.components import Transform
|
|
67
|
+
from pyguara.graphics.components.sprite import Sprite
|
|
68
|
+
from pyguara.common.types import Vector2
|
|
69
|
+
|
|
70
|
+
class MyGameScene(Scene):
|
|
71
|
+
def on_enter(self) -> None:
|
|
72
|
+
print("Welcome to PyGuara!")
|
|
73
|
+
|
|
74
|
+
# Create an entity
|
|
75
|
+
player = self.entity_manager.create_entity("player")
|
|
76
|
+
|
|
77
|
+
# Add components
|
|
78
|
+
player.add_component(Transform(position=Vector2(100, 100)))
|
|
79
|
+
player.add_component(Sprite(texture_path="assets/player.png"))
|
|
80
|
+
|
|
81
|
+
def update(self, dt: float) -> None:
|
|
82
|
+
# Game logic goes here
|
|
83
|
+
pass
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## 🏗️ Architecture Overview
|
|
87
|
+
|
|
88
|
+
The codebase is organized to enforce separation of concerns:
|
|
89
|
+
|
|
90
|
+
* `pyguara/ecs/`: The core Entity-Component-System implementation.
|
|
91
|
+
* `pyguara/di/`: The Dependency Injection container.
|
|
92
|
+
* `pyguara/events/`: The event dispatching system.
|
|
93
|
+
* `pyguara/graphics/`: Rendering protocols, pipelines, and backends.
|
|
94
|
+
* `pyguara/physics/`: Physics engine integration (Pymunk).
|
|
95
|
+
* `pyguara/application/`: Application lifecycle and bootstrapping.
|
|
96
|
+
|
|
97
|
+
## 🤝 Contributing
|
|
98
|
+
|
|
99
|
+
Contributions are welcome! Please ensure you adhere to the project's code quality standards.
|
|
100
|
+
|
|
101
|
+
1. **Install development dependencies**:
|
|
102
|
+
```bash
|
|
103
|
+
uv sync --extra dev
|
|
104
|
+
```
|
|
105
|
+
2. **Run tests**:
|
|
106
|
+
```bash
|
|
107
|
+
pytest
|
|
108
|
+
```
|
|
109
|
+
3. **Run linters**:
|
|
110
|
+
```bash
|
|
111
|
+
ruff check .
|
|
112
|
+
mypy pyguara
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## 📄 License
|
|
116
|
+
|
|
117
|
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
|
118
|
+
|
|
119
|
+
## ✍️ Author
|
|
120
|
+
|
|
121
|
+
Developed by **Wedeueis Braz**.
|
|
File without changes
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Systems for updating AI logic."""
|
|
2
|
+
|
|
3
|
+
from pyguara.ai.components import AIComponent
|
|
4
|
+
from pyguara.ecs.manager import EntityManager
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class AISystem:
|
|
8
|
+
"""Updates AI decision making (FSMs/Trees)."""
|
|
9
|
+
|
|
10
|
+
def __init__(self, entity_manager: EntityManager):
|
|
11
|
+
"""Initialize the AI system for all Entities."""
|
|
12
|
+
self.manager = entity_manager
|
|
13
|
+
|
|
14
|
+
def update(self, dt: float) -> None:
|
|
15
|
+
"""Update all AI components."""
|
|
16
|
+
# Query entities with AI
|
|
17
|
+
for entity in self.manager.get_entities_with(AIComponent):
|
|
18
|
+
ai: AIComponent = entity.ai_component # Using __getattr__ magic
|
|
19
|
+
|
|
20
|
+
if not ai.enabled:
|
|
21
|
+
continue
|
|
22
|
+
|
|
23
|
+
# Update FSM if present
|
|
24
|
+
if ai.fsm:
|
|
25
|
+
ai.fsm.update(dt)
|
|
26
|
+
|
|
27
|
+
# (Future) Update Behavior Tree if present
|
|
28
|
+
# if ai.behavior_tree:
|
|
29
|
+
# ai.behavior_tree.tick(dt)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Blackboard system for sharing data between AI nodes and states."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Blackboard:
|
|
7
|
+
"""
|
|
8
|
+
A shared memory container for AI decision making.
|
|
9
|
+
|
|
10
|
+
Allows different parts of an AI (e.g., nodes in a Behavior Tree or states
|
|
11
|
+
in an FSM) to read and write shared data without tight coupling.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self) -> None:
|
|
15
|
+
"""Initialize the blackboard."""
|
|
16
|
+
self._data: Dict[str, Any] = {}
|
|
17
|
+
|
|
18
|
+
def set(self, key: str, value: Any) -> None:
|
|
19
|
+
"""Set a value in the blackboard."""
|
|
20
|
+
self._data[key] = value
|
|
21
|
+
|
|
22
|
+
def get(self, key: str, default: Any = None) -> Any:
|
|
23
|
+
"""Retrieve a value from the blackboard."""
|
|
24
|
+
return self._data.get(key, default)
|
|
25
|
+
|
|
26
|
+
def has(self, key: str) -> bool:
|
|
27
|
+
"""Check if a key exists."""
|
|
28
|
+
return key in self._data
|
|
29
|
+
|
|
30
|
+
def clear(self) -> None:
|
|
31
|
+
"""Clear all data."""
|
|
32
|
+
self._data.clear()
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""ECS components for AI."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import Optional, List
|
|
5
|
+
|
|
6
|
+
from pyguara.common.types import Vector2
|
|
7
|
+
from pyguara.ai.blackboard import Blackboard
|
|
8
|
+
from pyguara.ai.fsm import StateMachine
|
|
9
|
+
from pyguara.ecs.component import BaseComponent
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class AIComponent(BaseComponent):
|
|
14
|
+
"""
|
|
15
|
+
Component that holds the AI brain (FSM or Behavior Tree).
|
|
16
|
+
|
|
17
|
+
Attributes:
|
|
18
|
+
blackboard: Shared memory for this agent.
|
|
19
|
+
fsm: Optional Finite State Machine.
|
|
20
|
+
enabled: Whether AI logic should run.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
blackboard: Blackboard = field(default_factory=Blackboard)
|
|
24
|
+
fsm: Optional[StateMachine] = None
|
|
25
|
+
enabled: bool = True
|
|
26
|
+
|
|
27
|
+
def __post_init__(self) -> None:
|
|
28
|
+
"""Call superclass init after initialization."""
|
|
29
|
+
super().__init__()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass
|
|
33
|
+
class SteeringAgent(BaseComponent):
|
|
34
|
+
"""
|
|
35
|
+
Component that defines movement capabilities.
|
|
36
|
+
|
|
37
|
+
Attributes:
|
|
38
|
+
max_speed: Maximum movement speed.
|
|
39
|
+
max_force: Maximum steering force (turn speed/acceleration).
|
|
40
|
+
mass: Used to calculate acceleration (Force / Mass).
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
max_speed: float = 200.0
|
|
44
|
+
max_force: float = 500.0
|
|
45
|
+
mass: float = 1.0
|
|
46
|
+
|
|
47
|
+
def __post_init__(self) -> None:
|
|
48
|
+
"""Call superclass init after initialization."""
|
|
49
|
+
super().__init__()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class Navigator(BaseComponent):
|
|
54
|
+
"""
|
|
55
|
+
Component that handles pathfollowing.
|
|
56
|
+
|
|
57
|
+
Attributes:
|
|
58
|
+
path: Current list of waypoints.
|
|
59
|
+
current_index: Which waypoint we are moving toward.
|
|
60
|
+
reach_threshold: How close to get before switching to next waypoint.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
path: List[Vector2] = field(default_factory=list)
|
|
64
|
+
current_index: int = 0
|
|
65
|
+
reach_threshold: float = 5.0
|
|
66
|
+
|
|
67
|
+
def set_path(self, path: List[Vector2]) -> None:
|
|
68
|
+
"""Set the path defined by a list of vectors."""
|
|
69
|
+
self.path = path
|
|
70
|
+
self.current_index = 0
|
|
71
|
+
|
|
72
|
+
def get_current_target(self) -> Optional[Vector2]:
|
|
73
|
+
"""Return the current imediate destination."""
|
|
74
|
+
if 0 <= self.current_index < len(self.path):
|
|
75
|
+
return self.path[self.current_index]
|
|
76
|
+
return None
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""Finite State Machine (FSM) implementation."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from typing import Dict, Optional
|
|
5
|
+
|
|
6
|
+
from pyguara.ai.blackboard import Blackboard
|
|
7
|
+
from pyguara.ecs.entity import Entity
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class State(ABC):
|
|
11
|
+
"""Abstract base class for FSM states."""
|
|
12
|
+
|
|
13
|
+
def __init__(self, entity: Entity, blackboard: Blackboard):
|
|
14
|
+
"""Initialize the state of an entity and a Blackboard."""
|
|
15
|
+
self.entity = entity
|
|
16
|
+
self.blackboard = blackboard
|
|
17
|
+
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def on_enter(self) -> None:
|
|
20
|
+
"""Call when entering this state."""
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
@abstractmethod
|
|
24
|
+
def on_exit(self) -> None:
|
|
25
|
+
"""Call when exiting this state."""
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
@abstractmethod
|
|
29
|
+
def update(self, dt: float) -> Optional[str]:
|
|
30
|
+
"""
|
|
31
|
+
Update the state logic.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Name of the next state to transition to, or None to stay.
|
|
35
|
+
"""
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class StateMachine:
|
|
40
|
+
"""Manages states and transitions for an entity."""
|
|
41
|
+
|
|
42
|
+
def __init__(self, entity: Entity, blackboard: Blackboard):
|
|
43
|
+
"""Initialize the State Machine of an entity and a Blackboard."""
|
|
44
|
+
self.entity = entity
|
|
45
|
+
self.blackboard = blackboard
|
|
46
|
+
self._states: Dict[str, State] = {}
|
|
47
|
+
self._current_state: Optional[State] = None
|
|
48
|
+
self._current_state_name: str = ""
|
|
49
|
+
|
|
50
|
+
def add_state(self, name: str, state: State) -> None:
|
|
51
|
+
"""Register a state instance."""
|
|
52
|
+
self._states[name] = state
|
|
53
|
+
|
|
54
|
+
def set_initial_state(self, name: str) -> None:
|
|
55
|
+
"""Set the starting state."""
|
|
56
|
+
if name in self._states:
|
|
57
|
+
self._current_state = self._states[name]
|
|
58
|
+
self._current_state_name = name
|
|
59
|
+
self._current_state.on_enter()
|
|
60
|
+
|
|
61
|
+
def update(self, dt: float) -> None:
|
|
62
|
+
"""Update current state and handle transitions."""
|
|
63
|
+
if not self._current_state:
|
|
64
|
+
return
|
|
65
|
+
|
|
66
|
+
# Update returns potential transition
|
|
67
|
+
next_state_name = self._current_state.update(dt)
|
|
68
|
+
|
|
69
|
+
if next_state_name and next_state_name != self._current_state_name:
|
|
70
|
+
self._transition_to(next_state_name)
|
|
71
|
+
|
|
72
|
+
def _transition_to(self, name: str) -> None:
|
|
73
|
+
"""Execute transition logic."""
|
|
74
|
+
if name not in self._states:
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
if self._current_state:
|
|
78
|
+
self._current_state.on_exit()
|
|
79
|
+
|
|
80
|
+
self._current_state = self._states[name]
|
|
81
|
+
self._current_state_name = name
|
|
82
|
+
self._current_state.on_enter()
|