Documentation

Debugging Profiling

ЭффСктивная ΠΎΡ‚Π»Π°Π΄ΠΊΠ° ΠΈ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ β€” ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹Π΅ Π½Π°Π²Ρ‹ΠΊΠΈ для ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ ΠΈΠ³Ρ€ Π½Π° Wudgine. Π’ этом Ρ€Π°Π·Π΄Π΅Π»Π΅ Ρ€Π°ΡΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°ΡŽΡ‚ΡΡ инструмСнты ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΈΠΊΠΈ для выявлСния ΠΈ устранСния ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ.

Π’Π²Π΅Π΄Π΅Π½ΠΈΠ΅

ΠžΡ‚Π»Π°Π΄ΠΊΠ° ΠΈ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ Π½Π΅ΠΎΡ‚ΡŠΠ΅ΠΌΠ»Π΅ΠΌΠΎΠΉ Ρ‡Π°ΡΡ‚ΡŒΡŽ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΈΠ³Ρ€. Wudgine прСдоставляСт Π½Π°Π±ΠΎΡ€ инструмСнтов, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΠΎΠΌΠΎΠ³Π°ΡŽΡ‚ Π²Ρ‹ΡΠ²Π»ΡΡ‚ΡŒ ΠΈ ΡƒΡΡ‚Ρ€Π°Π½ΡΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ, ΡƒΡ‚Π΅Ρ‡ΠΊΠΈ памяти ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ошибки.

ВстроСнныС инструмСнты ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ

Консоль ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ

Wudgine Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π²ΡΡ‚Ρ€ΠΎΠ΅Π½Π½ΡƒΡŽ консоль ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ, которая позволяСт ΠΏΡ€ΠΎΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒ Π»ΠΎΠ³ΠΈ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ Π²ΠΎ врСмя Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΈΠ³Ρ€Ρ‹.

// Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ консоли ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ
Wudgine::Debug::Console::Initialize();

// РСгистрация ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹
Wudgine::Debug::Console::RegisterCommand("spawn_enemy", [](const std::vector<std::string>& args) {
    if (args.size() < 2) {
        return "ИспользованиС: spawn_enemy <Ρ‚ΠΈΠΏ> <количСство>";
    }
    
    std::string enemyType = args[0];
    int count = std::stoi(args[1]);
    
    for (int i = 0; i < count; i++) {
        // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Π²Ρ€Π°Π³Π° ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ°
        SpawnEnemy(enemyType);
    }
    
    return "Π‘ΠΎΠ·Π΄Π°Π½ΠΎ " + std::to_string(count) + " Π²Ρ€Π°Π³ΠΎΠ² Ρ‚ΠΈΠΏΠ° " + enemyType;
});

// Π’Ρ‹Π²ΠΎΠ΄ сообщСния Π² консоль
Wudgine::Debug::Console::Log("Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ ΠΈΠ³Ρ€Ρ‹ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π°");
Wudgine::Debug::Console::LogWarning("РСсурс Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½: textures/missing.png");
Wudgine::Debug::Console::LogError("ΠšΡ€ΠΈΡ‚ΠΈΡ‡Π΅ΡΠΊΠ°Ρ ошибка ΠΏΡ€ΠΈ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ΅ уровня");

Визуализация ΠΎΡ‚Π»Π°Π΄ΠΎΡ‡Π½ΠΎΠΉ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ

// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΎΡ‚Π»Π°Π΄ΠΎΡ‡Π½ΠΎΠ³ΠΎ Ρ€Π΅Π½Π΄Π΅Ρ€Π΅Ρ€Π°
Wudgine::Debug::DebugRenderer debugRenderer;

