تخطَّ إلى المحتوى
ARAB CODEمجتمع المطورين العرب

محرك العب مصغر

cppv1MITنُشر ٢٠ أغسطس ٢٠٢٦· ♥ 0 · ⬇ 1 · 💬 0

محرك اللعب

/**
 * ╔═══════════════════════════════════════════════════════════════════════════╗
 * ║                    SovereignX Mini Game Engine v1.0                       ║
 * ║                    محرك ألعاب SovereignX المصغر                          ║
 * ╠═══════════════════════════════════════════════════════════════════════════╣
 * ║  محرك ألعاب 3D بسيط و احترافي مكتوب بلغة C++ في ملف واحد                ║
 * ║  يدعم: نظام كيانات (ECS) - كاميرا FPS - إضاءة Phong - مشاهد 3D         ║
 * ╠═══════════════════════════════════════════════════════════════════════════╣
 * ║  المتطلبات:                                                               ║
 * ║    - GLFW3        (نافذة و إدخال)  https://www.glfw.org                   ║
 * ║    - GLAD         (محمل OpenGL)    https://glad.dav1d.de                  ║
 * ║      قم بتوليد: C/C++ | gl Version 3.3 | Core Profile | Generate Loader   ║
 * ║      ثم ضع glad.h في مجلد include و glad.c بجانب هذا الملف               ║
 * ╠═══════════════════════════════════════════════════════════════════════════╣
 * ║  التجميع (Linux):                                                         ║
 * ║    g++ engine.cpp glad.c -o engine -lglfw -ldl -lpthread -Wall -O2        ║
 * ║  التجميع (Windows MinGW):                                                 ║
 * ║    g++ engine.cpp glad.c -o engine.exe -lglfw3 -lopengl32 -lgdi32 -Wall   ║
 * ╚═══════════════════════════════════════════════════════════════════════════╝
 */

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <cmath>
#include <cstddef>
#include <algorithm>
#include <ctime>

// ============================================================================
// ████████  نظام التسجيل (Logging)  ████████
// ============================================================================
namespace Log {
    enum Level { INFO, WARN, ERROR };
    void msg(Level lvl, const std::string& text) {
        const char* prefix[] = { "[INFO]", "[WARN]", "[ERROR]" };
        const char* color[]  = { "\033[36m", "\033[33m", "\033[31m" };
        std::cout << color[lvl] << prefix[lvl] << " \033[0m" << text << std::endl;
    }
}

// ============================================================================
// ████████  مكتبة الرياضيات (Math Library)  ████████
// ============================================================================
struct Vec2 {
    float x, y;
    Vec2(float x = 0, float y = 0) : x(x), y(y) {}
};

struct Vec3 {
    float x, y, z;
    Vec3(float x = 0, float y = 0, float z = 0) : x(x), y(y), z(z) {}
    Vec3 operator + (const Vec3& o) const { return Vec3(x + o.x, y + o.y, z + o.z); }
    Vec3 operator - (const Vec3& o) const { return Vec3(x - o.x, y - o.y, z - o.z); }
    Vec3 operator * (float s)       const { return Vec3(x * s, y * s, z * s); }
    Vec3 operator / (float s)       const { return Vec3(x / s, y / s, z / s); }
    float dot(const Vec3& o)        const { return x * o.x + y * o.y + z * o.z; }
    Vec3 cross(const Vec3& o)       const {
        return Vec3(y * o.z - z * o.y, z * o.x - x * o.z, x * o.y - y * o.x);
    }
    float length() const { return std::sqrt(dot(*this)); }
    Vec3 normalize() const { float l = length(); return l > 0 ? (*this) / l : Vec3(); }
    Vec3 lerp(const Vec3& o, float t) const { return (*this) * (1 - t) + o * t; }
};

struct Vec4 {
    float x, y, z, w;
    Vec4(float x = 0, float y = 0, float z = 0, float w = 1) : x(x), y(y), z(z), w(w) {}
};

