Skip to main content

Moon

Project description

🌙 Moon Framework - Ключевые особенности реализации

Подробный технический обзор архитектуры и реализации игрового фреймворка Moon


📋 Содержание

  1. Архитектурный обзор
  2. Гибридная архитектура Python + C++
  3. Система управления памятью
  4. Оптимизации производительности
  5. Система рендеринга
  6. Обработка событий
  7. Математические вычисления
  8. Система цветов и градиентов
  9. Аудиосистема
  10. Система сборки
  11. Безопасность и стабильность

🏗️ Архитектурный обзор

Многослойная архитектура

Moon построен по принципу многослойной архитектуры:

┌─────────────────────────────────────┐
│        Python API Layer          │  ← Удобный интерфейс для разработчиков
├─────────────────────────────────────┤
│      Python Wrapper Layer        │  ← Обертки и управление ресурсами
├─────────────────────────────────────┤
│       C++ Binding Layer          │  ← ctypes биндинги
├─────────────────────────────────────┤
│      Native C++ Core (SFML)      │  ← Высокопроизводительное ядро
└─────────────────────────────────────┘

Принципы дизайна

  1. Performance First - критические операции выполняются в C++
  2. Developer Friendly - простой и интуитивный Python API
  3. Memory Safe - автоматическое управление ресурсами
  4. 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

Защита от утечек памяти

  1. Автоматические деструкторы - каждый объект освобождает свои ресурсы
  2. Проверка валидности указателей - защита от двойного освобождения
  3. Исключения с гарантиями - корректная очистка при ошибках

Оптимизация памяти с 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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

moonframework-0.1.17.tar.gz (2.7 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

moonframework-0.1.17-py3-none-any.whl (2.7 MB view details)

Uploaded Python 3

File details

Details for the file moonframework-0.1.17.tar.gz.

File metadata

  • Download URL: moonframework-0.1.17.tar.gz
  • Upload date:
  • Size: 2.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for moonframework-0.1.17.tar.gz
Algorithm Hash digest
SHA256 fd71f6440640d4e983eb6f57c090c794a4e411796f1f413daf342fb30e9ff8af
MD5 d085023e228b9039e487deb1474f54ce
BLAKE2b-256 60c274a4dc8fedf665ba5f619f938507bac9ac18231687e6d4db563dde75d74c

See more details on using hashes here.

File details

Details for the file moonframework-0.1.17-py3-none-any.whl.

File metadata

  • Download URL: moonframework-0.1.17-py3-none-any.whl
  • Upload date:
  • Size: 2.7 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for moonframework-0.1.17-py3-none-any.whl
Algorithm Hash digest
SHA256 36ed31229310f5cff7e020c8ea4e91e0ae7fd2fdd7cf83559b177aa6c86f17c4
MD5 dccaca72a30f81bced5b094eafa3710d
BLAKE2b-256 2568620c115c66d78a587f182883152e166cd3eff3212addaba85f746e22e43f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page