// ΠžΡ‚Ρ€ΠΈΡΠΎΠ²ΠΊΠ° ΠΎΡ‚Π»Π°Π΄ΠΎΡ‡Π½Ρ‹Ρ… ΠΏΡ€ΠΈΠΌΠΈΡ‚ΠΈΠ²ΠΎΠ²
void Update(float deltaTime) {
    // ΠžΡ‚Ρ€ΠΈΡΠΎΠ²ΠΊΠ° ΠΊΠΎΠ»Π»Π°ΠΉΠ΄Π΅Ρ€ΠΎΠ²
    for (auto entity : physicsSystem.GetEntities()) {
        auto& collider = world.GetComponent<Wudgine::Physics::ColliderComponent>(entity);
        auto& transform = world.GetComponent<Wudgine::ECS::TransformComponent>(entity);
        
        // ΠžΡ‚Ρ€ΠΈΡΠΎΠ²ΠΊΠ° ΠΊΠΎΠ»Π»Π°ΠΉΠ΄Π΅Ρ€Π° Π² зависимости ΠΎΡ‚ Π΅Π³ΠΎ Ρ‚ΠΈΠΏΠ°
        switch (collider.type) {
            case Wudgine::Physics::ColliderType::Box:
                debugRenderer.DrawBox(transform.position, collider.size, transform.rotation, 
                                     Wudgine::Math::Color(0, 1, 0, 0.5f));
                break;
            case Wudgine::Physics::ColliderType::Sphere:
                debugRenderer.DrawSphere(transform.position, collider.radius, 
                                        Wudgine::Math::Color(0, 1, 0, 0.5f));
                break;
        }
    }
    
    // ΠžΡ‚Ρ€ΠΈΡΠΎΠ²ΠΊΠ° ΠΏΡƒΡ‚Π΅ΠΉ Π½Π°Π²ΠΈΠ³Π°Ρ†ΠΈΠΈ
    for (auto& path : navigationSystem.GetActivePaths()) {
        debugRenderer.DrawPath(path.points, Wudgine::Math::Color(0, 0, 1, 1.0f));
    }
    
    // ΠžΡ‚Ρ€ΠΈΡΠΎΠ²ΠΊΠ° Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠΉ ΠΈ Π²Π΅ΠΊΡ‚ΠΎΡ€ΠΎΠ²
    debugRenderer.DrawArrow(player.position, player.position + player.velocity * 2.0f, 
                           Wudgine::Math::Color(1, 0, 0, 1.0f));
}

ΠŸΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ

ВстроСнный ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊ

Wudgine Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ встроСнный ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊ для измСрСния ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… частСй ΠΈΠ³Ρ€Ρ‹.

// Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ°
Wudgine::Profiling::Profiler::Initialize();

// ΠŸΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈΠ»ΠΈ Π±Π»ΠΎΠΊΠ° ΠΊΠΎΠ΄Π°
void Update(float deltaTime) {
    WUDGINE_PROFILE_FUNCTION(); // АвтоматичСски ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΡƒΠ΅Ρ‚ всю Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ
    
    {
        WUDGINE_PROFILE_SCOPE("Physics Update"); // ΠŸΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ Π±Π»ΠΎΠΊΠ° ΠΊΠΎΠ΄Π°
        physicsSystem.Update(deltaTime);
    }
    
    {
        WUDGINE_PROFILE_SCOPE("AI Update");
        aiSystem.Update(deltaTime);
    }
    
    {
        WUDGINE_PROFILE_SCOPE("Rendering");
        renderSystem.Render();
    }
}

// Π‘ΠΎΡ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² профилирования
void OnGameExit() {
    Wudgine::Profiling::Profiler::SaveResults("profile_results.json");
}

Π˜Π½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΡ с внСшними ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ°ΠΌΠΈ

// Π˜Π½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΡ с Tracy Profiler
#include "TracyWudgine.h"

void GameLoop() {
    while (running) {
        ZoneScoped; // Tracy: ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ всСго ΠΊΠ°Π΄Ρ€Π°
        
        {
            ZoneScopedN("Input Processing"); // Tracy: имСнованная Π·ΠΎΠ½Π° профилирования
            ProcessInput();
        }
        
        {
            ZoneScopedN("Update");
            Update(deltaTime);
        }
        
        {
            ZoneScopedN("Render");
            Render();
        }
        
        FrameMark; // Tracy: ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΊΠ° ΠΊΠΎΠ½Ρ†Π° ΠΊΠ°Π΄Ρ€Π°
    }
}

ΠžΡ‚Π»Π°Π΄ΠΊΠ° памяти

ΠžΡ‚ΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ΡƒΡ‚Π΅Ρ‡Π΅ΠΊ памяти

// Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ отслСТивания памяти
Wudgine::Debug::MemoryTracker::Initialize();

// ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ статистики использования памяти
void DisplayMemoryStats() {
    auto stats = Wudgine::Debug::MemoryTracker::GetStats();
    
    std::cout << "Бтатистика памяти:" << std::endl;
    std::cout << "- ВсСго Π²Ρ‹Π΄Π΅Π»Π΅Π½ΠΎ: " << stats.totalAllocated / (1024 * 1024) << " ΠœΠ‘" << std::endl;
    std::cout << "- ВсСго освобоТдСно: " << stats.totalFreed / (1024 * 1024) << " ΠœΠ‘" << std::endl;
    std::cout << "- Π’Π΅ΠΊΡƒΡ‰Π΅Π΅ использованиС: " << stats.currentUsage / (1024 * 1024) << " ΠœΠ‘" << std::endl;
    std::cout << "- ПиковоС использованиС: " << stats.peakUsage / (1024 * 1024) << " ΠœΠ‘" << std::endl;
    std::cout << "- ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹Ρ… Π²Ρ‹Π΄Π΅Π»Π΅Π½ΠΈΠΉ: " << stats.activeAllocations << std::endl;
}

Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ снимков памяти для сравнСния

// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ снимка памяти для сравнСния
void CheckForLeaks() {
    // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ снимка Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ состояния памяти
    auto snapshot1 = Wudgine::Debug::MemoryTracker::CreateSnapshot();
    
    // Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ ΡƒΡ‚Π΅Ρ‡ΠΊΠΈ
    LoadLevel("test_level");
    UnloadLevel("test_level");
    
    // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Π²Ρ‚ΠΎΡ€ΠΎΠ³ΠΎ снимка
    auto snapshot2 = Wudgine::Debug::MemoryTracker::CreateSnapshot();
    
    // Π‘Ρ€Π°Π²Π½Π΅Π½ΠΈΠ΅ снимков для выявлСния ΡƒΡ‚Π΅Ρ‡Π΅ΠΊ
    auto diff = Wudgine::Debug::MemoryTracker::CompareSnapshots(snapshot1, snapshot2);
    
    if (diff.newAllocations.empty()) {
        std::cout << "Π£Ρ‚Π΅Ρ‡Π΅ΠΊ памяти Π½Π΅ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΎ!" << std::endl;
    } else {
        std::cout << "ΠžΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½Ρ‹ ΠΏΠΎΡ‚Π΅Π½Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Π΅ ΡƒΡ‚Π΅Ρ‡ΠΊΠΈ памяти:" << std::endl;
        for (const auto& alloc : diff.newAllocations) {
            std::cout << "- " << alloc.size << " Π±Π°ΠΉΡ‚ Π² " << alloc.file << ":" << alloc.line << std::endl;
        }
    }
}

ΠžΡ‚Π»Π°Π΄ΠΊΠ° Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³Π°

Визуализация Π±ΡƒΡ„Π΅Ρ€ΠΎΠ² Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³Π°

// ΠžΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… Π±ΡƒΡ„Π΅Ρ€ΠΎΠ² Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³Π°
void RenderDebugBuffers() {
    if (Wudgine::Debug::ImGui::Begin("Debug Buffers")) {
        // ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ тСкстур Π±ΡƒΡ„Π΅Ρ€ΠΎΠ²
        auto colorBuffer = renderer.GetColorBufferTexture();
        auto depthBuffer = renderer.GetDepthBufferTexture();
        auto normalBuffer = renderer.GetGBufferTexture(Wudgine::Rendering::GBufferType::Normal);
        auto velocityBuffer = renderer.GetGBufferTexture(Wudgine::Rendering::GBufferType::Velocity);
        
        // ΠžΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π±ΡƒΡ„Π΅Ρ€ΠΎΠ²
        Wudgine::Debug::ImGui::Text("Color Buffer");
        Wudgine::Debug::ImGui::Image(colorBuffer, ImVec2(200, 200));
        
        Wudgine::Debug::ImGui::Text("Depth Buffer");
        Wudgine::Debug::ImGui::Image(depthBuffer, ImVec2(200, 200));
        
        Wudgine::Debug::ImGui::Text("Normal Buffer");
        Wudgine::Debug::ImGui::Image(normalBuffer, ImVec2(200, 200));
        
        Wudgine::Debug::ImGui::Text("Velocity Buffer");
        Wudgine::Debug::ImGui::Image(velocityBuffer, ImVec2(200, 200));
        
        Wudgine::Debug::ImGui::End();
    }
}

ΠžΡ‚Π»Π°Π΄ΠΊΠ° ΡˆΠ΅ΠΉΠ΄Π΅Ρ€ΠΎΠ²

// Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ ΡˆΠ΅ΠΉΠ΄Π΅Ρ€ΠΎΠ²
Wudgine::Rendering::ShaderDebugger::Initialize();

// ΠžΡ‚Π»Π°Π΄ΠΊΠ° ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ ΡˆΠ΅ΠΉΠ΄Π΅Ρ€Π°
void DebugShader(const std::string& shaderName) {
    auto debugInfo = Wudgine::Rendering::ShaderDebugger::DebugShader(shaderName);
    
    std::cout << "ΠžΡ‚Π»Π°Π΄ΠΊΠ° ΡˆΠ΅ΠΉΠ΄Π΅Ρ€Π°: " << shaderName << std::endl;
    std::cout << "- ВрСмя компиляции: " << debugInfo.compilationTimeMs << " мс" << std::endl;
    std::cout << "- ИспользованиС рСгистров: " << debugInfo.registerUsage << "%" << std::endl;
    
    if (!debugInfo.warnings.empty()) {
        std::cout << "ΠŸΡ€Π΅Π΄ΡƒΠΏΡ€Π΅ΠΆΠ΄Π΅Π½ΠΈΡ:" << std::endl;
        for (const auto& warning : debugInfo.warnings) {
            std::cout << "- " << warning << std::endl;
        }
    }
}