struct Mat4 {
    float m[16];
    Mat4(bool identity = true) {
        for (int i = 0; i < 16; i++) m[i] = 0;
        if (identity) m[0] = m[5] = m[10] = m[15] = 1.0f;
    }
    static Mat4 perspective(float fovDeg, float aspect, float near, float far) {
        Mat4 r(false);
        float tanHalf = std::tan(fovDeg * 3.14159265f / 360.0f);
        r.m[0]  = 1.0f / (aspect * tanHalf);
        r.m[5]  = 1.0f / tanHalf;
        r.m[10] = -(far + near) / (far - near);
        r.m[11] = -1.0f;
        r.m[14] = -(2.0f * far * near) / (far - near);
        return r;
    }
    static Mat4 lookAt(Vec3 eye, Vec3 center, Vec3 up) {
        Vec3 f = (center - eye).normalize();
        Vec3 s = f.cross(up).normalize();
        Vec3 u = s.cross(f);
        Mat4 r;
        r.m[0] = s.x;  r.m[4] = s.y;  r.m[8]  = s.z;  r.m[12] = -s.dot(eye);
        r.m[1] = u.x;  r.m[5] = u.y;  r.m[9]  = u.z;  r.m[13] = -u.dot(eye);
        r.m[2] = -f.x; r.m[6] = -f.y; r.m[10] = -f.z; r.m[14] = f.dot(eye);
        return r;
    }
    static Mat4 translate(Vec3 t) {
        Mat4 r; r.m[12] = t.x; r.m[13] = t.y; r.m[14] = t.z; return r;
    }
    static Mat4 scale(Vec3 s) {
        Mat4 r; r.m[0] = s.x; r.m[5] = s.y; r.m[10] = s.z; return r;
    }
    static Mat4 rotate(float angleDeg, Vec3 axis) {
        float rad = angleDeg * 3.14159265f / 180.0f;
        float c = std::cos(rad), s = std::sin(rad);
        Vec3 a = axis.normalize();
        Mat4 r;
        r.m[0] = c + a.x*a.x*(1-c);       r.m[4] = a.x*a.y*(1-c) - a.z*s;   r.m[8]  = a.x*a.z*(1-c) + a.y*s;
        r.m[1] = a.y*a.x*(1-c) + a.z*s;   r.m[5] = c + a.y*a.y*(1-c);       r.m[9]  = a.y*a.z*(1-c) - a.x*s;
        r.m[2] = a.z*a.x*(1-c) - a.y*s;   r.m[6] = a.z*a.y*(1-c) + a.x*s;   r.m[10] = c + a.z*a.z*(1-c);
        return r;
    }
    Mat4 operator * (const Mat4& o) const {
        Mat4 res(false);
        for (int i = 0; i < 4; i++)
            for (int j = 0; j < 4; j++)
                for (int k = 0; k < 4; k++)
                    res.m[i*4+j] += m[i*4+k] * o.m[k*4+j];
        return res;
    }
};

// ============================================================================
// ████████  نظام الوقت (Time System)  ████████
// ============================================================================
class Time {
    float lastTime = 0;
    float currentTime = 0;
public:
    float deltaTime = 0;
    float totalTime = 0;
    int fps = 0;
    void update() {
        currentTime = (float)glfwGetTime();
        deltaTime = currentTime - lastTime;
        lastTime = currentTime;
        totalTime = currentTime;
        static float fpsTimer = 0; static int fpsCount = 0;
        fpsTimer += deltaTime; fpsCount++;
        if (fpsTimer >= 1.0f) { fps = fpsCount; fpsCount = 0; fpsTimer = 0; }
    }
};

// ============================================================================
// ████████  نظام المظللات (Shader System)  ████████
// ============================================================================
class Shader {
    GLuint programID = 0;
public:
    Shader(const char* vertSrc, const char* fragSrc) {
        GLuint vs = compile(vertSrc, GL_VERTEX_SHADER);
        GLuint fs = compile(fragSrc, GL_FRAGMENT_SHADER);
        programID = glCreateProgram();
        glAttachShader(programID, vs);
        glAttachShader(programID, fs);
        glLinkProgram(programID);
        checkLink();
        glDeleteShader(vs);
        glDeleteShader(fs);
    }
    ~Shader() { if (programID) glDeleteProgram(programID); }
    void use() const { glUseProgram(programID); }
    GLuint id() const { return programID; }

