#include "raylib.h" #include #include #include struct Wall { Vector3 position; Vector3 size; }; struct Furniture { Vector3 position; Vector3 size; int type; }; static const int MAZE_W = 41; static const int MAZE_H = 41; static const float CELL = 4.0f; static bool maze[MAZE_H][MAZE_W]; static std::vector walls; static std::vector furniture; extern Vector3 playerPosition; extern Camera3D GetPlayerCamera(); extern void UpdatePlayer(float deltaTime); extern void UpdateEnemy(float deltaTime); extern void UpdateWeapons(float deltaTime); extern void DrawEnemy(); extern void DrawBullets(); extern void DrawPlayerWeapon(); bool IsSolidAt(Vector3 position, float radius) { for (const Wall& wall : walls) { if (position.x >= wall.position.x - wall.size.x / 2.0f - radius && position.x <= wall.position.x + wall.size.x / 2.0f + radius && position.z >= wall.position.z - wall.size.z / 2.0f - radius && position.z <= wall.position.z + wall.size.z / 2.0f + radius) { return true; } } for (const Furniture& object : furniture) { if (position.x >= object.position.x - object.size.x / 2.0f - radius && position.x <= object.position.x + object.size.x / 2.0f + radius && position.z >= object.position.z - object.size.z / 2.0f - radius && position.z <= object.position.z + object.size.z / 2.0f + radius) { return true; } } return false; } static Vector3 CellToWorld(int x, int z) { return { (x - MAZE_W / 2) * CELL, 0.0f, (z - MAZE_H / 2) * CELL }; } static void GenerateMaze() { for (int z = 0; z < MAZE_H; z++) { for (int x = 0; x < MAZE_W; x++) { maze[z][x] = true; } } std::vector stack; stack.push_back({1, 1}); maze[1][1] = false; std::mt19937 rng(12345); const int dirs[4][2] = { { 2, 0 }, {-2, 0 }, { 0, 2 }, { 0,-2 } }; while (!stack.empty()) { Vector2 current = stack.back(); std::vector available; for (int i = 0; i < 4; i++) { int nx = (int)current.x + dirs[i][0]; int nz = (int)current.y + dirs[i][1]; if (nx > 0 && nx < MAZE_W - 1 && nz > 0 && nz < MAZE_H - 1 && maze[nz][nx]) { available.push_back(i); } } if (available.empty()) { stack.pop_back(); continue; } int d = available[rng() % available.size()]; int nx = (int)current.x + dirs[d][0]; int nz = (int)current.y + dirs[d][1]; maze[((int)current.y + nz) / 2] [((int)current.x + nx) / 2] = false; maze[nz][nx] = false; stack.push_back({(float)nx, (float)nz}); } for (int z = 3; z < MAZE_H - 3; z += 6) { for (int x = 3; x < MAZE_W - 3; x += 6) { maze[z][x] = false; if (x + 1 < MAZE_W - 1) maze[z][x + 1] = false; if (x > 1) maze[z][x - 1] = false; if (z + 1 < MAZE_H - 1) maze[z + 1][x] = false; if (z > 1) maze[z - 1][x] = false; } } } static void BuildWalls() { walls.clear(); for (int z = 0; z < MAZE_H; z++) { for (int x = 0; x < MAZE_W; x++) { if (!maze[z][x]) continue; Vector3 p = CellToWorld(x, z); walls.push_back({ {p.x, 1.5f, p.z}, {CELL, 3.0f, CELL} }); } } } static void GenerateFurniture() { furniture.clear(); for (int z = 2; z < MAZE_H - 2; z++) { for (int x = 2; x < MAZE_W - 2; x++) { if (maze[z][x]) continue; if ((x * 13 + z * 7) % 17 != 0) continue; if (x <= 4 && z <= 4) continue; Vector3 p = CellToWorld(x, z); Furniture object; object.type = (x * 3 + z * 5) % 5; switch (object.type) { case 0: object.position = {p.x, 0.8f, p.z}; object.size = {2.4f, 1.6f, 2.4f}; break; case 1: object.position = {p.x, 0.75f, p.z}; object.size = {1.5f, 1.5f, 1.5f}; break; case 2: object.position = {p.x, 1.35f, p.z}; object.size = {1.8f, 2.7f, 1.0f}; break; case 3: object.position = {p.x, 0.4f, p.z}; object.size = {2.5f, 0.8f, 0.8f}; break; default: object.position = {p.x, 0.6f, p.z}; object.size = {2.0f, 1.2f, 1.2f}; break; } if (!IsSolidAt(object.position, 0.2f)) furniture.push_back(object); } } } static void DrawFloor() { for (int z = 0; z < MAZE_H; z++) { for (int x = 0; x < MAZE_W; x++) { if (maze[z][x]) continue; Vector3 p = CellToWorld(x, z); int shade = 108 + ((x * 17 + z * 11) % 9); Color color = { (unsigned char)shade, (unsigned char)shade, (unsigned char)(shade + 1), 255 }; DrawCube( {p.x, -0.06f, p.z}, CELL + 0.16f, 0.12f, CELL + 0.16f, color ); } } } static void DrawWalls() { for (const Wall& wall : walls) { DrawCube( wall.position, wall.size.x, wall.size.y, wall.size.z, {52, 82, 116, 255} ); } } static void DrawCeiling() { for (int z = 0; z < MAZE_H; z++) { for (int x = 0; x < MAZE_W; x++) { if (maze[z][x]) continue; Vector3 p = CellToWorld(x, z); bool lightZone = ((x * 3 + z * 7) % 11 == 0); Color ceilingColor = lightZone ? Color{155, 155, 155, 255} : Color{70, 70, 70, 255}; DrawCube( {p.x, 3.12f, p.z}, CELL + 0.16f, 0.16f, CELL + 0.16f, ceilingColor ); if (lightZone) { DrawCube( {p.x, 3.01f, p.z}, 1.3f, 0.04f, 0.7f, RAYWHITE ); } } } } static void DrawFurniture() { for (const Furniture& object : furniture) { Color color; switch (object.type) { case 0: color = {75, 75, 75, 255}; break; case 1: color = {100, 82, 65, 255}; break; case 2: color = {62, 62, 68, 255}; break; case 3: color = {84, 70, 55, 255}; break; default: color = {90, 90, 90, 255}; break; } DrawCube( object.position, object.size.x, object.size.y, object.size.z, color ); } } static void DrawHUD() { DrawRectangle( 0, 0, 300, 70, {0, 0, 0, 100} ); DrawText( "NIVEL: TALAN-TALAN", 15, 12, 20, RAYWHITE ); DrawText( "WASD MOVER", 15, 39, 15, LIGHTGRAY ); int centerX = GetScreenWidth() / 2; int centerY = GetScreenHeight() / 2; DrawLine( centerX - 8, centerY, centerX + 8, centerY, RAYWHITE ); DrawLine( centerX, centerY - 8, centerX, centerY + 8, RAYWHITE ); } void RunGame() { InitWindow( 1366, 768, "A4B1 - Nivel Talan-Talan" ); SetTargetFPS(60); DisableCursor(); GenerateMaze(); BuildWalls(); GenerateFurniture(); while (!WindowShouldClose()) { float deltaTime = GetFrameTime(); if (IsKeyPressed(KEY_F11)) { ToggleFullscreen(); } UpdatePlayer(deltaTime); UpdateEnemy(deltaTime); UpdateWeapons(deltaTime); BeginDrawing(); ClearBackground({25, 25, 28, 255}); BeginMode3D(GetPlayerCamera()); DrawFloor(); DrawWalls(); DrawCeiling(); DrawFurniture(); DrawEnemy(); DrawBullets(); EndMode3D(); DrawPlayerWeapon(); DrawHUD(); EndDrawing(); } EnableCursor(); CloseWindow(); }