Files
2026-09-27 00:12:17 -03:00

458 lines
6.8 KiB
C++

#include "raylib.h"
#include <cmath>
#include <vector>
#include <random>
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<Wall> walls;
static std::vector<Furniture> 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<Vector2> 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<int> 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();
}