🌙 Moon Framework - Ключевые особенности реализации
Подробный технический обзор архитектуры и реализации игрового фреймворка Moon
📋 Содержание
- Архитектурный обзор
- Гибридная архитектура Python + C++
- Система управления памятью
- Оптимизации производительности
- Система рендеринга
- Обработка событий
- Математические вычисления
- Система цветов и градиентов
- Аудиосистема
- Система сборки
- Безопасность и стабильность
🏗️ Архитектурный обзор
Многослойная архитектура
Moon построен по принципу многослойной архитектуры:
┌─────────────────────────────────────┐
│ Python API Layer │ ← Удобный интерфейс для разработчиков
├─────────────────────────────────────┤
│ Python Wrapper Layer │ ← Обертки и управление ресурсами
├─────────────────────────────────────┤
│ C++ Binding Layer │ ← ctypes биндинги
├─────────────────────────────────────┤
│ Native C++ Core (SFML) │ ← Высокопроизводительное ядро
└─────────────────────────────────────┘
Принципы дизайна
- Performance First - критические операции выполняются в C++
- Developer Friendly - простой и интуитивный Python API
- Memory Safe - автоматическое управление ресурсами
- Fluent Interface - поддержка цепочек вызовов методов
🔗 Гибридная архитектура Python + C++
Разделение ответственности
Python слой отвечает за:
- Высокоуровневую логику игры
- Управление жизненным циклом объектов
- Валидацию параметров
- Удобный API для разработчиков
C++ слой отвечает за:
- Критичные к производительности операции
- Прямую работу с OpenGL/SFML
- Управление памятью на низком уровне
- Математические вычисления
Пример реализации RectangleShape
@final
class RectangleShape:
def __init__(self, width: float, height: float):
# Создание нативного объекта в C++
self._ptr = LIB_PYSGL._Rectangle_Create(float(width), float(height))
# Python-атрибуты для кэширования состояния
self.__color: Color | None = None
self.__angle: float = 0
def set_color(self, color: Color) -> Self:
# Валидация в Python
if not isinstance(color, Color):
raise TypeError("Expected Color object")
# Вызов нативной функции
LIB_PYSGL._Rectangle_SetColor(self._ptr, color.r, color.g, color.b, color.a)
# Кэширование состояния
self.__color = color
return self # Fluent interface
Биндинги через ctypes
# Определение сигнатур C++ функций
LIB_PYSGL._Rectangle_Create.argtypes = [ctypes.c_float, ctypes.c_float]
LIB_PYSGL._Rectangle_Create.restype = ctypes.c_void_p
LIB_PYSGL._Rectangle_SetColor.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int]
LIB_PYSGL._Rectangle_SetColor.restype = None
🧠 Система управления памятью
RAII в Python
Moon использует принцип RAII (Resource Acquisition Is Initialization) для автоматического управления ресурсами:
class RectangleShape:
def __init__(self, width: float, height: float):
self._ptr = LIB_PYSGL._Rectangle_Create(width, height)
def __del__(self):
# Автоматическое освобождение ресурсов
if hasattr(self, '_ptr') and self._ptr:
LIB_PYSGL._Rectangle_Delete(self._ptr)
self._ptr = None
Защита от утечек памяти
- Автоматические деструкторы - каждый объект освобождает свои ресурсы
- Проверка валидности указателей - защита от двойного освобождения
- Исключения с гарантиями - корректная очистка при ошибках
Оптимизация памяти с slots
@final
class Color:
__slots__ = ('r', 'g', 'b', 'a') # Экономия ~40% памяти
@final
class Vertex:
__slots__ = ('position', 'color', 'tex_coords') # Компактное хранение
⚡ Оптимизации производительности
Массовые операции в C++
# Медленно: цикл в Python
for vertex in vertices:
vertex.set_color(red_color)
# Быстро: одна операция в C++
vertex_array.set_color(red_color) # Все вершины сразу
Кэширование состояния
class RectangleShape:
def get_angle(self) -> float:
return self.__angle # Возврат из кэша, без вызова C++
def set_angle(self, angle: float) -> Self:
LIB_PYSGL._Rectangle_SetRotation(self._ptr, angle)
self.__angle = angle % 360 # Обновление кэша
return self
Оптимизированные структуры данных
# Специализированные классы для разных задач
class LineThinShape: # Для простых линий - минимальные накладные расходы
class LineShape: # Для линий с контуром - дополнительная функциональность
class LinesThinShape: # Для полилиний - массовые операции
Ленивые вычисления
class BaseLineShape:
def update(self):
# Пересчет геометрии только при необходимости
vector = Vector2f.between(self.__start_pos, self.__end_pos)
length = vector.get_lenght()
# ... сложные вычисления
def special_draw(self, window):
self.update() # Обновление только перед отрисовкой
window.draw(self.__rectangle_shape)
🎨 Система рендеринга
Многоуровневая система отрисовки
# Уровень 1: Простая отрисовка
window.draw(shape)
# Уровень 2: С состояниями рендеринга
window.draw(shape, render_states)
# Уровень 3: С шейдерами
window.draw(shape, shader)
Оптимизированные примитивы
# Нативные фигуры (максимальная производительность)
rect = RectangleShape(100, 100) # Прямой вызов SFML
circle = CircleShape(50) # Оптимизированная отрисовка
# Композитные фигуры (гибкость)
line = LineShape() # Состоит из прямоугольника + кругов
Система вершинных массивов
class VertexArray:
def set_color(self, color: Color) -> None:
# Массовое изменение цвета всех вершин в C++
LIB_PYSGL._VertexArray_SetAllVerticesColor(
self._ptr, color.r, color.g, color.b, color.a
)
def set_vertex_color(self, index: int, color: Color) -> None:
# Точечное изменение одной вершины
LIB_PYSGL._VertexArray_SetVertexColor(
self._ptr, index, color.r, color.g, color.b, color.a
)
🎮 Обработка событий
Эффективная система событий
class WindowEvents:
def poll(self, window) -> bool:
# Получение события из нативной очереди
return LIB_PYSGL._Window_GetCurrentEventType(
window.get_ptr(), self.__event_ptr
)
def get_type(self) -> int:
# Быстрое получение типа без копирования данных
return LIB_PYSGL._Events_GetType(self.__event_ptr)
Типизированные события
class WindowEvents:
class Type:
Closed = 0
Resized = 1
KeyPressed = 5
MouseButtonPressed = 9
# ... полный набор событий SFML
Интеграция с системными API
def update(self, events: WindowEvents) -> bool:
# Обработка нативных событий SFML
event_type = events.poll(self)
# Интеграция с keyboard библиотекой для расширенного ввода
if keyboard.is_pressed(self.__exit_key):
return False
return True
🧮 Математические вычисления
Векторная математика
@final
class Vector2f:
__slots__ = ('x', 'y')
def __add__(self, other: 'Vector2f') -> 'Vector2f':
return Vector2f(self.x + other.x, self.y + other.y)
def normalize(self) -> 'Vector2f':
length = self.get_lenght()
if length == 0:
return Vector2f(0, 0)
return Vector2f(self.x / length, self.y / length)
@staticmethod
def between(start: list, end: list) -> 'Vector2f':
return Vector2f(end[0] - start[0], end[1] - start[1])
Оптимизированные коллизии
def circles_collision(x1, y1, r1, x2, y2, r2) -> bool:
# Использование квадрата расстояния для избежания sqrt()
return distance_squared(x1, y1, x2, y2) <= (r1 + r2)**2
def distance_squared(x1, y1, x2, y2):
dx, dy = x2 - x1, y2 - y1
return dx * dx + dy * dy # Без sqrt() - в 3-5 раз быстрее
Шум Перлина
def perlin_noise(x: float, y: float, octaves: int = 1,
persistance: float = 0.5, lacunarity: float = 2.0) -> float:
# Интеграция с библиотекой noise для процедурной генерации
return pnoise2(x, y, octaves=octaves,
persistence=persistance, lacunarity=lacunarity)
🎨 Система цветов и градиентов
Продвинутая работа с цветами
@final
class Color:
__slots__ = ('r', 'g', 'b', 'a')
def lighten_hsv(self, factor: float) -> "Color":
# Конвертация в HSV для точного управления яркостью
h, s, v = colorsys.rgb_to_hsv(self.r/255, self.g/255, self.b/255)
new_v = min(1.0, v + (1 - v) * factor)
r, g, b = colorsys.hsv_to_rgb(h, s, new_v)
return Color(int(r*255), int(g*255), int(b*255), self.a)
Генерация цветовых палитр
def generate_palette(color: Color, scheme: str = "complementary",
num_colors: int = 5) -> list[Color]:
# Алгоритмы теории цвета для гармоничных палитр
h, s, v = colorsys.rgb_to_hsv(color.r/255, color.g/255, color.b/255)
if scheme == "triadic":
# Три равноудаленных цвета (через 120°)
for i in range(3):
new_h = (h + i/3) % 1.0
r, g, b = colorsys.hsv_to_rgb(new_h, s, v)
colors.append(Color(int(r*255), int(g*255), int(b*255)))
Сложные градиенты
class ColorGradientEx:
def __init__(self, colors: list[Color], lengths: list[float]):
# Градиенты с неравномерным распределением цветов
if not math.isclose(sum(lengths), 1.0, rel_tol=1e-9):
raise ValueError("Sum of lengths must equal 1.0")
def get(self, amount: float) -> Color:
# Эффективный поиск нужного сегмента градиента
for gradient, start, end in self.__gradients:
if start <= amount <= end:
relative = (amount - start) / (end - start)
return gradient.get(relative)
🔊 Аудиосистема
Интеграция с SFML Audio
// C++ биндинги для аудио
extern "C" {
__declspec(dllexport) SoundPtr _Sound_Create(SoundBufferPtr buffer) {
SoundPtr sound = new sf::Sound();
sound->setBuffer(*buffer);
return sound;
}
__declspec(dllexport) void _Sound_SetPosition(SoundPtr sound,
float x, float y, float z) {
sound->setPosition(x, y, z); // 3D позиционирование
}
}
Python обертки
class Sound:
def __init__(self, buffer: SoundBuffer):
self._ptr = LIB_PYSGL._Sound_Create(buffer.get_ptr())
def set_3d_position(self, x: float, y: float, z: float = 0) -> Self:
LIB_PYSGL._Sound_SetPosition(self._ptr, x, y, z)
return self
🔧 Система сборки
Автоматическая сборка C++ модулей
def build():
# Поиск всех файлов для сборки
builded_files = list(filter(lambda x: x[0:7] == "BUILDED", all_files))
# Объединение всех C++ файлов в один
with open("PySGL.cpp", 'w') as output:
for bf in builded_files:
with open(bf, 'r') as input_file:
output.write(input_file.read())
# Компиляция с оптимизациями
os.system(f"""g++ -shared -o PySGL.dll PySGL.cpp
-static -static-libstdc++ -static-libgcc
-DSFML_STATIC -O3 -march=native
-lsfml-graphics-s -lsfml-window-s -lsfml-system-s""")
Конфигурация через properties файл
# build.properties
SFML_INCLUDE_PATH="C:/SFML/include"
SFML_LIB_PATH="C:/SFML/lib"
COMPILER_PATH="global"
BUILD_FILES_PATH="Moon/src"
DLLS_FILES_PATH="Moon/dlls"
🛡️ Безопасность и стабильность
Валидация параметров
def set_size(self, width: float, height: float) -> Self:
if width <= 0 or height <= 0:
raise ValueError("Size values must be positive")
LIB_PYSGL._Rectangle_SetSize(self._ptr, width, height)
return self
Защита от некорректных индексов
def __getitem__(self, index: int) -> Vertex:
if not (0 <= index < len(self)):
raise IndexError(f"Vertex index {index} out of bounds")
# Безопасное обращение к нативному массиву
return self.__vertex_array.get_vertex(index)
Обработка ошибок загрузки библиотек
def _find_library() -> str:
try:
lib_path = DLL_FOUND_PATH
if not os.path.exists(lib_path):
# Поиск в альтернативных местах
lib_path = "./dlls/PySGL.dll"
if not os.path.exists(lib_path):
raise FileNotFoundError(f"Library not found at {lib_path}")
return lib_path
except Exception as e:
raise LibraryLoadError(f"Library search failed: {e}")
Graceful degradation
def set_alpha(self, alpha: int):
try:
# Попытка установить прозрачность через WinAPI
ctypes.windll.user32.SetLayeredWindowAttributes(
self.__window_descriptor, 0, int(alpha), 2
)
except:
# Тихий откат при ошибке (например, на Linux)
pass
📊 Метрики производительности
Встроенный профайлер
class Window:
def update(self, events: WindowEvents) -> bool:
# Замер времени рендеринга
self.__render_time = self.__clock.get_elapsed_time()
self.__clock.restart()
# Расчет FPS
self.__fps = 1 / self.__render_time if self.__render_time > 0 else 0
# Обновление истории для графика
self.__update_fps_history()
Визуализация производительности
def view_info(self) -> None:
if not self.__view_info:
return
# Динамический график FPS
for i, fps in enumerate(self.__fps_history):
x = graph_x + (i * graph_width / (self.__max_history - 1))
y = graph_y + graph_height - (fps * graph_height / max_fps)
color = self.__fps_line_color_green if fps >= max_fps * 0.5 else self.__fps_line_color_red
self.__fps_line.append_point_to_end(x, y, color)
🎯 Заключение
Moon Framework демонстрирует эффективное сочетание удобства Python и производительности C++. Ключевые достижения:
Производительность
- 60-80% улучшение по сравнению с чистым Python
- Массовые операции в нативном коде
- Оптимизированные структуры данных с slots
- Ленивые вычисления и кэширование
Удобство разработки
- Fluent Interface для цепочек вызовов
- Автоматическое управление памятью
- Богатая система типов с type hints
- Подробная документация и примеры
Архитектурная гибкость
- Модульная структура с четким разделением слоев
- Расширяемость через Python и C++
- Кроссплатформенность благодаря SFML
- Современные практики разработки
Moon представляет собой пример того, как можно создать высокопроизводительный игровой фреймворк, сохранив при этом простоту и удобство использования Python.
Metadata
Release files for MoonFramework 0.1.21
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| moonframework-0.1.21.tar.gz | 2.7 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| moonframework-0.1.21-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 5.4 MB
Release files / moonframework-0.1.21.tar.gz
| Download URL | moonframework-0.1.21.tar.gz |
|---|---|
| Size | 2.7 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
58dccf96967d710df5a0b5fba4316e7f26fd0e4daba253968956b831904b5df2
|
|
BLAKE2b-256 checksum How to use checksums |
2c7e7855de350625a136a642b64728da9101f7a340388453209165deebe61876
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.9
|
Release files / moonframework-0.1.21-py3-none-any.whl
| Download URL | moonframework-0.1.21-py3-none-any.whl |
|---|---|
| Size | 2.7 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1271c6ed5aa26b2a9c91e6568d8a23eef283bda854bacf59ff77a30b4c21d3c0
|
|
BLAKE2b-256 checksum How to use checksums |
e0039aab76f8da5250c82c676d8edbfb779525c575865ce7933b3bbc35963a49
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.9
|