Загрузка данных


// Полный код с уровнями
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <SDL3/SDL_image.h>
#include <cmath>
#include <vector>
#include <algorithm>
#include <cstring>

const int WIDTH = 640;
const int HEIGHT = 600;
const int FPS = 30;
const float FOV = M_PI / 2.5f;
const int CASTED_RAYS = 320;
const int SCALE = WIDTH / CASTED_RAYS;
const float WALL_HEIGHT_SCALE = 10.0f;
Uint32 fireStartTime = 0;
bool gunFiring = false;

SDL_Window* window = nullptr;
SDL_Renderer* renderer = nullptr;
SDL_Texture* screen_texture = nullptr;
Uint32* screen_buffer = nullptr;

Uint32* baseTexture = nullptr;
int baseTexW = 0, baseTexH = 0;

SDL_Texture* gunTex1 = nullptr;
SDL_Texture* gunTex2 = nullptr;

struct Wall {
    float x1, y1, x2, y2;
    Uint32* tex;
    int texW, texH;
    Wall(float _x1, float _y1, float _x2, float _y2,
         Uint32* _tex = nullptr, int _w = 0, int _h = 0)
        : x1(_x1), y1(_y1), x2(_x2), y2(_y2),
          tex(_tex), texW(_w), texH(_h) {}
};

struct Enemy {
    float x, y;
    float speed = 1.0f;
    int hp = 3;
    Uint32* aliveTex; int aW, aH;
    Uint32* deadTex;  int dW, dH;
    Enemy(float _x, float _y,
          Uint32* a, int aw, int ah,
          Uint32* d, int dw, int dh)
        : x(_x), y(_y), aliveTex(a), aW(aw), aH(ah),
          deadTex(d), dW(dw), dH(dh) {}
};

struct Player {
    float x = 150.0f, y = 150.0f;
    float angle = 0.0f;
    float vx = 0.0f, vy = 0.0f;
    const float accel = 0.4f, decel = 0.5f, maxSpeed = 5.0f;
    float rot_speed = 0.12f;
};

std::vector<Wall> staticWalls;
std::vector<Enemy> enemies;

Uint32* loadPixels(SDL_Surface* surf, int& w, int& h) {
    SDL_Surface* s = SDL_ConvertSurface(surf, SDL_PIXELFORMAT_ARGB8888);
    SDL_DestroySurface(surf);
    w = s->w; h = s->h;
    Uint32* pixels = new Uint32[w * h];
    memcpy(pixels, s->pixels, w * h * sizeof(Uint32));
    SDL_DestroySurface(s);
    return pixels;
}

Uint32* fimozTexAlive = nullptr, *fimozTexDead = nullptr;
int fimozW = 0, fimozH = 0, fimozDW = 0, fimozDH = 0;