    void setMat4(const char* name, const Mat4& mat) {
        glUniformMatrix4fv(glGetUniformLocation(programID, name), 1, GL_FALSE, mat.m);
    }
    void setVec3(const char* name, Vec3 v) {
        glUniform3f(glGetUniformLocation(programID, name), v.x, v.y, v.z);
    }
    void setVec4(const char* name, Vec4 v) {
        glUniform4f(glGetUniformLocation(programID, name), v.x, v.y, v.z, v.w);
    }
    void setFloat(const char* name, float f) {
        glUniform1f(glGetUniformLocation(programID, name), f);
    }
    void setInt(const char* name, int i) {
        glUniform1i(glGetUniformLocation(programID, name), i);
    }

private:
    GLuint compile(const char* src, GLenum type) {
        GLuint s = glCreateShader(type);
        glShaderSource(s, 1, &src, nullptr);
        glCompileShader(s);
        GLint ok; glGetShaderiv(s, GL_COMPILE_STATUS, &ok);
        if (!ok) {
            char log[1024]; glGetShaderInfoLog(s, 1024, nullptr, log);
            Log::msg(Log::ERROR, std::string("Shader Compile: ") + log);
        }
        return s;
    }
    void checkLink() {
        GLint ok; glGetProgramiv(programID, GL_LINK_STATUS, &ok);
        if (!ok) {
            char log[1024]; glGetProgramInfoLog(programID, 1024, nullptr, log);
            Log::msg(Log::ERROR, std::string("Shader Link: ") + log);
        }
    }
};

// ============================================================================
// ████████  نظام الشبكات (Mesh System)  ████████
// ============================================================================
struct Vertex {
    Vec3 position;
    Vec3 normal;
    Vec2 texCoord;
};

class Mesh {
    GLuint VAO = 0, VBO = 0, EBO = 0;
    GLsizei indexCount = 0;
public:
    Mesh(const std::vector<Vertex>& vertices, const std::vector<GLuint>& indices) {
        indexCount = static_cast<GLsizei>(indices.size());
        glGenVertexArrays(1, &VAO);
        glGenBuffers(1, &VBO);
        glGenBuffers(1, &EBO);
        glBindVertexArray(VAO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, normal));
        glEnableVertexAttribArray(2);
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texCoord));
        glBindVertexArray(0);
    }
    ~Mesh() {
        glDeleteVertexArrays(1, &VAO);
        glDeleteBuffers(1, &VBO);
        glDeleteBuffers(1, &EBO);
    }
    void draw() const {
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, nullptr);
        glBindVertexArray(0);
    }
};

