aether-engine 1.7.0__tar.gz → 1.7.1__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.
Files changed (121) hide show
  1. {aether_engine-1.7.0/aether_engine.egg-info → aether_engine-1.7.1}/PKG-INFO +18 -9
  2. {aether_engine-1.7.0 → aether_engine-1.7.1}/README.md +13 -4
  3. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/__init__.py +1 -1
  4. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/cli.py +1 -2
  5. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/core/_identity.py +1 -1
  6. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/web/content.py +110 -32
  7. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/web/plain_content.py +59 -18
  8. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/web/templates.py +5 -2
  9. {aether_engine-1.7.0 → aether_engine-1.7.1/aether_engine.egg-info}/PKG-INFO +18 -9
  10. {aether_engine-1.7.0 → aether_engine-1.7.1}/examples/01_hello_cube.py +1 -2
  11. {aether_engine-1.7.0 → aether_engine-1.7.1}/examples/02_sphere_scene.py +1 -2
  12. {aether_engine-1.7.0 → aether_engine-1.7.1}/examples/03_first_person.py +2 -1
  13. {aether_engine-1.7.0 → aether_engine-1.7.1}/setup.py +1 -1
  14. {aether_engine-1.7.0 → aether_engine-1.7.1}/LICENSE +0 -0
  15. {aether_engine-1.7.0 → aether_engine-1.7.1}/MANIFEST.in +0 -0
  16. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/__main__.py +0 -0
  17. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/accelerators/__init__.py +0 -0
  18. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/accelerators/gameplay.py +0 -0
  19. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/accelerators/voxel.py +0 -0
  20. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/ai/behavior_tree.py +0 -0
  21. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/ai/navmesh.py +0 -0
  22. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/animation/skeleton.py +0 -0
  23. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/assets/__pycache__/asset_pipeline.cpython-314.pyc +0 -0
  24. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/assets/asset_pipeline.py +0 -0
  25. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/assets/fonts/AetherSans.ttf +0 -0
  26. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/audio/__init__.py +0 -0
  27. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/audio/audio_manager.py +0 -0
  28. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/audio/music.py +0 -0
  29. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/audio/sfx.py +0 -0
  30. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/audio/sound.py +0 -0
  31. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/core/__init__.py +0 -0
  32. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/core/achievement_system.py +0 -0
  33. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/core/application.py +0 -0
  34. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/core/boot_splash.py +0 -0
  35. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/core/branding_guard.py +0 -0
  36. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/core/config.py +0 -0
  37. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/core/console.py +0 -0
  38. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/core/engine.py +0 -0
  39. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/core/event_bus.py +0 -0
  40. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/core/input.py +0 -0
  41. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/core/plugin_system.py +0 -0
  42. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/core/save_system.py +0 -0
  43. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/core/time_manager.py +0 -0
  44. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/core/window.py +0 -0
  45. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/editor/__init__.py +0 -0
  46. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/environment/environment_system.py +0 -0
  47. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/__init__.py +0 -0
  48. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/camera.py +0 -0
  49. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/first_person.py +0 -0
  50. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/framebuffer.py +0 -0
  51. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/light.py +0 -0
  52. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/lod_system.py +0 -0
  53. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/material.py +0 -0
  54. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/mesh.py +0 -0
  55. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/mesh_factory.py +0 -0
  56. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/particle_system.py +0 -0
  57. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/post_process.py +0 -0
  58. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/renderer.py +0 -0
  59. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/shader.py +0 -0
  60. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/shader_library.py +0 -0
  61. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/sky_atmosphere.py +0 -0
  62. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/terrain.py +0 -0
  63. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/texture.py +0 -0
  64. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/voxel_mesh.py +0 -0
  65. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics/water.py +0 -0
  66. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/graphics2d/__init__.py +0 -0
  67. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/network/network_manager.py +0 -0
  68. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/physics/__init__.py +0 -0
  69. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/physics/bullet_backend.py +0 -0
  70. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/physics/collider.py +0 -0
  71. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/physics/physics2d.py +0 -0
  72. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/physics/physics3d.py +0 -0
  73. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/physics/physics_world.py +0 -0
  74. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/physics/raycast.py +0 -0
  75. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/physics/rigidbody.py +0 -0
  76. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/platform/steam_api.py +0 -0
  77. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/resources/__init__.py +0 -0
  78. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/resources/asset_database.py +0 -0
  79. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/resources/asset_loader.py +0 -0
  80. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/resources/loaders/model_loader.py +0 -0
  81. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/resources/loaders/obj_loader.py +0 -0
  82. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/resources/loaders/texture_loader.py +0 -0
  83. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/resources/resource_manager.py +0 -0
  84. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/resources/save_load.py +0 -0
  85. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/resources/serialization.py +0 -0
  86. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/scene/__init__.py +0 -0
  87. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/scene/component.py +0 -0
  88. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/scene/entity.py +0 -0
  89. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/scene/scene.py +0 -0
  90. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/scene/scene_graph.py +0 -0
  91. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/scene/scene_manager.py +0 -0
  92. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/tools/__init__.py +0 -0
  93. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/tools/packager.py +0 -0
  94. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/ui/__init__.py +0 -0
  95. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/ui/button.py +0 -0
  96. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/ui/canvas.py +0 -0
  97. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/ui/hud.py +0 -0
  98. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/ui/text.py +0 -0
  99. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/utils/__init__.py +0 -0
  100. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/utils/fonts.py +0 -0
  101. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/utils/logger.py +0 -0
  102. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/utils/math_utils.py +0 -0
  103. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/utils/object_pool.py +0 -0
  104. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/utils/profiler.py +0 -0
  105. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/web/__init__.py +0 -0
  106. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/web/bot_detect.py +0 -0
  107. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/web/config.py +0 -0
  108. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/web/notifications.py +0 -0
  109. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/web/plain.py +0 -0
  110. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/web/registry.py +0 -0
  111. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/web/secrets.py +0 -0
  112. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/web/server.py +0 -0
  113. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether/web/urls.py +0 -0
  114. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether_engine.egg-info/SOURCES.txt +0 -0
  115. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether_engine.egg-info/dependency_links.txt +0 -0
  116. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether_engine.egg-info/entry_points.txt +0 -0
  117. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether_engine.egg-info/requires.txt +4 -4
  118. {aether_engine-1.7.0 → aether_engine-1.7.1}/aether_engine.egg-info/top_level.txt +0 -0
  119. {aether_engine-1.7.0 → aether_engine-1.7.1}/examples/04_physics2d.py +0 -0
  120. {aether_engine-1.7.0 → aether_engine-1.7.1}/pyproject.toml +0 -0
  121. {aether_engine-1.7.0 → aether_engine-1.7.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aether-engine
3
- Version: 1.7.0
3
+ Version: 1.7.1
4
4
  Summary: 3D/2D game engine by entiti937 — OpenGL, physics, FPS, mandatory branding splash
5
5
  Home-page: https://pypi.org/project/aether-engine/
6
6
  Author: entiti937
@@ -31,13 +31,13 @@ Requires-Dist: trimesh>=3.21; extra == "models"
31
31
  Provides-Extra: build
32
32
  Requires-Dist: pyinstaller>=6.0; extra == "build"
33
33
  Provides-Extra: full
34
- Requires-Dist: freetype-py>=2.4; extra == "full"
35
- Requires-Dist: imageio>=2.31; extra == "full"
34
+ Requires-Dist: pyinstaller>=6.0; extra == "full"
36
35
  Requires-Dist: pygame-ce>=2.5; extra == "full"
37
- Requires-Dist: pyyaml>=6.0; extra == "full"
36
+ Requires-Dist: imageio>=2.31; extra == "full"
38
37
  Requires-Dist: trimesh>=3.21; extra == "full"
39
38
  Requires-Dist: pymunk>=6.0; extra == "full"
40
- Requires-Dist: pyinstaller>=6.0; extra == "full"
39
+ Requires-Dist: pyyaml>=6.0; extra == "full"
40
+ Requires-Dist: freetype-py>=2.4; extra == "full"
41
41
  Dynamic: author
42
42
  Dynamic: classifier
43
43
  Dynamic: description
@@ -52,7 +52,7 @@ Dynamic: summary
52
52
  # Aether Engine
53
53
 
54
54
  **3D / 2D игровой движок на Python + OpenGL**
55
- **Разработчик:** entiti937 · **Версия:** 1.7.0 · **Лицензия:** MIT
55
+ **Разработчик:** entiti937 · **Версия:** 1.7.1 · **Лицензия:** MIT
56
56
  **PyPI:** https://pypi.org/project/aether-engine/
57
57
 
58
58
  > Полное руководство: [`docs/GUIDE.md`](docs/GUIDE.md)
@@ -65,6 +65,12 @@ Dynamic: summary
65
65
  pip install -U "aether-engine[full]"
66
66
  ```
67
67
 
68
+ ## Что нового в 1.7.1
69
+
70
+ - Документация: 2D-физика (pymunk), статус 3D-солвера, GLFW vs pygame-ce
71
+ - Единый импорт компонентов из `aether`
72
+ - Расширен раздел Performance
73
+
68
74
  ## Что нового в 1.7.0
69
75
 
70
76
  - **AssetLoader** — загрузка любых моделей, спрайтов и текстур (OBJ/GLB/FBX/PNG/WebP/…)
@@ -95,8 +101,10 @@ aether website
95
101
  ## Минимальный код
96
102
 
97
103
  ```python
98
- from aether import Engine, Scene, Entity, MeshFactory, Material, Camera
99
- from aether.scene.component import Transform, MeshRenderer
104
+ from aether import (
105
+ Engine, Scene, Entity, Transform, MeshRenderer,
106
+ MeshFactory, Material, Camera,
107
+ )
100
108
 
101
109
  engine = Engine(1280, 720, "Game by you — engine by entiti937")
102
110
  scene = Scene("Main")
@@ -105,7 +113,8 @@ scene.set_main_camera(camera)
105
113
 
106
114
  cube = Entity("Cube")
107
115
  cube.add_component(Transform(position=(0, 1, 0)))
108
- mat = Material(); mat.albedo[:] = (0.2, 0.85, 1.0)
116
+ mat = Material()
117
+ mat.albedo[:] = (0.2, 0.85, 1.0)
109
118
  cube.add_component(MeshRenderer(mesh=MeshFactory.create_cube(), material=mat))
110
119
  scene.spawn(cube)
111
120
 
@@ -1,7 +1,7 @@
1
1
  # Aether Engine
2
2
 
3
3
  **3D / 2D игровой движок на Python + OpenGL**
4
- **Разработчик:** entiti937 · **Версия:** 1.7.0 · **Лицензия:** MIT
4
+ **Разработчик:** entiti937 · **Версия:** 1.7.1 · **Лицензия:** MIT
5
5
  **PyPI:** https://pypi.org/project/aether-engine/
6
6
 
7
7
  > Полное руководство: [`docs/GUIDE.md`](docs/GUIDE.md)
@@ -14,6 +14,12 @@
14
14
  pip install -U "aether-engine[full]"
15
15
  ```
16
16
 
17
+ ## Что нового в 1.7.1
18
+
19
+ - Документация: 2D-физика (pymunk), статус 3D-солвера, GLFW vs pygame-ce
20
+ - Единый импорт компонентов из `aether`
21
+ - Расширен раздел Performance
22
+
17
23
  ## Что нового в 1.7.0
18
24
 
19
25
  - **AssetLoader** — загрузка любых моделей, спрайтов и текстур (OBJ/GLB/FBX/PNG/WebP/…)
@@ -44,8 +50,10 @@ aether website
44
50
  ## Минимальный код
45
51
 
46
52
  ```python
47
- from aether import Engine, Scene, Entity, MeshFactory, Material, Camera
48
- from aether.scene.component import Transform, MeshRenderer
53
+ from aether import (
54
+ Engine, Scene, Entity, Transform, MeshRenderer,
55
+ MeshFactory, Material, Camera,
56
+ )
49
57
 
50
58
  engine = Engine(1280, 720, "Game by you — engine by entiti937")
51
59
  scene = Scene("Main")
@@ -54,7 +62,8 @@ scene.set_main_camera(camera)
54
62
 
55
63
  cube = Entity("Cube")
56
64
  cube.add_component(Transform(position=(0, 1, 0)))
57
- mat = Material(); mat.albedo[:] = (0.2, 0.85, 1.0)
65
+ mat = Material()
66
+ mat.albedo[:] = (0.2, 0.85, 1.0)
58
67
  cube.add_component(MeshRenderer(mesh=MeshFactory.create_cube(), material=mat))
59
68
  scene.spawn(cube)
60
69
 
@@ -31,7 +31,7 @@ from aether.audio.sfx import SfxBank
31
31
  from aether.resources.save_load import save_json, load_json
32
32
  from aether.physics.raycast import Raycaster
33
33
 
34
- __version__ = "1.7.0"
34
+ __version__ = "1.7.1"
35
35
 
36
36
  from aether.graphics.voxel_mesh import ChunkedVoxelMesher
37
37
  from aether.accelerators import is_native_available, backend_name
@@ -17,8 +17,7 @@ QUICK_REFERENCE = f"""
17
17
  pip install -U "aether-engine[full]"
18
18
 
19
19
  МИНИМАЛЬНЫЙ КОД (3D)
20
- from aether import Engine, Scene, Entity, MeshFactory, Material, Camera
21
- from aether.scene.component import Transform, MeshRenderer
20
+ from aether import Engine, Scene, Entity, Transform, MeshRenderer, MeshFactory, Material, Camera
22
21
 
23
22
  engine = Engine(1280, 720, "My Game")
24
23
  scene = Scene("Main")
@@ -20,7 +20,7 @@ _B = {
20
20
  ]),
21
21
  "sig": bytes([
22
22
  230, 194, 211, 207, 194, 213, 135, 226, 201, 192, 206, 201, 194,
23
- 135, 150, 137, 144, 137, 151,
23
+ 135, 150, 137, 144, 137, 150,
24
24
  ]),
25
25
  }
26
26
 
@@ -20,18 +20,23 @@ _BODIES = {
20
20
  <div class="step"><span class="step-num">Step 1</span>
21
21
  <pre><code>pip install -U "aether-engine[full]"</code></pre></div>
22
22
  <div class="step"><span class="step-num">Step 2 — first game</span>
23
- <pre><code>from aether import Engine, Scene, Entity, MeshFactory, Material, Camera
24
- from aether.scene.component import Transform, MeshRenderer
23
+ <pre><code>from aether import (
24
+ Engine, Scene, Entity, Transform, MeshRenderer,
25
+ MeshFactory, Material, Camera,
26
+ )
25
27
 
26
28
  engine = Engine(1280, 720, "Hello")
27
29
  scene = Scene("Main")
28
30
  cam = Camera(position=(0, 2, 8), yaw=-90)
29
31
  scene.set_main_camera(cam)
32
+
30
33
  cube = Entity("Cube")
31
34
  cube.add_component(Transform(position=(0, 1, 0)))
32
- m = Material(); m.albedo[:] = (0.3, 0.8, 0.4)
33
- cube.add_component(MeshRenderer(mesh=MeshFactory.create_cube(), material=m))
35
+ mat = Material()
36
+ mat.albedo[:] = (0.3, 0.8, 0.4)
37
+ cube.add_component(MeshRenderer(mesh=MeshFactory.create_cube(), material=mat))
34
38
  scene.spawn(cube)
39
+
35
40
  engine.load_scene(scene)
36
41
  engine.run()</code></pre></div>
37
42
 
@@ -73,6 +78,13 @@ engine.run()</code></pre></div>
73
78
 
74
79
  <div class="tip">After install, run <code>python -c "from aether import Engine; print('OK')"</code>.
75
80
  If you see <code>OK</code>, the engine is ready.</div>
81
+
82
+ <h2>Window &amp; audio stack</h2>
83
+ <div class="callout">
84
+ <strong>GLFW</strong> owns the game window, input, and OpenGL 4.6 context.<br>
85
+ <strong>pygame-ce</strong> is used only as an audio mixer (<code>pygame.mixer</code>) — the display module is never initialized.
86
+ No context conflicts, lower overhead than running two window backends.
87
+ </div>
76
88
  </section>
77
89
  """,
78
90
  "concepts": """
@@ -116,6 +128,13 @@ scene.spawn(player)</code></pre>
116
128
  engine.on_update(update)
117
129
  engine.run() # blocks until ESC</code></pre>
118
130
  <div class="tip"><code>dt</code> is delta time. Multiply movement by <code>dt</code> so speed stays the same on all FPS.</div>
131
+
132
+ <h2>Physics (2D ready out of the box)</h2>
133
+ <div class="callout">
134
+ <strong>2D physics is built in</strong> via <code>engine.physics2d</code> (pymunk backend).
135
+ See <a href="/physics">Physics</a> and run <code>examples/04_physics2d.py</code>.
136
+ </div>
137
+ <p>3D physics uses a lightweight in-engine solver today. PyBullet / Jolt integration is planned for a future major release.</p>
119
138
  </section>
120
139
  """,
121
140
  "quickstart": """
@@ -123,8 +142,10 @@ engine.run() # blocks until ESC</code></pre>
123
142
  <h1>Quick Start — first 3D scene</h1>
124
143
  <p class="lead">Copy this into <code>my_game.py</code> and run <code>python my_game.py</code>.</p>
125
144
 
126
- <pre><code>from aether import Engine, Scene, Entity, MeshFactory, Material, Camera
127
- from aether.scene.component import Transform, MeshRenderer
145
+ <pre><code>from aether import (
146
+ Engine, Scene, Entity, Transform, MeshRenderer,
147
+ MeshFactory, Material, Camera,
148
+ )
128
149
 
129
150
  # 1) Create engine and scene
130
151
  engine = Engine(1280, 720, "Hello Aether")
@@ -247,27 +268,44 @@ engine.on_update(update)</code></pre>
247
268
  <section>
248
269
  <h1>Physics</h1>
249
270
 
250
- <h2>3D — bodies and raycasts</h2>
251
- <pre><code>from aether.physics import BoxCollider
271
+ <div class="callout">
272
+ <strong>2D physics — available now.</strong>
273
+ Aether Engine ships with full <code>engine.physics2d</code> powered by <strong>pymunk</strong>.
274
+ Run the ready-made demo: <code>python examples/04_physics2d.py</code>
275
+ </div>
276
+
277
+ <h2>2D — pymunk (<code>engine.physics2d</code>)</h2>
278
+ <pre><code>engine.set_mode("2d")
279
+ pw = engine.physics2d
280
+
281
+ ground = pw.create_box(0, -200, 600, 40, static=True)
282
+ ball = pw.create_circle(0, 0, 20, mass=1.0)
283
+ pw.apply_impulse(ball, 300, 0)
284
+
285
+ # Sync sprite position each frame
286
+ sprite.x, sprite.y = ball.x, ball.y</code></pre>
287
+
288
+ <h3>Coordinate system</h3>
289
+ <p>Aether uses <strong>Y-up</strong> for both pymunk and <code>Renderer2D</code> — same origin convention, no flip needed.
290
+ Gravity defaults to <code>(0, -980)</code> (downward). Camera center follows world units; see <code>examples/04_physics2d.py</code>.</p>
291
+
292
+ <h2>3D — lightweight built-in solver</h2>
293
+ <div class="tip">
294
+ <strong>Status:</strong> 3D physics currently runs on Aether's own lightweight solver (gravity, boxes, spheres, raycasts).
295
+ <strong>PyBullet / Jolt</strong> integration is planned for upcoming major releases — not in 1.7.x yet.
296
+ </div>
297
+ <pre><code>from aether import BoxCollider
252
298
 
253
299
  body = engine.physics3d.create_body_for_entity(
254
300
  entity, mass=1.0, collider=BoxCollider(size=(1, 1, 1))
255
301
  )
256
302
  body.velocity[:] = (0, 4, 0)
257
303
 
258
- # Shoot a ray from camera
259
304
  origin = camera.position
260
305
  direction = camera.front
261
306
  hit = engine.physics3d.raycast(origin, direction, max_distance=100)
262
307
  if hit:
263
308
  print("Hit at distance", hit["distance"])</code></pre>
264
-
265
- <h2>2D — pymunk</h2>
266
- <pre><code>pw = engine.physics2d
267
- ground = pw.create_box(0, -200, 600, 40, static=True)
268
- ball = pw.create_circle(0, 0, 20, mass=1.0)
269
- pw.apply_impulse(ball, 300, 0)</code></pre>
270
- <div class="tip">2D coordinates: X right, Y up. Gravity defaults to downward.</div>
271
309
  </section>
272
310
  """,
273
311
  "models": """
@@ -275,8 +313,7 @@ pw.apply_impulse(ball, 300, 0)</code></pre>
275
313
  <h1>Loading 3D Models</h1>
276
314
  <p class="lead">Install model support: <code>pip install aether-engine[models]</code></p>
277
315
 
278
- <pre><code>from aether import ModelLoader, Entity, Material
279
- from aether.scene.component import Transform, MeshRenderer
316
+ <pre><code>from aether import ModelLoader, Entity, Material, Transform, MeshRenderer
280
317
 
281
318
  mesh = ModelLoader.load("assets/character.glb")
282
319
 
@@ -323,8 +360,7 @@ hero = Sprite.from_image("sprites/hero.png", x=0, y=0)
323
360
  engine.renderer2d.add_sprite(hero)</code></pre>
324
361
 
325
362
  <h2>3D models</h2>
326
- <pre><code>from aether import Entity, Material
327
- from aether.scene.component import Transform, MeshRenderer
363
+ <pre><code>from aether import Entity, Material, AssetLoader, Transform, MeshRenderer
328
364
 
329
365
  mesh = AssetLoader.load_model("models/character.glb")
330
366
  ent = Entity("Hero")
@@ -401,27 +437,69 @@ aether build my_game.py --name MyGame --console</code></pre>
401
437
  "architecture": """
402
438
  <section>
403
439
  <h1>Engine Architecture</h1>
404
- <pre><code>Engine -> Window, Input, Renderer3D, Renderer2D, Physics, Audio, Scene
405
- Scene -> Entity -> Components</code></pre>
406
- <p>Boot splash runs once at startup. Optional Rust accelerators with Python fallback.</p>
440
+ <pre><code>Engine -> Window (GLFW), Input, Renderer3D, Renderer2D, Physics, Audio, Scene
441
+ Scene -> Entity -> Components (Transform, MeshRenderer, …)</code></pre>
442
+
443
+ <h2>Window &amp; audio (no pygame display)</h2>
444
+ <div class="callout">
445
+ <strong>GLFW</strong> fully manages the window, input, and OpenGL 4.6 context.<br>
446
+ <strong>pygame-ce</strong> is used exclusively as an advanced audio mixer (<code>pygame.mixer</code>) — the display module is never initialized.
447
+ </div>
448
+
449
+ <h2>Physics</h2>
450
+ <ul class="checklist">
451
+ <li><strong>2D:</strong> <code>engine.physics2d</code> + pymunk — production-ready, see <code>examples/04_physics2d.py</code></li>
452
+ <li><strong>3D:</strong> lightweight built-in solver (prototypes / simple games)</li>
453
+ <li><strong>Roadmap:</strong> PyBullet or Jolt in a future major release</li>
454
+ </ul>
455
+
456
+ <p>Boot splash runs once at startup. Optional Rust accelerators with Python fallback (<code>backend_name()</code>).</p>
407
457
  </section>
408
458
  """,
409
459
  "performance": """
410
460
  <section>
411
461
  <h1>Performance</h1>
462
+ <p class="lead">Aether is a single-threaded Python game loop. Heavy work is pushed into native code where possible.</p>
463
+
464
+ <h2>Python GIL — what actually runs outside it</h2>
465
+ <table class="data">
466
+ <tr><th>Subsystem</th><th>How it helps</th></tr>
467
+ <tr><td>OpenGL (PyOpenGL)</td><td>GPU does rasterization; CPU uploads buffers once per mesh</td></tr>
468
+ <tr><td>NumPy</td><td>Vertex/index arrays stored as contiguous buffers; math runs in C</td></tr>
469
+ <tr><td>trimesh</td><td>Model import (GLB/OBJ/FBX…) triangulates in native code — pay once at load time</td></tr>
470
+ <tr><td>pymunk</td><td>2D physics simulation in C; good for platformers</td></tr>
471
+ <tr><td>Rust accelerators (optional)</td><td>Chunked voxel meshing, NPC helpers — <code>backend_name()</code> returns <code>rust</code> or <code>python</code></td></tr>
472
+ </table>
473
+ <p>The main loop (input → update → draw) stays on one thread — same model as most indie engines. Profile before adding threads.</p>
474
+
475
+ <h2>Mesh loading &amp; runtime cost</h2>
412
476
  <ul class="checklist">
413
- <li>Use ChunkedVoxelMesher for editable block worlds</li>
414
- <li>Reuse materials and meshes</li>
415
- <li>Merge static geometry for many identical props</li>
416
- <li>Keep draw_hud=False unless needed</li>
477
+ <li><strong>Load time:</strong> trimesh + NumPy convert files to GPU-ready buffers — complex GLB is fine if you load at startup</li>
478
+ <li><strong>Runtime:</strong> cost is draw calls, not Python per-vertex math</li>
479
+ <li><strong>Voxels:</strong> use <code>ChunkedVoxelMesher</code> — only dirty 16³ chunks rebuild</li>
480
+ <li><strong>Props:</strong> reuse <code>Material</code> and <code>Mesh</code> instances; merge static geometry</li>
481
+ <li><strong>HUD:</strong> keep <code>draw_hud=False</code> unless you need overlay</li>
417
482
  </ul>
483
+
484
+ <h2>Physics roadmap</h2>
485
+ <table class="data">
486
+ <tr><th>Mode</th><th>Status</th></tr>
487
+ <tr><td>2D (pymunk)</td><td><strong>Available now</strong> — <code>engine.physics2d</code>, see <a href="/physics">Physics</a> and <code>examples/04_physics2d.py</code></td></tr>
488
+ <tr><td>3D (built-in)</td><td>Lightweight custom solver — gravity, AABB/sphere, good for prototypes</td></tr>
489
+ <tr><td>3D (PyBullet / Jolt)</td><td>Planned integration — not in 1.7.x yet</td></tr>
490
+ </table>
491
+
492
+ <h2>Audio vs window</h2>
493
+ <p><strong>GLFW</strong> owns the game window, input, and OpenGL context.<br>
494
+ <strong>pygame-ce</strong> is used only for <code>pygame.mixer</code> (SFX + music) — no pygame display, no conflict with GLFW.</p>
495
+
496
+ <h2>Rough benchmarks (GTX 1050 class)</h2>
418
497
  <table class="data">
419
- <tr><th>Scenario</th><th>GTX 1050 class</th></tr>
420
- <tr><td>Simple 3D scene</td><td>60+ FPS</td></tr>
421
- <tr><td>Chunked voxel edits</td><td>Stable FPS vs full rebuild</td></tr>
422
- <tr><td>1000+ unique draw calls</td><td>Consider merging meshes</td></tr>
498
+ <tr><th>Scenario</th><th>Typical result</th></tr>
499
+ <tr><td>Simple 3D scene (few meshes)</td><td>60+ FPS</td></tr>
500
+ <tr><td>Chunked voxel edits</td><td>Stable vs full-world rebuild</td></tr>
501
+ <tr><td>1000+ separate draw calls</td><td>Merge meshes or batch</td></tr>
423
502
  </table>
424
- <p>3D physics: built-in solver. 2D: pymunk. EXE build: Windows via PyInstaller (Linux/macOS: run from Python).</p>
425
503
  </section>
426
504
  """,
427
505
  }
@@ -22,8 +22,10 @@ pip install -U "aether-engine[full]"
22
22
 
23
23
  ## Minimal example
24
24
  ```python
25
- from aether import Engine, Scene, Entity, MeshFactory, Material, Camera
26
- from aether.scene.component import Transform, MeshRenderer
25
+ from aether import (
26
+ Engine, Scene, Entity, Transform, MeshRenderer,
27
+ MeshFactory, Material, Camera,
28
+ )
27
29
 
28
30
  engine = Engine(1280, 720, "My Game")
29
31
  scene = Scene("Main")
@@ -32,7 +34,8 @@ scene.set_main_camera(camera)
32
34
 
33
35
  cube = Entity("Cube")
34
36
  cube.add_component(Transform(position=(0, 1, 0)))
35
- mat = Material(); mat.albedo[:] = (0.2, 0.9, 0.4)
37
+ mat = Material()
38
+ mat.albedo[:] = (0.2, 0.9, 0.4)
36
39
  cube.add_component(MeshRenderer(mesh=MeshFactory.create_cube(), material=mat))
37
40
  scene.spawn(cube)
38
41
 
@@ -65,6 +68,10 @@ pip install -U "aether-engine[full]"
65
68
 
66
69
  ## Verify
67
70
  python -c "from aether import Engine; print('OK')"
71
+
72
+ ## Window & audio
73
+ GLFW: window, input, OpenGL 4.6 context.
74
+ pygame-ce: mixer only (SFX/music) — display module is NEVER initialized. No conflict with GLFW.
68
75
  """,
69
76
  "concepts": """
70
77
  ## Engine
@@ -84,6 +91,10 @@ Game object. Attach components for behavior.
84
91
  ## Loop
85
92
  engine.on_update(lambda dt: ...)
86
93
  engine.run()
94
+
95
+ ## Physics
96
+ 2D physics built in: engine.physics2d (pymunk). Demo: examples/04_physics2d.py
97
+ 3D: lightweight built-in solver. PyBullet/Jolt planned for future major release.
87
98
  """,
88
99
  "quickstart": """
89
100
  See home page minimal example. Controls: WASD move camera, Tab mouse look, ESC quit.
@@ -101,9 +112,20 @@ engine.renderer2d.add_sprite(Sprite(x, y, w, h, color=(r,g,b,a)))
101
112
  Sprite.from_image("icon.png") — load PNG/JPG/WebP as textured sprite
102
113
  """,
103
114
  "physics": """
104
- 3D: engine.physics3d.create_body_for_entity(entity, mass=1, collider=BoxCollider(...))
105
- 2D: engine.physics2d.create_box(x, y, w, h, static=False)
106
- Raycast: engine.physics3d.raycast(origin, direction, max_distance)
115
+ 2D PHYSICS — AVAILABLE NOW (pymunk via engine.physics2d)
116
+ Run: python examples/04_physics2d.py
117
+
118
+ engine.set_mode("2d")
119
+ pw = engine.physics2d
120
+ ground = pw.create_box(0, -200, 600, 40, static=True)
121
+ ball = pw.create_circle(0, 0, 20, mass=1.0)
122
+ sprite.x, sprite.y = ball.x, ball.y # same Y-up coords, no flip
123
+
124
+ 3D PHYSICS — lightweight built-in solver (gravity, boxes, spheres, raycasts)
125
+ PyBullet / Jolt integration planned for future major releases (not in 1.7.x)
126
+
127
+ engine.physics3d.create_body_for_entity(entity, mass=1, collider=BoxCollider(...))
128
+ engine.physics3d.raycast(origin, direction, max_distance)
107
129
  """,
108
130
  "models": """
109
131
  pip install aether-engine[models]
@@ -145,22 +167,41 @@ examples/03_first_person.py — FPS
145
167
  examples/04_physics2d.py — 2D physics
146
168
  """,
147
169
  "architecture": """
148
- Engine -> Window, Input, Renderer3D, Renderer2D, Physics3D, Physics2D, Audio, Scene
170
+ Engine -> GLFW (window/input/OpenGL), Renderer3D, Renderer2D, Physics3D, Physics2D, Audio, Scene
149
171
  Scene -> Entity -> Components
172
+
173
+ Window/audio split:
174
+ - GLFW: full window + OpenGL 4.6 + input
175
+ - pygame-ce: pygame.mixer ONLY (no display init)
176
+
177
+ Physics:
178
+ - 2D: engine.physics2d + pymunk (ready, examples/04_physics2d.py)
179
+ - 3D: lightweight built-in solver; PyBullet/Jolt planned
180
+
150
181
  Optional Rust accelerators with Python fallback (backend_name()).
151
182
  """,
152
183
  "performance": """
153
- ## Tips
154
- - Use ChunkedVoxelMesher for editable block worlds (not full mesh rebuild per block).
155
- - Reuse Material and Mesh instances across entities.
156
- - Keep draw_hud=False unless HUD is needed.
157
- - physics3d fixed timestep via engine config.
158
-
159
- ## Typical scale (GTX 1050 class)
160
- - Thousands of static cubes: OK with chunked meshing
161
- - Hundreds of separate draw calls without batching: may drop below 60 FPS
162
- - Instancing for identical meshes: planned; merge static geometry where possible
184
+ ## GIL and native backends
185
+ - Main loop: single-threaded Python (input -> update -> draw)
186
+ - OpenGL: GPU rasterization; CPU uploads vertex buffers
187
+ - NumPy: mesh data in contiguous C arrays
188
+ - trimesh: model import triangulation in native code (cost at load time, not every frame)
189
+ - pymunk: 2D physics in C (available now via engine.physics2d)
190
+ - Optional Rust accelerators: ChunkedVoxelMesher, NPC helpers (backend_name())
191
+
192
+ ## Physics roadmap
193
+ - 2D: pymunk — available (examples/04_physics2d.py)
194
+ - 3D: lightweight built-in solver (prototypes)
195
+ - 3D PyBullet/Jolt: planned, not in 1.7.x
196
+
197
+ ## Audio vs window
198
+ - GLFW: window, input, OpenGL
199
+ - pygame-ce: mixer only (SFX/music), no pygame display
163
200
 
164
- Physics 3D: lightweight custom solver. Physics 2D: pymunk.
201
+ ## Tips
202
+ - ChunkedVoxelMesher for block worlds
203
+ - Reuse Material/Mesh instances
204
+ - Merge static geometry to cut draw calls
205
+ - draw_hud=False unless needed
165
206
  """,
166
207
  }