void loadLevel1() {
    staticWalls.clear();
    enemies.clear();
    staticWalls = {
        {100,100,300,100, baseTexture, baseTexW, baseTexH},
        {300,100,300,300, baseTexture, baseTexW, baseTexH},
        {300,300,100,300, baseTexture, baseTexW, baseTexH},
        {100,300,100,100, baseTexture, baseTexW, baseTexH}
    };
    enemies.emplace_back(500,200, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
}

void loadLevel2() {
    staticWalls.clear();
    enemies.clear();
    staticWalls = {
        {50,50, 600,50, baseTexture, baseTexW, baseTexH},
        {600,50, 600,400, baseTexture, baseTexW, baseTexH},
        {600,400, 50,400, baseTexture, baseTexW, baseTexH},
        {50,400, 50,50, baseTexture, baseTexW, baseTexH}
    };
    enemies.emplace_back(300,200, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
}

void loadLevel3() {
    staticWalls.clear();
    enemies.clear();
    for (int i = 0; i < 5; ++i)
        staticWalls.emplace_back(100+i*100, 100, 100+i*100, 500, baseTexture, baseTexW, baseTexH);
    enemies.emplace_back(550, 300, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(400, 150, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
}
void loadLevel4() {
    staticWalls.clear();
    enemies.clear();
    for (int i = 0; i < 5; ++i)
        staticWalls.emplace_back(100+i*100, 100, 100+i*100, 500, baseTexture, baseTexW, baseTexH);
    enemies.emplace_back(550, 300, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(400, 150, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(300,200, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(500,200, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
}

// --- Новые уровни (с 5 по 10) ---

void loadLevel5() {
    staticWalls.clear(); enemies.clear();
    // Горизонтальный лабиринт из длинных стен
    for (int i = 0; i < 4; ++i) {
        // Чередуем проходы слева и справа
        if (i % 2 == 0)
            staticWalls.emplace_back(50, 100 + i * 100, 500, 100 + i * 100, baseTexture, baseTexW, baseTexH);
        else
            staticWalls.emplace_back(150, 100 + i * 100, 600, 100 + i * 100, baseTexture, baseTexW, baseTexH);
    }
    // Враги прячутся за поворотами лабиринта
    enemies.emplace_back(100, 150, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(550, 250, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(100, 350, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
}

void loadLevel6() {
    staticWalls.clear(); enemies.clear();
    // Две изолированные квадратные комнаты (арены)
    // Комната 1
    staticWalls.emplace_back(50, 50, 250, 50, baseTexture, baseTexW, baseTexH);
    staticWalls.emplace_back(250, 50, 250, 250, baseTexture, baseTexW, baseTexH);
    staticWalls.emplace_back(250, 250, 50, 250, baseTexture, baseTexW, baseTexH);
    staticWalls.emplace_back(50, 250, 50, 50, baseTexture, baseTexW, baseTexH);
    // Комната 2
    staticWalls.emplace_back(350, 300, 550, 300, baseTexture, baseTexW, baseTexH);
    staticWalls.emplace_back(550, 300, 550, 500, baseTexture, baseTexW, baseTexH);
    staticWalls.emplace_back(550, 500, 350, 500, baseTexture, baseTexW, baseTexH);
    staticWalls.emplace_back(350, 500, 350, 300, baseTexture, baseTexW, baseTexH);

    // Враги внутри и снаружи комнат
    enemies.emplace_back(150, 150, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(450, 400, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(300, 100, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
}

void loadLevel7() {
    staticWalls.clear(); enemies.clear();
    // "Звезда" или крест по центру карты, разделяющий сектора
    staticWalls.emplace_back(320, 100, 320, 250, baseTexture, baseTexW, baseTexH);
    staticWalls.emplace_back(320, 350, 320, 500, baseTexture, baseTexW, baseTexH);
    staticWalls.emplace_back(100, 300, 250, 300, baseTexture, baseTexW, baseTexH);
    staticWalls.emplace_back(390, 300, 540, 300, baseTexture, baseTexW, baseTexH);

    // По одному врагу в каждом образовавшемся углу карты
    enemies.emplace_back(150, 150, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(480, 150, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(150, 450, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(480, 450, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
}

void loadLevel8() {
    staticWalls.clear(); enemies.clear();
    // Сужающийся длинный коридор-колоннада
    for (int i = 0; i < 6; ++i) {
        float x_offset = i * 60;
        // Верхний ряд зубьев
        staticWalls.emplace_back(100 + x_offset, 100, 100 + x_offset, 200, baseTexture, baseTexW, baseTexH);
        // Нижний ряд зубьев
        staticWalls.emplace_back(100 + x_offset, 400, 100 + x_offset, 500, baseTexture, baseTexW, baseTexH);
    }
    // Замыкающая стена в конце
    staticWalls.emplace_back(460, 200, 460, 400, baseTexture, baseTexW, baseTexH);

    // Толпа врагов в конце коридора
    enemies.emplace_back(420, 300, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(420, 250, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(420, 350, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
}

void loadLevel9() {
    staticWalls.clear(); enemies.clear();
    // Сетка из мелких колонн (колышков) по всей карте
    for (int x = 150; x <= 500; x += 150) {
        for (int y = 150; y <= 450; y += 150) {
            // Маленький крестик-колонна
            staticWalls.emplace_back(x - 10, y, x + 10, y, baseTexture, baseTexW, baseTexH);
            staticWalls.emplace_back(x, y - 10, x, y + 10, baseTexture, baseTexW, baseTexH);
        }
    }
    // Много врагов, рассредоточенных среди колонн
    enemies.emplace_back(200, 200, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(450, 200, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(200, 400, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(450, 400, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(320, 300, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
}

void loadLevel10() {
    staticWalls.clear(); enemies.clear();
    // Финальный уровень: Огромная замкнутая коробка по периметру экрана и куча врагов
    staticWalls.emplace_back(20, 20, 620, 20, baseTexture, baseTexW, baseTexH);
    staticWalls.emplace_back(620, 20, 620, 580, baseTexture, baseTexW, baseTexH);
    staticWalls.emplace_back(620, 580, 20, 580, baseTexture, baseTexW, baseTexH);
    staticWalls.emplace_back(20, 580, 20, 20, baseTexture, baseTexW, baseTexH);

    // Настоящая армия "Фимозов" (6 штук)
    enemies.emplace_back(300, 100, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(400, 150, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(500, 250, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(300, 500, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(200, 400, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
    enemies.emplace_back(500, 450, fimozTexAlive, fimozW, fimozH, fimozTexDead, fimozDW, fimozDH);
}

// --- Обновленная функция диспетчера уровней ---
void loadLevel(int i) {
    if (i == 1) loadLevel1();
    else if (i == 2) loadLevel2();
    else if (i == 3) loadLevel3();
    else if (i == 4) loadLevel4();
    else if (i == 5) loadLevel5();
    else if (i == 6) loadLevel6();
    else if (i == 7) loadLevel7();
    else if (i == 8) loadLevel8();
    else if (i == 9) loadLevel9();
    else if (i == 10) loadLevel10();
    else {
        // Если прошли все 10 уровней — возвращаемся на первый уровень
        loadLevel1(); 
    }
}


bool initSDL() {
    if (!SDL_Init(SDL_INIT_VIDEO)) return false;
    window = SDL_CreateWindow("Raycaster", WIDTH, HEIGHT, 0);
    renderer = SDL_CreateRenderer(window, nullptr);
    screen_texture = SDL_CreateTexture(renderer,
        SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING,
        WIDTH, HEIGHT);
    screen_buffer = new Uint32[WIDTH * HEIGHT];

    SDL_Surface* surf = IMG_Load("bricks.png");
    baseTexture = loadPixels(surf, baseTexW, baseTexH);

    SDL_Surface* aS = IMG_Load("fimoz.png");
    fimozTexAlive = loadPixels(aS, fimozW, fimozH);
    SDL_Surface* dS = IMG_Load("fimozD.png");
    fimozTexDead = loadPixels(dS, fimozDW, fimozDH);

    auto loadGun = [&](const char* file) {
        SDL_Surface* s = IMG_Load(file);
        SDL_Surface* c = SDL_ConvertSurface(s, SDL_PIXELFORMAT_ARGB8888);
        SDL_DestroySurface(s);
        SDL_Texture* t = SDL_CreateTexture(renderer,
            SDL_PIXELFORMAT_ARGB8888,
            SDL_TEXTUREACCESS_STATIC,
            c->w, c->h);
        SDL_UpdateTexture(t, NULL, c->pixels, c->w * sizeof(Uint32));
        SDL_DestroySurface(c);
        return t;
    };
    gunTex1 = loadGun("gun1.png");
    gunTex2 = loadGun("gun2.png");

    return true;
}


bool shootEnemy(Player& p, const std::vector<Wall>& walls) {
    float ray_angle = p.angle;
    float dir_x = cosf(ray_angle), dir_y = sinf(ray_angle);
    float wallDist = INFINITY;
    for (auto& w : walls) {
        float dx = w.x2 - w.x1, dy = w.y2 - w.y1;
        float det = dir_x * dy - dir_y * dx;
        if (fabs(det) < 1e-6f) continue;
        float t = ((p.x - w.x1) * dy - (p.y - w.y1) * dx) / det;
        float u = ((w.x1 - p.x) * dir_y - (w.y1 - p.y) * dir_x) / det;
        if (t > 0 && u >= 0 && u <= 1) {
            float ix = p.x + t * dir_x;
            float iy = p.y + t * dir_y;
            wallDist = std::min(wallDist, hypotf(ix - p.x, iy - p.y));
        }
    }
    for (auto& enemy : enemies) {
        if (enemy.hp <= 0) continue;
        float dx = enemy.x - p.x;
        float dy = enemy.y - p.y;
        float nx = -dy, ny = dx;
        float len = hypotf(nx, ny);
        nx /= len; ny /= len;
        float half = 20.0f;
        Wall ew(enemy.x - nx * half, enemy.y - ny * half,
                enemy.x + nx * half, enemy.y + ny * half);
        float det = dir_x * (ew.y2 - ew.y1) - dir_y * (ew.x2 - ew.x1);
        if (fabs(det) < 1e-6f) continue;
        float t = ((p.x - ew.x1) * (ew.y2 - ew.y1) - (p.y - ew.y1) * (ew.x2 - ew.x1)) / det;
        float u = ((ew.x1 - p.x) * dir_y - (ew.y1 - p.y) * dir_x) / det;
        if (t > 0 && u >= 0 && u <= 1) {
            float ex = p.x + t * dir_x;
            float ey = p.y + t * dir_y;
            float dist = hypotf(ex - p.x, ey - p.y);
            if (dist < wallDist) {
                enemy.hp--;
                return true;
            }
        }
    }
    return false;
}

void drawCrosshair(Uint32 color = 0xFF0000) {
    int cx = WIDTH / 2, cy = HEIGHT / 2;
    for (int dy = -5; dy <= 5; ++dy)
        if (cy + dy >= 0 && cy + dy < HEIGHT)
            screen_buffer[(cy + dy) * WIDTH + cx] = color;
    for (int dx = -5; dx <= 5; ++dx)
        if (cx + dx >= 0 && cx + dx < WIDTH)
            screen_buffer[cy * WIDTH + cx + dx] = color;
}

void renderFrame(Player& p) {
    float start = p.angle - FOV / 2;
    float step = FOV / CASTED_RAYS;
    memset(screen_buffer, 0, WIDTH * HEIGHT * sizeof(Uint32));
    std::vector<float> depthBuffer(CASTED_RAYS, INFINITY);





    std::vector<Wall> all = staticWalls;
    for (int r = 0; r < CASTED_RAYS; ++r) {
        float ang = start + r * step;
        float dx = cosf(ang), dy = sinf(ang);
        float minD = INFINITY, bestU = 0;
        Uint32* curTex = nullptr; int tW = 0, tH = 0;

        for (auto& w : all) {
            float ex = w.x2 - w.x1, ey = w.y2 - w.y1;
            float det = dx * ey - dy * ex;
            if (fabs(det) < 1e-6f) continue;
            float t = ((p.x - w.x1) * ey - (p.y - w.y1) * ex) / det;
            float u = ((w.x1 - p.x) * dy - (w.y1 - p.y) * dx) / det;
            if (t > 0 && u >= 0 && u <= 1 && t < minD) {
                minD = t; bestU = u;
                curTex = w.tex; tW = w.texW; tH = w.texH;
            }
        }

        if (minD < INFINITY && curTex) {
            float dd = minD * cosf(p.angle - ang);
            depthBuffer[r] = dd;
            
            int h = int((HEIGHT * 2 * WALL_HEIGHT_SCALE) / (dd + 0.0001f));
            int y0 = std::max(-h / 2 + HEIGHT / 2, 0);
            int y1 = std::min(h / 2 + HEIGHT / 2, HEIGHT - 1);
            int tx = std::clamp(int(bestU * tW), 0, tW - 1);
            for (int y = y0; y < y1; ++y) {
                int ty = (y - y0) * tH / h;
               	Uint32 col = curTex[ty * tW + tx];
				Uint8 a = col >> 24;
				if (a < 128) continue;

                for (int dxp = 0; dxp < SCALE; ++dxp) {
                    int sx = r * SCALE + dxp;
                    if (sx < WIDTH) screen_buffer[y * WIDTH + sx] = col;
                }
            }
        }
    }
    
    all.clear();
    
    
    
    for (auto& e : enemies) {
        float dx = e.x - p.x, dy = e.y - p.y;
        float nx = -dy, ny = dx;
        float len = hypotf(nx, ny);
        nx /= len; ny /= len;
        float half = 20;
        Uint32* tex = (e.hp > 0 ? e.aliveTex : e.deadTex);
        int w = (e.hp > 0 ? e.aW : e.dW);
        int h = (e.hp > 0 ? e.aH : e.dH);
        all.emplace_back(e.x - nx * half, e.y - ny * half,
                         e.x + nx * half, e.y + ny * half,
                         tex, w, h);
    }
    
    

    for (int r = 0; r < CASTED_RAYS; ++r) {
        float ang = start + r * step;
        float dx = cosf(ang), dy = sinf(ang);
        float minD = INFINITY, bestU = 0;
        Uint32* curTex = nullptr; int tW = 0, tH = 0;

        for (auto& w : all) {
            float ex = w.x2 - w.x1, ey = w.y2 - w.y1;
            float det = dx * ey - dy * ex;
            if (fabs(det) < 1e-6f) continue;
            float t = ((p.x - w.x1) * ey - (p.y - w.y1) * ex) / det;
            float u = ((w.x1 - p.x) * dy - (w.y1 - p.y) * dx) / det;
            if (t > 0 && u >= 0 && u <= 1 && t < minD) {
                minD = t; bestU = u;
                curTex = w.tex; tW = w.texW; tH = w.texH;
            }
        }

        if (minD < INFINITY && curTex) {
            float dd = minD * cosf(p.angle - ang);
            if(dd> depthBuffer[r]) continue;
            
            int h = int((HEIGHT * 2 * WALL_HEIGHT_SCALE) / (dd + 0.0001f));
            int y0 = std::max(-h / 2 + HEIGHT / 2, 0);
            int y1 = std::min(h / 2 + HEIGHT / 2, HEIGHT - 1);
            int tx = std::clamp(int(bestU * tW), 0, tW - 1);
            for (int y = y0; y < y1; ++y) {
                int ty = (y - y0) * tH / h;
                Uint32 col = curTex[ty * tW + tx];
				Uint8 a = col >> 24;
				if (a < 128) continue;
                for (int dxp = 0; dxp < SCALE; ++dxp) {
                    int sx = r * SCALE + dxp;
                    if (sx < WIDTH) screen_buffer[y * WIDTH + sx] = col;
                }
            }
        }
    }

    // Crosshair
    drawCrosshair(0xFF2D9ED8); 
}

int main(int argc, char* argv[]) {
    if (!initSDL()) return 1;
    Player player;
    int currentLevel = 1;
    loadLevel(currentLevel);
    SDL_Event e;
    while (true) {
        Uint32 frame_start = SDL_GetTicks();
       while (SDL_PollEvent(&e)) {
            if (e.type == SDL_EVENT_QUIT) goto end;
            if (e.type == SDL_EVENT_KEY_DOWN && e.key.scancode == SDL_SCANCODE_SPACE) {
                gunFiring = true;
                fireStartTime = frame_start;
                shootEnemy(player, staticWalls);
            }
        }

        const bool* keys = SDL_GetKeyboardState(NULL);
        bool isAccel = false;

        if (keys[SDL_SCANCODE_DOWN]) {
            player.vx += cosf(player.angle) * player.accel;
            player.vy += sinf(player.angle) * player.accel;
            isAccel = true;
        }
        if (keys[SDL_SCANCODE_UP]) {
            player.vx -= cosf(player.angle) * player.accel;
            player.vy -= sinf(player.angle) * player.accel;
            isAccel = true;
        }

        float vlen = hypotf(player.vx, player.vy);
        if (vlen > player.maxSpeed) {
            player.vx *= player.maxSpeed / vlen;
            player.vy *= player.maxSpeed / vlen;
        }
		
		if(!isAccel)
		{
			player.vx *= (1 - player.decel);
        	player.vy *= (1 - player.decel);
		}
        
        player.x += player.vx;
        player.y += player.vy;

 		if (keys[SDL_SCANCODE_LEFT]) player.angle -= player.rot_speed;
        if (keys[SDL_SCANCODE_RIGHT]) player.angle += player.rot_speed;

        renderFrame(player);
        SDL_UpdateTexture(screen_texture, NULL, screen_buffer, WIDTH * sizeof(Uint32));
        SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
        SDL_RenderClear(renderer);
        SDL_RenderTexture(renderer, screen_texture, NULL, NULL);
        
        
        
        // Отрисовка оружия
        int gw = 200, gh = 150;
        SDL_FRect dst = { WIDTH / 2 - gw / 2, HEIGHT - gh, gw, gh };
        if (gunFiring && SDL_GetTicks() - fireStartTime < 200)
            SDL_RenderTexture(renderer, gunTex2, NULL, &dst);
        else {
            gunFiring = false;
            SDL_RenderTexture(renderer, gunTex1, NULL, &dst);
        }

        SDL_RenderPresent(renderer);
        
        bool allDead = true;
        
        for(auto& e : enemies)
        {
        	if(e.hp>0)
        	{
        		allDead = false;
    			break;
			}
		}
		
		if(allDead)
		{
			currentLevel++;
			loadLevel(currentLevel);
		}
        

        Uint32 dt = SDL_GetTicks() - frame_start;
        if (dt < 1000 / FPS) SDL_Delay(1000 / FPS - dt);
    }

end:
    delete[] baseTexture;
    delete[] screen_buffer;
    for (auto& e : enemies) {
        delete[] e.aliveTex;
        delete[] e.deadTex;
    }
    SDL_DestroyTexture(screen_texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    SDL_Quit();
    return 0;
}