// ============================================================================
// ████████  مولدات الأشكال (Primitive Generators)  ████████
// ============================================================================
std::shared_ptr<Mesh> createCube() {
    std::vector<Vertex> v = {
        // Front
        {Vec3(-0.5f,-0.5f, 0.5f), Vec3(0,0,1), Vec2(0,0)}, {Vec3(0.5f,-0.5f, 0.5f), Vec3(0,0,1), Vec2(1,0)},
        {Vec3(0.5f, 0.5f, 0.5f), Vec3(0,0,1), Vec2(1,1)}, {Vec3(-0.5f, 0.5f, 0.5f), Vec3(0,0,1), Vec2(0,1)},
        // Back
        {Vec3(-0.5f,-0.5f,-0.5f), Vec3(0,0,-1), Vec2(1,0)}, {Vec3(-0.5f, 0.5f,-0.5f), Vec3(0,0,-1), Vec2(1,1)},
        {Vec3(0.5f, 0.5f,-0.5f), Vec3(0,0,-1), Vec2(0,1)}, {Vec3(0.5f,-0.5f,-0.5f), Vec3(0,0,-1), Vec2(0,0)},
        // Top
        {Vec3(-0.5f, 0.5f,-0.5f), Vec3(0,1,0), Vec2(0,1)}, {Vec3(-0.5f, 0.5f, 0.5f), Vec3(0,1,0), Vec2(0,0)},
        {Vec3(0.5f, 0.5f, 0.5f), Vec3(0,1,0), Vec2(1,0)}, {Vec3(0.5f, 0.5f,-0.5f), Vec3(0,1,0), Vec2(1,1)},
        // Bottom
        {Vec3(-0.5f,-0.5f,-0.5f), Vec3(0,-1,0), Vec2(1,1)}, {Vec3(0.5f,-0.5f,-0.5f), Vec3(0,-1,0), Vec2(0,1)},
        {Vec3(0.5f,-0.5f, 0.5f), Vec3(0,-1,0), Vec2(0,0)}, {Vec3(-0.5f,-0.5f, 0.5f), Vec3(0,-1,0), Vec2(1,0)},
        // Right
        {Vec3(0.5f,-0.5f,-0.5f), Vec3(1,0,0), Vec2(1,0)}, {Vec3(0.5f, 0.5f,-0.5f), Vec3(1,0,0), Vec2(1,1)},
        {Vec3(0.5f, 0.5f, 0.5f), Vec3(1,0,0), Vec2(0,1)}, {Vec3(0.5f,-0.5f, 0.5f), Vec3(1,0,0), Vec2(0,0)},
        // Left
        {Vec3(-0.5f,-0.5f,-0.5f), Vec3(-1,0,0), Vec2(0,0)}, {Vec3(-0.5f,-0.5f, 0.5f), Vec3(-1,0,0), Vec2(1,0)},
        {Vec3(-0.5f, 0.5f, 0.5f), Vec3(-1,0,0), Vec2(1,1)}, {Vec3(-0.5f, 0.5f,-0.5f), Vec3(-1,0,0), Vec2(0,1)},
    };
    std::vector<GLuint> i = {
        0,1,2, 2,3,0, 4,5,6, 6,7,4, 8,9,10, 10,11,8,
        12,13,14, 14,15,12, 16,17,18, 18,19,16, 20,21,22, 22,23,20
    };
    return std::make_shared<Mesh>(v, i);
}

std::shared_ptr<Mesh> createPlane(int segments = 1) {
    std::vector<Vertex> v;
    std::vector<GLuint> idx;
    float step = 1.0f / segments;
    for (int z = 0; z <= segments; z++) {
        for (int x = 0; x <= segments; x++) {
            float px = x * step - 0.5f;
            float pz = z * step - 0.5f;
            v.push_back({Vec3(px, 0, pz), Vec3(0,1,0), Vec2(x * step, z * step)});
        }
    }
    for (int z = 0; z < segments; z++) {
        for (int x = 0; x < segments; x++) {
            int a = z * (segments + 1) + x;
            int b = a + 1;
            int c = a + segments + 1;
            int d = c + 1;
            idx.push_back(a); idx.push_back(c); idx.push_back(b);
            idx.push_back(b); idx.push_back(c); idx.push_back(d);
        }
    }
    return std::make_shared<Mesh>(v, idx);
}

// ============================================================================
// ████████  نظام الكاميرا (Camera System)  ████████
// ============================================================================
class Camera {
public:
    Vec3 position;
    Vec3 front, up, right, worldUp;
    float yaw = -90.0f, pitch = 0.0f;
    float moveSpeed = 4.0f;
    float mouseSensitivity = 0.12f;
    float fov = 60.0f;

    Camera(Vec3 pos = Vec3(0, 2, 5)) : position(pos), worldUp(Vec3(0, 1, 0)) {
        updateVectors();
    }
    Mat4 getView() { return Mat4::lookAt(position, position + front, up); }
    Mat4 getProjection(float aspect) { return Mat4::perspective(fov, aspect, 0.1f, 200.0f); }