ΠžΡ‚Π»Π°Π΄ΠΊΠ° Ρ„ΠΈΠ·ΠΈΠΊΠΈ

Визуализация физичСских ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ²

// Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Ρ„ΠΈΠ·ΠΈΠΊΠΈ
Wudgine::Physics::Debug::EnableVisualization();

// Настройка ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ
Wudgine::Physics::Debug::SetVisualizationOptions({
    .showColliders = true,
    .showContacts = true,
    .showJoints = true,
    .showAABBs = false,
    .showVelocities = true,
    .colliderColor = Wudgine::Math::Color(0, 1, 0, 0.5f),
    .contactColor = Wudgine::Math::Color(1, 0, 0, 1.0f),
    .jointColor = Wudgine::Math::Color(0, 0, 1, 1.0f),
    .velocityColor = Wudgine::Math::Color(1, 1, 0, 1.0f)
});

ΠžΡ‚Π»Π°Π΄ΠΊΠ° столкновСний

// РСгистрация ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠ³ΠΎ Π²Ρ‹Π·ΠΎΠ²Π° для ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ столкновСний
Wudgine::Physics::Debug::RegisterCollisionCallback([](const Wudgine::Physics::CollisionInfo& info) {
    std::cout << "Π‘Ρ‚ΠΎΠ»ΠΊΠ½ΠΎΠ²Π΅Π½ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌΠΈ " << info.entityA << " ΠΈ " << info.entityB << std::endl;
    std::cout << "- Π’ΠΎΡ‡ΠΊΠ° ΠΊΠΎΠ½Ρ‚Π°ΠΊΡ‚Π°: " << info.contactPoint.x << ", " 
              << info.contactPoint.y << ", " << info.contactPoint.z << std::endl;
    std::cout << "- ΠΠΎΡ€ΠΌΠ°Π»ΡŒ: " << info.normal.x << ", " 
              << info.normal.y << ", " << info.normal.z << std::endl;
    std::cout << "- Π“Π»ΡƒΠ±ΠΈΠ½Π° проникновСния: " << info.penetrationDepth << std::endl;
    
    // МоТно Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚ΠΎΡ‡ΠΊΡƒ ΠΊΠΎΠ½Ρ‚Π°ΠΊΡ‚Π°
    Wudgine::Debug::DebugRenderer::DrawSphere(info.contactPoint, 0.1f, 
                                             Wudgine::Math::Color(1, 0, 0, 1.0f), 2.0f);
});

ΠžΡ‚Π»Π°Π΄ΠΊΠ° искусствСнного ΠΈΠ½Ρ‚Π΅Π»Π»Π΅ΠΊΡ‚Π°

Визуализация повСдСния ИИ

// Визуализация Π·ΠΎΠ½ восприятия ИИ
void DebugAIPerception() {
    for (auto entity : aiSystem.GetEntities()) {
        auto& perception = world.GetComponent<Wudgine::AI::PerceptionComponent>(entity);
        auto& transform = world.GetComponent<Wudgine::ECS::TransformComponent>(entity);
        
        // Визуализация Π·ΠΎΠ½Ρ‹ видимости
        if (perception.hasVision) {
            debugRenderer.DrawCone(transform.position, transform.forward, 
                                  perception.visionRange, perception.visionAngle,
                                  Wudgine::Math::Color(1, 1, 0, 0.3f));
        }
        
        // Визуализация Π·ΠΎΠ½Ρ‹ ΡΠ»Ρ‹ΡˆΠΈΠΌΠΎΡΡ‚ΠΈ
        if (perception.hasHearing) {
            debugRenderer.DrawSphere(transform.position, perception.hearingRange,
                                    Wudgine::Math::Color(0, 1, 1, 0.3f));
        }
        
        // Визуализация ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½Π½Ρ‹Ρ… Ρ†Π΅Π»Π΅ΠΉ
        for (const auto& target : perception.detectedTargets) {
            debugRenderer.DrawLine(transform.position, target.position,
                                  Wudgine::Math::Color(1, 0, 0, 1.0f));
        }
    }
}

ΠžΡ‚Π»Π°Π΄ΠΊΠ° Π΄Π΅Ρ€Π΅Π²ΡŒΠ΅Π² повСдСния

// Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ Π΄Π΅Ρ€Π΅Π²ΡŒΠ΅Π² повСдСния
Wudgine::AI::BehaviorTreeDebugger::Initialize();