@@ -89,9 +89,9 @@ h3 { font-size: 1rem; margin: 1rem 0 0.4rem; color: #ddd; }
89
89
  padding: 1rem 1.15rem; margin: 0.85rem 0; }
90
90
  .step-num { color: var(--accent2); font-weight: 700; font-size: 0.75rem; text-transform: uppercase; }
91
91
  pre { background: rgba(0,0,0,0.42); border: 1px solid var(--border); border-radius: 10px;
92
- padding: 0.9rem; overflow-x: auto; margin: 0.65rem 0; }
92
+ padding: 0.9rem; overflow-x: auto; margin: 0.65rem 0; white-space: pre; }
93
93
  code { font-family: Consolas, monospace; font-size: 0.86rem; }
94
- pre code { color: #c5e8ff; }
94
+ pre code { color: #c5e8ff; white-space: pre; }
95
95
  .grid-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 0.85rem; }
96
96
  .card { background: var(--card); border: 1px solid var(--border); border-radius: 12px; padding: 1rem; }
97
97
  .checklist { list-style: none; margin: 0.5rem 0; }
@@ -103,6 +103,9 @@ table.data th { background: var(--card); }
103
103
  .muted { color: var(--muted); font-size: 0.88rem; }
104
104
  .tip { border-left: 3px solid var(--accent2); padding: 0.6rem 0.9rem; margin: 0.75rem 0;
105
105
  background: rgba(0,212,170,0.06); border-radius: 0 8px 8px 0; }
106
+ .callout { border: 1px solid var(--accent2); background: rgba(0,212,170,0.1); border-radius: 10px;
107
+ padding: 0.85rem 1rem; margin: 1rem 0; font-weight: 600; line-height: 1.5; }
108
+ .callout strong { color: var(--accent2); }
106
109
  footer { margin-top: 2.5rem; padding-top: 1rem; border-top: 1px solid var(--border);
107
110
  font-size: 0.78rem; color: var(--muted); }
108
111
  @media (max-width: 768px) { .layout { flex-direction: column; } .sidebar { width: 100%; height: auto; position: relative; } }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aether-engine
3
- Version: 1.7.0
3
+ Version: 1.7.1
4
4
  Summary: 3D/2D game engine by entiti937 — OpenGL, physics, FPS, mandatory branding splash
5
5
  Home-page: https://pypi.org/project/aether-engine/
6
6
  Author: entiti937
@@ -31,13 +31,13 @@ Requires-Dist: trimesh>=3.21; extra == "models"
31
31
  Provides-Extra: build
32
32
  Requires-Dist: pyinstaller>=6.0; extra == "build"
33
33
  Provides-Extra: full
34
- Requires-Dist: freetype-py>=2.4; extra == "full"
35
- Requires-Dist: imageio>=2.31; extra == "full"
34
+ Requires-Dist: pyinstaller>=6.0; extra == "full"
36
35
  Requires-Dist: pygame-ce>=2.5; extra == "full"
37
- Requires-Dist: pyyaml>=6.0; extra == "full"
36
+ Requires-Dist: imageio>=2.31; extra == "full"
38
37
  Requires-Dist: trimesh>=3.21; extra == "full"
39
38
  Requires-Dist: pymunk>=6.0; extra == "full"
40
- Requires-Dist: pyinstaller>=6.0; extra == "full"
39
+ Requires-Dist: pyyaml>=6.0; extra == "full"
40
+ Requires-Dist: freetype-py>=2.4; extra == "full"
41
41
  Dynamic: author
42
42
  Dynamic: classifier
43
43
  Dynamic: description
@@ -52,7 +52,7 @@ Dynamic: summary
52
52
  # Aether Engine
53
53
 
54
54
  **3D / 2D игровой движок на Python + OpenGL**
55
- **Разработчик:** entiti937 · **Версия:** 1.7.0 · **Лицензия:** MIT
55
+ **Разработчик:** entiti937 · **Версия:** 1.7.1 · **Лицензия:** MIT
56
56
  **PyPI:** https://pypi.org/project/aether-engine/
57
57
 
58
58
  > Полное руководство: [`docs/GUIDE.md`](docs/GUIDE.md)
@@ -65,6 +65,12 @@ Dynamic: summary
65
65
  pip install -U "aether-engine[full]"
66
66
  ```
67
67
 
68
+ ## Что нового в 1.7.1
69
+
70
+ - Документация: 2D-физика (pymunk), статус 3D-солвера, GLFW vs pygame-ce
71
+ - Единый импорт компонентов из `aether`
72
+ - Расширен раздел Performance
73
+
68
74
  ## Что нового в 1.7.0
69
75
 
70
76
  - **AssetLoader** — загрузка любых моделей, спрайтов и текстур (OBJ/GLB/FBX/PNG/WebP/…)
@@ -95,8 +101,10 @@ aether website
95
101
  ## Минимальный код
96
102
 
97
103
  ```python
98
- from aether import Engine, Scene, Entity, MeshFactory, Material, Camera
99
- from aether.scene.component import Transform, MeshRenderer
104
+ from aether import (
105
+ Engine, Scene, Entity, Transform, MeshRenderer,
106
+ MeshFactory, Material, Camera,
107
+ )
100
108
 
101
109
  engine = Engine(1280, 720, "Game by you — engine by entiti937")
102
110
  scene = Scene("Main")
@@ -105,7 +113,8 @@ scene.set_main_camera(camera)
105
113
 
106
114
  cube = Entity("Cube")
107
115
  cube.add_component(Transform(position=(0, 1, 0)))
108
- mat = Material(); mat.albedo[:] = (0.2, 0.85, 1.0)
116
+ mat = Material()
117
+ mat.albedo[:] = (0.2, 0.85, 1.0)
109
118
  cube.add_component(MeshRenderer(mesh=MeshFactory.create_cube(), material=mat))
110
119
  scene.spawn(cube)
111
120
 
@@ -5,8 +5,7 @@ ROOT = Path(__file__).resolve().parents[1]
5
5
  if str(ROOT) not in sys.path:
6
6
  sys.path.insert(0, str(ROOT))
7
7
 
8
- from aether import Engine, Scene, Entity, MeshFactory, Material, Camera
9
- from aether.scene.component import Transform, MeshRenderer
8
+ from aether import Engine, Scene, Entity, Transform, MeshRenderer, MeshFactory, Material, Camera
10
9
 
11
10
 
12
11
  def make_mat(color):
@@ -7,8 +7,7 @@ ROOT = Path(__file__).resolve().parents[1]
7
7
  if str(ROOT) not in sys.path:
8
8
  sys.path.insert(0, str(ROOT))
9
9
 
10
- from aether import Engine, Scene, Entity, MeshFactory, Material, Camera
11
- from aether.scene.component import Transform, MeshRenderer
10
+ from aether import Engine, Scene, Entity, Transform, MeshRenderer, MeshFactory, Material, Camera
12
11
 
13
12
 
14
13
  def main():
@@ -14,13 +14,14 @@ from aether import (
14
14
  Engine,
15
15
  Scene,
16
16
  Entity,
17
+ Transform,
18
+ MeshRenderer,
17
19
  MeshFactory,
18
20
  Material,
19
21
  Camera,
20
22
  ModelLoader,
21
23
  BoxCollider,
22
24
  )
23
- from aether.scene.component import Transform, MeshRenderer
24
25
 
25
26
 
26
27
  def make_mat(color, metallic=0.1, roughness=0.5):
@@ -72,7 +72,7 @@ extras_require = {
72
72
 
73
73
  setup(
74
74
  name="aether-engine",
75
- version="1.7.0",
75
+ version="1.7.1",
76
76
  author="entiti937",
77
77
  description="3D/2D game engine by entiti937 — OpenGL, physics, FPS, mandatory branding splash",
78
78
  long_description=long_description,
File without changes
File without changes
@@ -10,13 +10,13 @@ pygame-ce>=2.5
10
10
  pyinstaller>=6.0
11
11
 
12
12
  [full]
13
- freetype-py>=2.4
14
- imageio>=2.31
13
+ pyinstaller>=6.0
15
14
  pygame-ce>=2.5
16
- pyyaml>=6.0
15
+ imageio>=2.31
17
16
  trimesh>=3.21
18
17
  pymunk>=6.0
19
- pyinstaller>=6.0
18
+ pyyaml>=6.0
19
+ freetype-py>=2.4
20
20
 
21
21
  [models]
22
22
  trimesh>=3.21
File without changes