    void processKeyboard(int dir, float dt) {
        float v = moveSpeed * dt;
        if (dir == 0) position = position + front * v;      // W
        if (dir == 1) position = position - front * v;      // S
        if (dir == 2) position = position - right * v;      // A
        if (dir == 3) position = position + right * v;      // D
        if (dir == 4) position.y += v;                      // Space
        if (dir == 5) position.y -= v;                      // Left Shift
    }
    void processMouse(float xoff, float yoff) {
        xoff *= mouseSensitivity;
        yoff *= mouseSensitivity;
        yaw   += xoff;
        pitch += yoff;
        if (pitch > 89.0f)  pitch = 89.0f;
        if (pitch < -89.0f) pitch = -89.0f;
        updateVectors();
    }
    void processScroll(float yoff) {
        fov -= yoff * 2.0f;
        if (fov < 10.0f) fov = 10.0f;
        if (fov > 90.0f) fov = 90.0f;
    }
private:
    void updateVectors() {
        Vec3 f;
        f.x = std::cos(yaw * 3.14159265f / 180.0f) * std::cos(pitch * 3.14159265f / 180.0f);
        f.y = std::sin(pitch * 3.14159265f / 180.0f);
        f.z = std::sin(yaw * 3.14159265f / 180.0f) * std::cos(pitch * 3.14159265f / 180.0f);
        front = f.normalize();
        right = front.cross(worldUp).normalize();
        up    = right.cross(front).normalize();
    }
};

// ============================================================================
// ████████  نظام الكيانات والمكونات (ECS)  ████████
// ============================================================================
struct Transform {
    Vec3 position;
    Vec3 rotation;
    Vec3 scale;
    Transform(Vec3 p = Vec3(), Vec3 r = Vec3(), Vec3 s = Vec3(1,1,1))
        : position(p), rotation(r), scale(s) {}
    Mat4 getMatrix() const {
        Mat4 t = Mat4::translate(position);
        Mat4 rx = Mat4::rotate(rotation.x, Vec3(1,0,0));
        Mat4 ry = Mat4::rotate(rotation.y, Vec3(0,1,0));
        Mat4 rz = Mat4::rotate(rotation.z, Vec3(0,0,1));
        Mat4 s = Mat4::scale(scale);
        return t * (ry * rx * rz) * s;
    }
};

struct Renderable {
    std::shared_ptr<Mesh> mesh;
    Vec3 color;
    float metallic = 0.0f;
    float roughness = 0.5f;
    Renderable(std::shared_ptr<Mesh> m, Vec3 c = Vec3(1,1,1)) : mesh(m), color(c) {}
};

struct Rotator {
    Vec3 speed;
    Rotator(Vec3 s = Vec3(0, 30, 0)) : speed(s) {}
};

class Entity {
public:
    std::string name;
    Transform transform;
    std::shared_ptr<Renderable> renderable;
    std::shared_ptr<Rotator> rotator;
    bool active = true;

    Entity(const std::string& n) : name(n) {}

    void update(float dt) {
        if (rotator) {
            transform.rotation = transform.rotation + rotator->speed * dt;
        }
    }
};

class Scene {
    std::vector<std::shared_ptr<Entity>> entities;
public:
    void add(std::shared_ptr<Entity> e) { entities.push_back(e); }
    const std::vector<std::shared_ptr<Entity>>& all() const { return entities; }
    void update(float dt) {
        for (auto& e : entities) if (e->active) e->update(dt);
    }
};

// ============================================================================
// ████████  نظام الرسم (Renderer)  ████████
// ============================================================================
class Renderer {
    Shader* shader;
public:
    Renderer(Shader* s) : shader(s) {}

    void begin(Camera& cam, float aspect, Vec3 lightPos, Vec3 lightColor, Vec3 ambient) {
        shader->use();
        shader->setMat4("projection", cam.getProjection(aspect));
        shader->setMat4("view", cam.getView());
        shader->setVec3("lightPos", lightPos);
        shader->setVec3("lightColor", lightColor);
        shader->setVec3("ambientColor", ambient);
        shader->setVec3("viewPos", cam.position);
    }