// РСгистрация Π΄Π΅Ρ€Π΅Π²Π° повСдСния для ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ
void RegisterBehaviorTreeForDebugging(Wudgine::AI::BehaviorTree* tree, const std::string& name) {
    Wudgine::AI::BehaviorTreeDebugger::RegisterTree(tree, name);
}

// ΠžΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ состояния Π΄Π΅Ρ€Π΅Π²Π° повСдСния
void RenderBehaviorTreeDebugger() {
    if (Wudgine::Debug::ImGui::Begin("Behavior Tree Debugger")) {
        // Π’Ρ‹Π±ΠΎΡ€ Π΄Π΅Ρ€Π΅Π²Π° повСдСния для отобраТСния
        static int selectedTree = 0;
        auto treeNames = Wudgine::AI::BehaviorTreeDebugger::GetRegisteredTreeNames();
        
        if (Wudgine::Debug::ImGui::Combo("Tree", &selectedTree, treeNames)) {
            Wudgine::AI::BehaviorTreeDebugger::SetActiveTree(treeNames[selectedTree]);
        }
        
        // ΠžΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ структуры Π΄Π΅Ρ€Π΅Π²Π°
        Wudgine::AI::BehaviorTreeDebugger::RenderActiveTree();
        
        Wudgine::Debug::ImGui::End();
    }
}

ΠžΡ‚Π»Π°Π΄ΠΊΠ° сСти

ΠœΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΈΠ½Π³ сСтСвого Ρ‚Ρ€Π°Ρ„ΠΈΠΊΠ°

// Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΈΠ½Π³Π° сСтСвого Ρ‚Ρ€Π°Ρ„ΠΈΠΊΠ°
Wudgine::Networking::Debug::EnableTrafficMonitoring();

// ΠžΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ статистики сСтСвого Ρ‚Ρ€Π°Ρ„ΠΈΠΊΠ°
void DisplayNetworkStats() {
    auto stats = Wudgine::Networking::Debug::GetTrafficStats();
    
    std::cout << "Бтатистика сСти:" << std::endl;
    std::cout << "- ΠžΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ²: " << stats.packetsSent << std::endl;
    std::cout << "- ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ²: " << stats.packetsReceived << std::endl;
    std::cout << "- ΠžΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½ΠΎ Π±Π°ΠΉΡ‚: " << stats.bytesSent / 1024.0f << " ΠšΠ‘" << std::endl;
    std::cout << "- ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΎ Π±Π°ΠΉΡ‚: " << stats.bytesReceived / 1024.0f << " ΠšΠ‘" << std::endl;
    std::cout << "- БрСдняя Π·Π°Π΄Π΅Ρ€ΠΆΠΊΠ°: " << stats.averagePing << " мс" << std::endl;
    std::cout << "- ΠŸΠΎΡ‚Π΅Ρ€ΡΠ½ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ²: " << stats.packetsLost << " (" 
              << (stats.packetsSent > 0 ? (stats.packetsLost * 100.0f / stats.packetsSent) : 0.0f) 
              << "%)" << std::endl;
}

// Π›ΠΎΠ³ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ сСтСвых сообщСний
Wudgine::Networking::Debug::SetMessageLoggingLevel(Wudgine::Networking::Debug::LogLevel::Verbose);

Бимуляция сСтСвых условий

// Настройка симуляции сСтСвых условий
void SimulateNetworkConditions() {
    Wudgine::Networking::Debug::NetworkConditions conditions;
    
    // Бимуляция ΠΏΠ»ΠΎΡ…ΠΎΠ³ΠΎ соСдинСния
    conditions.packetLossPercentage = 5.0f;  // 5% ΠΏΠΎΡ‚Π΅Ρ€ΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ²
    conditions.minimumLatencyMs = 50;        // Минимальная Π·Π°Π΄Π΅Ρ€ΠΆΠΊΠ° 50 мс
    conditions.additionalRandomLatencyMs = 100; // Блучайная Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Π°Ρ Π·Π°Π΄Π΅Ρ€ΠΆΠΊΠ° Π΄ΠΎ 100 мс
    conditions.jitterMs = 20;                // Π”ΠΆΠΈΡ‚Ρ‚Π΅Ρ€ 20 мс
    
    Wudgine::Networking::Debug::SetNetworkConditions(conditions);
    
    // Запуск симуляции Π½Π° 60 сСкунд
    Wudgine::Networking::Debug::EnableNetworkSimulation(true, 60.0f);
}

АвтоматизированноС тСстированиС

ΠœΠΎΠ΄ΡƒΠ»ΡŒΠ½ΠΎΠ΅ тСстированиС