    void submit(Entity& e) {
        if (!e.renderable || !e.active) return;
        shader->setMat4("model", e.transform.getMatrix());
        shader->setVec3("objectColor", e.renderable->color);
        shader->setFloat("metallic", e.renderable->metallic);
        shader->setFloat("roughness", e.renderable->roughness);
        e.renderable->mesh->draw();
    }

    void render(Scene& scene, Camera& cam, float aspect, Vec3 lightPos, Vec3 lightColor, Vec3 ambient) {
        begin(cam, aspect, lightPos, lightColor, ambient);
        for (auto& e : scene.all()) submit(*e);
    }
};

// ============================================================================
// ████████  شفرات GLSL (Vertex & Fragment)  ████████
// ============================================================================
const char* vertexShaderSource = R"(
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoord;

out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main() {
    FragPos = vec3(model * vec4(aPos, 1.0));
    Normal = mat3(transpose(inverse(model))) * aNormal;
    TexCoord = aTexCoord;
    gl_Position = projection * view * vec4(FragPos, 1.0);
}
)";

const char* fragmentShaderSource = R"(
#version 330 core
out vec4 FragColor;

in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoord;

uniform vec3 objectColor;
uniform vec3 lightPos;
uniform vec3 lightColor;
uniform vec3 ambientColor;
uniform vec3 viewPos;
uniform float metallic;
uniform float roughness;

void main() {
    // Ambient
    vec3 ambient = ambientColor * lightColor * 0.3;

    // Diffuse
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(lightPos - FragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = diff * lightColor;

    // Specular (Blinn-Phong)
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 halfDir = normalize(lightDir + viewDir);
    float spec = pow(max(dot(norm, halfDir), 0.0), 32.0 * (1.0 - roughness));
    vec3 specular = spec * lightColor * metallic;

    vec3 result = (ambient + diffuse + specular) * objectColor;

    // Fog
    float dist = length(viewPos - FragPos);
    float fogFactor = exp(-dist * 0.02);
    fogFactor = clamp(fogFactor, 0.0, 1.0);
    vec3 fogColor = vec3(0.1, 0.1, 0.15);
    result = mix(fogColor, result, fogFactor);

    FragColor = vec4(result, 1.0);
}
)";

// ============================================================================
// ████████  تطبيق المحرك (Application)  ████████
// ============================================================================
class Application {
    GLFWwindow* window = nullptr;
    int width, height;
    std::unique_ptr<Shader> shader;
    std::unique_ptr<Camera> camera;
    std::unique_ptr<Scene> scene;
    std::unique_ptr<Renderer> renderer;
    Time time;
    float lastX = 0, lastY = 0;
    bool firstMouse = true;
    bool wireframe = false;
    bool paused = false;

    // Light animation
    Vec3 lightPos;
    Vec3 lightColor;
    Vec3 ambientColor;

public:
    Application(int w, int h) : width(w), height(h) {}

    bool init() {
        Log::msg(Log::INFO, "جاري تهيئة المحرك...");

        if (!glfwInit()) {
            Log::msg(Log::ERROR, "فشل تهيئة GLFW!");
            return false;
        }

        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        glfwWindowHint(GLFW_SAMPLES, 4);  // Anti-aliasing

        window = glfwCreateWindow(width, height, "SovereignX Engine v1.0 | محرك SovereignX", nullptr, nullptr);
        if (!window) {
            Log::msg(Log::ERROR, "فشل إنشاء النافذة!");
            glfwTerminate();
            return false;
        }

        glfwMakeContextCurrent(window);
        glfwSetWindowUserPointer(window, this);
        glfwSetFramebufferSizeCallback(window, framebufferSizeCallback);
        glfwSetCursorPosCallback(window, mouseCallback);
        glfwSetScrollCallback(window, scrollCallback);
        glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

        if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
            Log::msg(Log::ERROR, "فشل تهيئة GLAD!");
            return false;
        }