// ΠŸΡ€ΠΈΠΌΠ΅Ρ€ ΠΌΠΎΠ΄ΡƒΠ»ΡŒΠ½ΠΎΠ³ΠΎ тСста с использованиСм встроСнного Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠ° тСстирования
WUDGINE_TEST_CASE("Physics - Collision Detection") {
    // Настройка тСстового окруТСния
    Wudgine::Physics::World physicsWorld;
    
    // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ тСстовых ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ²
    auto boxA = physicsWorld.CreateBox({0, 0, 0}, {1, 1, 1}, 1.0f);
    auto boxB = physicsWorld.CreateBox({0.5f, 0, 0}, {1, 1, 1}, 1.0f);
    
    // Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ тСста
    physicsWorld.Step(1.0f / 60.0f);
    
    // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ²
    auto contacts = physicsWorld.GetContacts();
    WUDGINE_CHECK(!contacts.empty());
    WUDGINE_CHECK(contacts[0].entityA == boxA || contacts[0].entityA == boxB);
    WUDGINE_CHECK(contacts[0].entityB == boxA || contacts[0].entityB == boxB);
    WUDGINE_CHECK(contacts[0].entityA != contacts[0].entityB);
}

Π˜Π½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΎΠ½Π½ΠΎΠ΅ тСстированиС

// ΠŸΡ€ΠΈΠΌΠ΅Ρ€ ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΎΠ½Π½ΠΎΠ³ΠΎ тСста
WUDGINE_TEST_CASE("Game Systems Integration") {
    // Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ ΠΈΠ³Ρ€ΠΎΠ²Ρ‹Ρ… систСм
    Wudgine::ECS::World world;
    Wudgine::Physics::PhysicsSystem physicsSystem(&world);
    Wudgine::AI::AISystem aiSystem(&world);
    
    // Настройка тСстового сцСнария
    auto player = world.CreateEntity();
    world.AddComponent<Wudgine::ECS::TransformComponent>(player, {{0, 0, 0}, {0, 0, 0, 1}, {1, 1, 1}});
    world.AddComponent<Wudgine::Physics::RigidbodyComponent>(player, {1.0f, false});
    
    auto enemy = world.CreateEntity();
    world.AddComponent<Wudgine::ECS::TransformComponent>(enemy, {{5, 0, 0}, {0, 0, 0, 1}, {1, 1, 1}});
    world.AddComponent<Wudgine::AI::BehaviorComponent>(enemy, {"chase_player"});
    
    // Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ тСстового сцСнария
    for (int i = 0; i < 60; i++) {
        physicsSystem.Update(1.0f / 60.0f);
        aiSystem.Update(1.0f / 60.0f);
    }
    
    // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ²
    auto& enemyTransform = world.GetComponent<Wudgine::ECS::TransformComponent>(enemy);
    auto& playerTransform = world.GetComponent<Wudgine::ECS::TransformComponent>(player);
    
    // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Π²Ρ€Π°Π³ приблизился ΠΊ ΠΈΠ³Ρ€ΠΎΠΊΡƒ
    float distance = Wudgine::Math::Vector3::Distance(enemyTransform.position, playerTransform.position);
    WUDGINE_CHECK(distance < 5.0f);
}

БтрСсс-тСстированиС

// ΠŸΡ€ΠΈΠΌΠ΅Ρ€ стрСсс-тСста
WUDGINE_TEST_CASE("Rendering System Stress Test") {
    // Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ систСмы Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³Π°
    Wudgine::Rendering::Renderer renderer;
    
    // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ большого количСства ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² для Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³Π°
    const int objectCount = 10000;
    std::vector<Wudgine::Rendering::MeshInstance> instances;
    
    auto mesh = Wudgine::Resources::ResourceManager::LoadMesh("models/cube.obj");
    auto material = Wudgine::Resources::ResourceManager::LoadMaterial("materials/standard.mat");
    
    for (int i = 0; i < objectCount; i++) {
        Wudgine::Rendering::MeshInstance instance;
        instance.mesh = mesh;
        instance.material = material;
        instance.transform = Wudgine::Math::Matrix4x4::Translation(
            Wudgine::Math::Vector3(
                Wudgine::Math::Random::Range(-100.0f, 100.0f),
                Wudgine::Math::Random::Range(-100.0f, 100.0f),
                Wudgine::Math::Random::Range(-100.0f, 100.0f)
            )
        );
        instances.push_back(instance);
    }
    
    // Π˜Π·ΠΌΠ΅Ρ€Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³Π°
    Wudgine::Profiling::ScopedTimer timer("Rendering Stress Test");
    
    for (int frame = 0; frame < 100; frame++) {
        renderer.BeginFrame();
        renderer.RenderInstances(instances);
        renderer.EndFrame();
    }
    
    auto elapsedTime = timer.GetElapsedMilliseconds();
    auto averageFrameTime = elapsedTime / 100.0f;
    
    std::cout << "БтрСсс-тСст Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³Π°:" << std::endl;
    std::cout << "- ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ²: " << objectCount << std::endl;
    std::cout << "- ΠžΠ±Ρ‰Π΅Π΅ врСмя: " << elapsedTime << " мс" << std::endl;
    std::cout << "- Π‘Ρ€Π΅Π΄Π½Π΅Π΅ врСмя ΠΊΠ°Π΄Ρ€Π°: " << averageFrameTime << " мс" << std::endl;
    std::cout << "- Π‘Ρ€Π΅Π΄Π½ΠΈΠΉ FPS: " << 1000.0f / averageFrameTime << std::endl;
    
    // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ²
    WUDGINE_CHECK(averageFrameTime < 33.3f); // ΠœΠΈΠ½ΠΈΠΌΡƒΠΌ 30 FPS
}