        Log::msg(Log::INFO, std::string("OpenGL Version: ") + (const char*)glGetString(GL_VERSION));

        glEnable(GL_DEPTH_TEST);
        glEnable(GL_MULTISAMPLE);
        glEnable(GL_CULL_FACE);
        glCullFace(GL_BACK);
        glFrontFace(GL_CCW);

        shader = std::make_unique<Shader>(vertexShaderSource, fragmentShaderSource);
        camera = std::make_unique<Camera>(Vec3(0, 3, 8));
        scene = std::make_unique<Scene>();
        renderer = std::make_unique<Renderer>(shader.get());

        lightPos = Vec3(5, 8, 5);
        lightColor = Vec3(1.0f, 0.95f, 0.8f);
        ambientColor = Vec3(0.1f, 0.1f, 0.15f);

        buildScene();

        Log::msg(Log::INFO, "تم تهيئة المحرك بنجاح!");
        Log::msg(Log::INFO, "Controls: WASD - Move | Space/Shift - Up/Down | Mouse - Look | ESC - Exit | P - Pause | Tab - Wireframe");
        return true;
    }

    void buildScene() {
        auto cubeMesh = createCube();
        auto planeMesh = createPlane(20);

        // أرضية كبيرة
        auto ground = std::make_shared<Entity>("Ground");
        ground->transform.position = Vec3(0, -0.55f, 0);
        ground->transform.scale = Vec3(40, 1, 40);
        ground->renderable = std::make_shared<Renderable>(planeMesh, Vec3(0.15f, 0.18f, 0.22f));
        ground->renderable->roughness = 0.9f;
        scene->add(ground);

        // شبكة مكعبات
        for (int x = -3; x <= 3; x++) {
            for (int z = -3; z <= 3; z++) {
                if (x == 0 && z == 0) continue;
                auto box = std::make_shared<Entity>("Box_" + std::to_string(x) + "_" + std::to_string(z));
                box->transform.position = Vec3(x * 2.0f, 0.5f, z * 2.0f);
                box->transform.scale = Vec3(0.8f, 0.8f, 0.8f);

                // ألوان متنوعة
                float r = 0.3f + std::abs(std::sin(x * 0.7f)) * 0.7f;
                float g = 0.3f + std::abs(std::sin(z * 0.5f + 1)) * 0.7f;
                float b = 0.3f + std::abs(std::sin((x+z) * 0.3f + 2)) * 0.7f;
                box->renderable = std::make_shared<Renderable>(cubeMesh, Vec3(r, g, b));
                box->renderable->metallic = std::abs(std::sin(x*z*0.5f)) * 0.8f;
                box->renderable->roughness = 0.2f + std::abs(std::cos(x+z)) * 0.6f;

                // بعضها يدور
                if ((x + z) % 3 == 0) {
                    box->rotator = std::make_shared<Rotator>(Vec3(0, 45 + x * 10, 0));
                }
                scene->add(box);
            }
        }

        // مكعب مركزي كبير
        auto center = std::make_shared<Entity>("CenterPiece");
        center->transform.position = Vec3(0, 1.5f, 0);
        center->transform.scale = Vec3(1.5f, 1.5f, 1.5f);
        center->renderable = std::make_shared<Renderable>(cubeMesh, Vec3(0.9f, 0.2f, 0.2f));
        center->renderable->metallic = 0.8f;
        center->renderable->roughness = 0.2f;
        center->rotator = std::make_shared<Rotator>(Vec3(20, 40, 10));
        scene->add(center);

        // أعمدة
        for (int i = 0; i < 8; i++) {
            float angle = i * 3.14159265f * 2.0f / 8.0f;
            float radius = 7.0f;
            auto pillar = std::make_shared<Entity>("Pillar_" + std::to_string(i));
            pillar->transform.position = Vec3(std::cos(angle)*radius, 2.0f, std::sin(angle)*radius);
            pillar->transform.scale = Vec3(0.4f, 4.0f, 0.4f);
            pillar->renderable = std::make_shared<Renderable>(cubeMesh, Vec3(0.6f, 0.6f, 0.65f));
            pillar->renderable->roughness = 0.3f;
            pillar->renderable->metallic = 0.1f;
            scene->add(pillar);
        }
    }

    void run() {
        while (!glfwWindowShouldClose(window)) {
            time.update();

            processInput();

            if (!paused) {
                scene->update(time.deltaTime);

                // تحريك الضوء
                float t = time.totalTime;
                lightPos.x = std::sin(t * 0.5f) * 10.0f;
                lightPos.z = std::cos(t * 0.5f) * 10.0f;
                lightPos.y = 6.0f + std::sin(t * 0.3f) * 2.0f;
            }

            // Clear
            glClearColor(0.05f, 0.05f, 0.08f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

            // Render
            float aspect = (float)width / (float)height;
            renderer->render(*scene, *camera, aspect, lightPos, lightColor, ambientColor);

            glfwSwapBuffers(window);
            glfwPollEvents();
        }
    }

    void processInput() {
        // Exit
        if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
            glfwSetWindowShouldClose(window, true);

        // Pause
        static bool pPressed = false;
        if (glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS) {
            if (!pPressed) { paused = !paused; pPressed = true; }
        } else { pPressed = false; }

        // Wireframe toggle
        static bool tabPressed = false;
        if (glfwGetKey(window, GLFW_KEY_TAB) == GLFW_PRESS) {
            if (!tabPressed) {
                wireframe = !wireframe;
                glPolygonMode(GL_FRONT_AND_BACK, wireframe ? GL_LINE : GL_FILL);
                tabPressed = true;
            }
        } else { tabPressed = false; }

        if (paused) return;

        // Movement
        if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) camera->processKeyboard(0, time.deltaTime);
        if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) camera->processKeyboard(1, time.deltaTime);
        if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) camera->processKeyboard(2, time.deltaTime);
        if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) camera->processKeyboard(3, time.deltaTime);
        if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) camera->processKeyboard(4, time.deltaTime);
        if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) camera->processKeyboard(5, time.deltaTime);

        // Speed boost
        if (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS)
            camera->moveSpeed = 10.0f;
        else
            camera->moveSpeed = 4.0f;
    }

    static void framebufferSizeCallback(GLFWwindow* w, int width, int height) {
        glViewport(0, 0, width, height);
        auto app = static_cast<Application*>(glfwGetWindowUserPointer(w));
        app->width = width; app->height = height;
    }

    static void mouseCallback(GLFWwindow* w, double x, double y) {
        auto app = static_cast<Application*>(glfwGetWindowUserPointer(w));
        if (app->firstMouse) {
            app->lastX = (float)x; app->lastY = (float)y;
            app->firstMouse = false;
        }
        float xoff = (float)x - app->lastX;
        float yoff = app->lastY - (float)y;
        app->lastX = (float)x; app->lastY = (float)y;
        if (!app->paused) app->camera->processMouse(xoff, yoff);
    }

    static void scrollCallback(GLFWwindow* w, double x, double y) {
        auto app = static_cast<Application*>(glfwGetWindowUserPointer(w));
        app->camera->processScroll((float)y);
    }

    ~Application() {
        Log::msg(Log::INFO, "جاري إغلاق المحرك...");
        glfwTerminate();
    }
};

// ============================================================================
// ████████  الدالة الرئيسية (Main Entry Point)  ████████
// ============================================================================
int main() {
    std::cout << "\n";
    std::cout << "  ╔═══════════════════════════════════════════════════════════════╗\n";
    std::cout << "  ║         SovereignX Mini Game Engine v1.0                      ║\n";
    std::cout << "  ║         محرك ألعاب SovereignX المصغر                        ║\n";
    std::cout << "  ╚═══════════════════════════════════════════════════════════════╝\n\n";

    Application app(1280, 720);
    if (!app.init()) {
        Log::msg(Log::ERROR, "فشل تشغيل المحرك!");
        return -1;
    }

    app.run();
    return 0;
}

التعليقات (0)

سجّل الدخول للتعليق.