Анализ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ CPU ΠΈ GPU

Анализ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ CPU

// Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π°Π½Π°Π»ΠΈΠ·Π° ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ CPU
Wudgine::Profiling::CPUProfiler::Initialize();

// Запуск Π°Π½Π°Π»ΠΈΠ·Π°
void AnalyzeCPUPerformance() {
    Wudgine::Profiling::CPUProfiler::BeginSession("GameLoop");
    
    // Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΈΠ³Ρ€ΠΎΠ²ΠΎΠ³ΠΎ Ρ†ΠΈΠΊΠ»Π°
    for (int i = 0; i < 1000; i++) {
        {
            WUDGINE_CPU_PROFILE_SCOPE("Input");
            ProcessInput();
        }
        
        {
            WUDGINE_CPU_PROFILE_SCOPE("Update");
            Update(1.0f / 60.0f);
        }
        
        {
            WUDGINE_CPU_PROFILE_SCOPE("Render");
            Render();
        }
    }
    
    // Π—Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠ΅ Π°Π½Π°Π»ΠΈΠ·Π° ΠΈ сохранСниС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ²
    Wudgine::Profiling::CPUProfiler::EndSession();
    Wudgine::Profiling::CPUProfiler::SaveResults("cpu_profile.json");
}

Анализ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ GPU

// Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π°Π½Π°Π»ΠΈΠ·Π° ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ GPU
Wudgine::Profiling::GPUProfiler::Initialize();

// Запуск Π°Π½Π°Π»ΠΈΠ·Π°
void AnalyzeGPUPerformance() {
    Wudgine::Profiling::GPUProfiler::BeginSession("RenderingPipeline");
    
    // Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³Π°
    for (int i = 0; i < 100; i++) {
        renderer.BeginFrame();
        
        {
            WUDGINE_GPU_PROFILE_SCOPE("Shadow Maps");
            renderer.RenderShadowMaps();
        }
        
        {
            WUDGINE_GPU_PROFILE_SCOPE("GBuffer");
            renderer.RenderGBuffer();
        }
        
        {
            WUDGINE_GPU_PROFILE_SCOPE("Lighting");
            renderer.RenderLighting();
        }
        
        {
            WUDGINE_GPU_PROFILE_SCOPE("Post-Processing");
            renderer.RenderPostProcessing();
        }
        
        renderer.EndFrame();
    }
    
    // Π—Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠ΅ Π°Π½Π°Π»ΠΈΠ·Π° ΠΈ сохранСниС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ²
    Wudgine::Profiling::GPUProfiler::EndSession();
    Wudgine::Profiling::GPUProfiler::SaveResults("gpu_profile.json");
}

ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ использования

ΠžΡ‚Π»Π°Π΄ΠΊΠ° ΡƒΡ‚Π΅Ρ‡Π΅ΠΊ памяти

// ΠŸΡ€ΠΈΠΌΠ΅Ρ€ ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ ΡƒΡ‚Π΅Ρ‡Π΅ΠΊ памяти
void DebugMemoryLeaks() {
    // Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ отслСТивания памяти
    Wudgine::Debug::MemoryTracker::Initialize();
    
    // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ снимка памяти ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ΠΌ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ
    auto beforeSnapshot = Wudgine::Debug::MemoryTracker::CreateSnapshot();
    
    // Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ ΡƒΡ‚Π΅Ρ‡ΠΊΠΈ
    {
        // НамСрСнная ΡƒΡ‚Π΅Ρ‡ΠΊΠ° памяти для дСмонстрации
        auto* leakedData = new char[1024 * 1024]; // 1 ΠœΠ‘
        std::cout << "Π’Ρ‹Π΄Π΅Π»Π΅Π½ΠΎ " << leakedData << std::endl;
        // ΠžΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΠ΅Ρ‚ delete[]
    }
    
    // ΠŸΡ€ΠΈΠ½ΡƒΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ сбор мусора (Ссли ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΠΌΠΎ)
    Wudgine::Memory::GarbageCollector::Collect();
    
    // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ снимка памяти послС выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ
    auto afterSnapshot = Wudgine::Debug::MemoryTracker::CreateSnapshot();
    
    // Π‘Ρ€Π°Π²Π½Π΅Π½ΠΈΠ΅ снимков для выявлСния ΡƒΡ‚Π΅Ρ‡Π΅ΠΊ
    auto diff = Wudgine::Debug::MemoryTracker::CompareSnapshots(beforeSnapshot, afterSnapshot);
    
    // Π’Ρ‹Π²ΠΎΠ΄ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ²
    if (diff.newAllocations.empty()) {
        std::cout << "Π£Ρ‚Π΅Ρ‡Π΅ΠΊ памяти Π½Π΅ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΎ!" << std::endl;
    } else {
        std::cout << "ΠžΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½Ρ‹ ΠΏΠΎΡ‚Π΅Π½Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Π΅ ΡƒΡ‚Π΅Ρ‡ΠΊΠΈ памяти:" << std::endl;
        for (const auto& alloc : diff.newAllocations) {
            std::cout << "- " << alloc.size << " Π±Π°ΠΉΡ‚ Π² " << alloc.file << ":" << alloc.line << std::endl;
        }
    }
}

ΠŸΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ ΠΈΠ³Ρ€Ρ‹

// ΠŸΡ€ΠΈΠΌΠ΅Ρ€ профилирования ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ ΠΈΠ³Ρ€Ρ‹
void ProfileGamePerformance() {
    // Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ°
    Wudgine::Profiling::Profiler::Initialize();
    
    // Настройка ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² профилирования
    Wudgine::Profiling::ProfilerSettings settings;
    settings.captureFrameCount = 100;     // ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ ΠΊΠ°Π΄Ρ€ΠΎΠ² для профилирования
    settings.samplingFrequency = 1000;    // Частота сэмплирования (Π“Ρ†)
    settings.outputFile = "game_profile.json";
    
    Wudgine::Profiling::Profiler::Configure(settings);
    
    // Запуск профилирования
    Wudgine::Profiling::Profiler::StartCapture();
    
    // Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΈΠ³Ρ€ΠΎΠ²ΠΎΠ³ΠΎ Ρ†ΠΈΠΊΠ»Π°
    for (int i = 0; i < settings.captureFrameCount; i++) {
        WUDGINE_PROFILE_FRAME("Frame " + std::to_string(i));
        
        {
            WUDGINE_PROFILE_SCOPE("Input");
            ProcessInput();
        }
        
        {
            WUDGINE_PROFILE_SCOPE("Physics");
            physicsSystem.Update(1.0f / 60.0f);
        }
        
        {
            WUDGINE_PROFILE_SCOPE("AI");
            aiSystem.Update(1.0f / 60.0f);
        }
        
        {
            WUDGINE_PROFILE_SCOPE("Game Logic");
            gameLogicSystem.Update(1.0f / 60.0f);
        }
        
        {
            WUDGINE_PROFILE_SCOPE("Rendering");
            renderSystem.Render();
        }
    }
    
    // ΠžΡΡ‚Π°Π½ΠΎΠ²ΠΊΠ° профилирования ΠΈ сохранСниС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ²
    Wudgine::Profiling::Profiler::StopCapture();
    
    // Анализ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ²
    auto results = Wudgine::Profiling::Profiler::GetResults();
    
    std::cout << "Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ профилирования:" << std::endl;
    std::cout << "- Π‘Ρ€Π΅Π΄Π½Π΅Π΅ врСмя ΠΊΠ°Π΄Ρ€Π°: " << results.averageFrameTime << " мс" << std::endl;
    std::cout << "- МинимальноС врСмя ΠΊΠ°Π΄Ρ€Π°: " << results.minFrameTime << " мс" << std::endl;
    std::cout << "- МаксимальноС врСмя ΠΊΠ°Π΄Ρ€Π°: " << results.maxFrameTime << " мс" << std::endl;
    std::cout << "- 99-ΠΉ ΠΏΡ€ΠΎΡ†Π΅Π½Ρ‚ΠΈΠ»ΡŒ: " << results.percentile99 << " мс" << std::endl;
    
    // Π’Ρ‹Π²ΠΎΠ΄ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ выполнСния ΠΏΠΎ катСгориям
    for (const auto& category : results.categories) {
        std::cout << "- " << category.name << ": " 
                  << category.averageTime << " мс (" 
                  << (category.averageTime / results.averageFrameTime * 100.0f) << "%)" << std::endl;
    }
}

БвязанныС Ρ€Π°Π·Π΄Π΅Π»Ρ‹

Wudgine β€’ Β© 2025