3175 lines
60 KiB
C++
3175 lines
60 KiB
C++
#include "raylib.h"
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
#include <cstdlib>
|
|
#include <ctime>
|
|
#include <vector>
|
|
|
|
// ============================================================
|
|
// A4B1 0.0.2
|
|
// ============================================================
|
|
|
|
const int PANTALLA_ANCHO = 1280;
|
|
const int PANTALLA_ALTO = 720;
|
|
|
|
const float MUNDO_ANCHO = 2800.0f;
|
|
const float MUNDO_ALTO = 1900.0f;
|
|
|
|
const float BORDE = 45.0f;
|
|
|
|
const float RADIO_JUGADOR = 19.0f;
|
|
const float RADIO_IA = 20.0f;
|
|
|
|
const float VELOCIDAD_JUGADOR = 310.0f;
|
|
const float VELOCIDAD_IA = 180.0f;
|
|
|
|
const float RADIO_VISION = 470.0f;
|
|
const float TIEMPO_RECARGA = 1.15f;
|
|
|
|
const int EQUIPO_AZUL = 0;
|
|
const int EQUIPO_ROJO = 1;
|
|
|
|
// ============================================================
|
|
// ARMAS
|
|
// ============================================================
|
|
|
|
enum TipoArma
|
|
{
|
|
ARMA_RAPIDA = 0,
|
|
ARMA_EQUILIBRADA,
|
|
ARMA_PESADA,
|
|
ARMA_PRECISA
|
|
};
|
|
|
|
struct Arma
|
|
{
|
|
TipoArma tipo;
|
|
int balas;
|
|
int cartuchos;
|
|
|
|
bool enSuelo;
|
|
bool activa;
|
|
|
|
Vector2 posicion;
|
|
};
|
|
|
|
struct Bala
|
|
{
|
|
Vector2 posicion;
|
|
Vector2 direccion;
|
|
|
|
float velocidad;
|
|
float dano;
|
|
|
|
int equipo;
|
|
|
|
int paredesAtraviesadas;
|
|
int rebotes;
|
|
|
|
bool activa;
|
|
};
|
|
|
|
struct Botiquin
|
|
{
|
|
Vector2 posicion;
|
|
bool activa;
|
|
};
|
|
|
|
struct Municion
|
|
{
|
|
Vector2 posicion;
|
|
bool activa;
|
|
};
|
|
|
|
struct MarcaMuerte
|
|
{
|
|
Vector2 posicion;
|
|
float tiempo;
|
|
bool activa;
|
|
};
|
|
|
|
struct Entidad
|
|
{
|
|
Vector2 posicion;
|
|
Vector2 velocidad;
|
|
Vector2 direccion;
|
|
|
|
float radio;
|
|
|
|
float vida;
|
|
float vidaMaxima;
|
|
|
|
int equipo;
|
|
|
|
bool jugador;
|
|
bool viva;
|
|
|
|
int arma;
|
|
|
|
bool recargando;
|
|
float tiempoRecarga;
|
|
|
|
float tiempoDisparo;
|
|
float tiempoAtascado;
|
|
|
|
Vector2 ultimaPosicion;
|
|
};
|
|
|
|
struct Pared
|
|
{
|
|
Rectangle rectangulo;
|
|
};
|
|
|
|
// ============================================================
|
|
// FUNCIONES BÁSICAS
|
|
// ============================================================
|
|
|
|
float Distancia(Vector2 a, Vector2 b)
|
|
{
|
|
float dx = a.x - b.x;
|
|
float dy = a.y - b.y;
|
|
|
|
return std::sqrt(dx * dx + dy * dy);
|
|
}
|
|
|
|
Vector2 Normalizar(Vector2 v)
|
|
{
|
|
float longitud =
|
|
std::sqrt(v.x * v.x + v.y * v.y);
|
|
|
|
if (longitud <= 0.0001f)
|
|
return {0, 0};
|
|
|
|
return {
|
|
v.x / longitud,
|
|
v.y / longitud
|
|
};
|
|
}
|
|
|
|
Vector2 Multiplicar(Vector2 v, float valor)
|
|
{
|
|
return {
|
|
v.x * valor,
|
|
v.y * valor
|
|
};
|
|
}
|
|
|
|
// ============================================================
|
|
// ARMAS
|
|
// ============================================================
|
|
|
|
const char* NombreArma(TipoArma tipo)
|
|
{
|
|
switch (tipo)
|
|
{
|
|
case ARMA_RAPIDA:
|
|
return "RAPIDA";
|
|
|
|
case ARMA_EQUILIBRADA:
|
|
return "EQUILIBRADA";
|
|
|
|
case ARMA_PESADA:
|
|
return "PESADA";
|
|
|
|
case ARMA_PRECISA:
|
|
return "PRECISA";
|
|
}
|
|
|
|
return "???";
|
|
}
|
|
|
|
int CapacidadArma(TipoArma tipo)
|
|
{
|
|
switch (tipo)
|
|
{
|
|
case ARMA_RAPIDA:
|
|
return 12;
|
|
|
|
case ARMA_EQUILIBRADA:
|
|
return 8;
|
|
|
|
case ARMA_PESADA:
|
|
return 4;
|
|
|
|
case ARMA_PRECISA:
|
|
return 3;
|
|
}
|
|
|
|
return 8;
|
|
}
|
|
|
|
float CadenciaArma(TipoArma tipo)
|
|
{
|
|
switch (tipo)
|
|
{
|
|
case ARMA_RAPIDA:
|
|
return 0.10f;
|
|
|
|
case ARMA_EQUILIBRADA:
|
|
return 0.25f;
|
|
|
|
case ARMA_PESADA:
|
|
return 0.70f;
|
|
|
|
case ARMA_PRECISA:
|
|
return 1.05f;
|
|
}
|
|
|
|
return 0.25f;
|
|
}
|
|
|
|
float DanoArma(TipoArma tipo)
|
|
{
|
|
switch (tipo)
|
|
{
|
|
case ARMA_RAPIDA:
|
|
return 10.0f;
|
|
|
|
case ARMA_EQUILIBRADA:
|
|
return 18.0f;
|
|
|
|
case ARMA_PESADA:
|
|
return 40.0f;
|
|
|
|
case ARMA_PRECISA:
|
|
return 70.0f;
|
|
}
|
|
|
|
return 10.0f;
|
|
}
|
|
|
|
float VelocidadBala(TipoArma tipo)
|
|
{
|
|
switch (tipo)
|
|
{
|
|
case ARMA_RAPIDA:
|
|
return 820.0f;
|
|
|
|
case ARMA_EQUILIBRADA:
|
|
return 760.0f;
|
|
|
|
case ARMA_PESADA:
|
|
return 690.0f;
|
|
|
|
case ARMA_PRECISA:
|
|
return 1050.0f;
|
|
}
|
|
|
|
return 760.0f;
|
|
}
|
|
|
|
Color ColorArma(TipoArma tipo)
|
|
{
|
|
switch (tipo)
|
|
{
|
|
case ARMA_RAPIDA:
|
|
return YELLOW;
|
|
|
|
case ARMA_EQUILIBRADA:
|
|
return SKYBLUE;
|
|
|
|
case ARMA_PESADA:
|
|
return ORANGE;
|
|
|
|
case ARMA_PRECISA:
|
|
return PURPLE;
|
|
}
|
|
|
|
return WHITE;
|
|
}
|
|
|
|
Arma CrearArma(
|
|
TipoArma tipo,
|
|
Vector2 posicion,
|
|
bool enSuelo
|
|
)
|
|
{
|
|
Arma arma{};
|
|
|
|
arma.tipo = tipo;
|
|
arma.balas = CapacidadArma(tipo);
|
|
|
|
// Cartuchos infinitos.
|
|
arma.cartuchos = 999999;
|
|
|
|
arma.enSuelo = enSuelo;
|
|
arma.activa = true;
|
|
arma.posicion = posicion;
|
|
|
|
return arma;
|
|
}
|
|
|
|
// ============================================================
|
|
// COLISIONES
|
|
// ============================================================
|
|
|
|
bool CirculoChocaRectangulo(
|
|
Vector2 centro,
|
|
float radio,
|
|
Rectangle rect
|
|
)
|
|
{
|
|
float cercanoX =
|
|
std::clamp(
|
|
centro.x,
|
|
rect.x,
|
|
rect.x + rect.width
|
|
);
|
|
|
|
float cercanoY =
|
|
std::clamp(
|
|
centro.y,
|
|
rect.y,
|
|
rect.y + rect.height
|
|
);
|
|
|
|
float dx = centro.x - cercanoX;
|
|
float dy = centro.y - cercanoY;
|
|
|
|
return dx * dx + dy * dy <= radio * radio;
|
|
}
|
|
|
|
bool EntidadChocaPared(
|
|
Vector2 posicion,
|
|
float radio,
|
|
const std::vector<Pared>& paredes
|
|
)
|
|
{
|
|
for (const auto& pared : paredes)
|
|
{
|
|
if (
|
|
CirculoChocaRectangulo(
|
|
posicion,
|
|
radio,
|
|
pared.rectangulo
|
|
)
|
|
)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool PuntoDentroRectangulo(
|
|
Vector2 punto,
|
|
Rectangle rect
|
|
)
|
|
{
|
|
return CheckCollisionPointRec(
|
|
punto,
|
|
rect
|
|
);
|
|
}
|
|
|
|
bool LineaChocaRectangulo(
|
|
Vector2 inicio,
|
|
Vector2 fin,
|
|
Rectangle rect
|
|
)
|
|
{
|
|
const int pasos = 50;
|
|
|
|
for (int i = 0; i <= pasos; i++)
|
|
{
|
|
float t =
|
|
static_cast<float>(i) /
|
|
static_cast<float>(pasos);
|
|
|
|
Vector2 punto = {
|
|
inicio.x +
|
|
(fin.x - inicio.x) * t,
|
|
|
|
inicio.y +
|
|
(fin.y - inicio.y) * t
|
|
};
|
|
|
|
if (
|
|
PuntoDentroRectangulo(
|
|
punto,
|
|
rect
|
|
)
|
|
)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool HayParedEntre(
|
|
Vector2 a,
|
|
Vector2 b,
|
|
const std::vector<Pared>& paredes
|
|
)
|
|
{
|
|
for (const auto& pared : paredes)
|
|
{
|
|
if (
|
|
LineaChocaRectangulo(
|
|
a,
|
|
b,
|
|
pared.rectangulo
|
|
)
|
|
)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// ============================================================
|
|
// MAPA
|
|
// ============================================================
|
|
|
|
std::vector<Pared> CrearMapa()
|
|
{
|
|
std::vector<Pared> paredes;
|
|
|
|
// Bordes
|
|
paredes.push_back({
|
|
{0, 0, MUNDO_ANCHO, BORDE}
|
|
});
|
|
|
|
paredes.push_back({
|
|
{
|
|
0,
|
|
MUNDO_ALTO - BORDE,
|
|
MUNDO_ANCHO,
|
|
BORDE
|
|
}
|
|
});
|
|
|
|
paredes.push_back({
|
|
{0, 0, BORDE, MUNDO_ALTO}
|
|
});
|
|
|
|
paredes.push_back({
|
|
{
|
|
MUNDO_ANCHO - BORDE,
|
|
0,
|
|
BORDE,
|
|
MUNDO_ALTO
|
|
}
|
|
});
|
|
|
|
// Izquierda
|
|
paredes.push_back({
|
|
{500, 300, 400, 50}
|
|
});
|
|
|
|
paredes.push_back({
|
|
{500, 1550, 400, 50}
|
|
});
|
|
|
|
paredes.push_back({
|
|
{900, 300, 55, 500}
|
|
});
|
|
|
|
paredes.push_back({
|
|
{900, 1100, 55, 500}
|
|
});
|
|
|
|
// Derecha
|
|
paredes.push_back({
|
|
{1900, 300, 400, 50}
|
|
});
|
|
|
|
paredes.push_back({
|
|
{1900, 1550, 400, 50}
|
|
});
|
|
|
|
paredes.push_back({
|
|
{1845, 300, 55, 500}
|
|
});
|
|
|
|
paredes.push_back({
|
|
{1845, 1100, 55, 500}
|
|
});
|
|
|
|
// Centro
|
|
paredes.push_back({
|
|
{1220, 650, 360, 55}
|
|
});
|
|
|
|
paredes.push_back({
|
|
{1220, 1195, 360, 55}
|
|
});
|
|
|
|
// Coberturas
|
|
paredes.push_back({
|
|
{650, 700, 180, 45}
|
|
});
|
|
|
|
paredes.push_back({
|
|
{650, 1155, 180, 45}
|
|
});
|
|
|
|
paredes.push_back({
|
|
{1970, 700, 180, 45}
|
|
});
|
|
|
|
paredes.push_back({
|
|
{1970, 1155, 180, 45}
|
|
});
|
|
|
|
return paredes;
|
|
}
|
|
|
|
// ============================================================
|
|
// MOVIMIENTO
|
|
// ============================================================
|
|
|
|
void MoverEntidad(
|
|
Entidad& entidad,
|
|
Vector2 movimiento,
|
|
const std::vector<Pared>& paredes
|
|
)
|
|
{
|
|
Vector2 nuevaX = entidad.posicion;
|
|
nuevaX.x += movimiento.x;
|
|
|
|
if (
|
|
!EntidadChocaPared(
|
|
nuevaX,
|
|
entidad.radio,
|
|
paredes
|
|
)
|
|
)
|
|
{
|
|
entidad.posicion.x = nuevaX.x;
|
|
}
|
|
|
|
Vector2 nuevaY = entidad.posicion;
|
|
nuevaY.y += movimiento.y;
|
|
|
|
if (
|
|
!EntidadChocaPared(
|
|
nuevaY,
|
|
entidad.radio,
|
|
paredes
|
|
)
|
|
)
|
|
{
|
|
entidad.posicion.y = nuevaY.y;
|
|
}
|
|
}
|
|
|
|
// ============================================================
|
|
// SEPARACIÓN DE COMPAÑEROS
|
|
// ============================================================
|
|
|
|
Vector2 FuerzaSeparacion(
|
|
int indice,
|
|
const std::vector<Entidad>& entidades
|
|
)
|
|
{
|
|
Vector2 fuerza = {0, 0};
|
|
|
|
const Entidad& yo =
|
|
entidades[indice];
|
|
|
|
for (
|
|
int i = 0;
|
|
i < static_cast<int>(entidades.size());
|
|
i++
|
|
)
|
|
{
|
|
if (i == indice)
|
|
continue;
|
|
|
|
const Entidad& otra =
|
|
entidades[i];
|
|
|
|
if (!otra.viva)
|
|
continue;
|
|
|
|
if (otra.equipo != yo.equipo)
|
|
continue;
|
|
|
|
float distancia =
|
|
Distancia(
|
|
yo.posicion,
|
|
otra.posicion
|
|
);
|
|
|
|
if (
|
|
distancia > 0 &&
|
|
distancia < 110
|
|
)
|
|
{
|
|
Vector2 alejamiento = {
|
|
yo.posicion.x -
|
|
otra.posicion.x,
|
|
|
|
yo.posicion.y -
|
|
otra.posicion.y
|
|
};
|
|
|
|
alejamiento =
|
|
Normalizar(
|
|
alejamiento
|
|
);
|
|
|
|
float intensidad =
|
|
(110.0f - distancia) /
|
|
110.0f;
|
|
|
|
fuerza.x +=
|
|
alejamiento.x *
|
|
intensidad;
|
|
|
|
fuerza.y +=
|
|
alejamiento.y *
|
|
intensidad;
|
|
}
|
|
}
|
|
|
|
return fuerza;
|
|
}
|
|
|
|
// ============================================================
|
|
// DIRECCIÓN LIBRE
|
|
// ============================================================
|
|
|
|
Vector2 BuscarDireccionLibre(
|
|
const Entidad& entidad,
|
|
const std::vector<Pared>& paredes
|
|
)
|
|
{
|
|
const Vector2 direcciones[] = {
|
|
{1, 0},
|
|
{-1, 0},
|
|
{0, 1},
|
|
{0, -1},
|
|
|
|
{0.707f, 0.707f},
|
|
{-0.707f, 0.707f},
|
|
{0.707f, -0.707f},
|
|
{-0.707f, -0.707f}
|
|
};
|
|
|
|
for (const Vector2& direccion : direcciones)
|
|
{
|
|
Vector2 prueba = {
|
|
entidad.posicion.x +
|
|
direccion.x * 100.0f,
|
|
|
|
entidad.posicion.y +
|
|
direccion.y * 100.0f
|
|
};
|
|
|
|
if (
|
|
!EntidadChocaPared(
|
|
prueba,
|
|
entidad.radio + 4,
|
|
paredes
|
|
)
|
|
)
|
|
{
|
|
return direccion;
|
|
}
|
|
}
|
|
|
|
return {1, 0};
|
|
}
|
|
|
|
// ============================================================
|
|
// ENEMIGO VISIBLE
|
|
// ============================================================
|
|
|
|
int BuscarEnemigo(
|
|
int indice,
|
|
const std::vector<Entidad>& entidades,
|
|
const std::vector<Pared>& paredes
|
|
)
|
|
{
|
|
const Entidad& yo =
|
|
entidades[indice];
|
|
|
|
int mejor = -1;
|
|
float mejorDistancia = 999999.0f;
|
|
|
|
for (
|
|
int i = 0;
|
|
i < static_cast<int>(entidades.size());
|
|
i++
|
|
)
|
|
{
|
|
if (i == indice)
|
|
continue;
|
|
|
|
const Entidad& enemigo =
|
|
entidades[i];
|
|
|
|
if (!enemigo.viva)
|
|
continue;
|
|
|
|
if (enemigo.equipo == yo.equipo)
|
|
continue;
|
|
|
|
float distancia =
|
|
Distancia(
|
|
yo.posicion,
|
|
enemigo.posicion
|
|
);
|
|
|
|
if (distancia > 900)
|
|
continue;
|
|
|
|
if (
|
|
!HayParedEntre(
|
|
yo.posicion,
|
|
enemigo.posicion,
|
|
paredes
|
|
)
|
|
)
|
|
{
|
|
if (distancia < mejorDistancia)
|
|
{
|
|
mejorDistancia = distancia;
|
|
mejor = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
return mejor;
|
|
}
|
|
|
|
// ============================================================
|
|
// ARMAS EN EL SUELO
|
|
// ============================================================
|
|
|
|
int BuscarArmaCercana(
|
|
const Entidad& entidad,
|
|
const std::vector<Arma>& armas
|
|
)
|
|
{
|
|
int mejor = -1;
|
|
float mejorDistancia = 75.0f;
|
|
|
|
for (
|
|
int i = 0;
|
|
i < static_cast<int>(armas.size());
|
|
i++
|
|
)
|
|
{
|
|
const Arma& arma =
|
|
armas[i];
|
|
|
|
if (!arma.activa)
|
|
continue;
|
|
|
|
if (!arma.enSuelo)
|
|
continue;
|
|
|
|
float distancia =
|
|
Distancia(
|
|
entidad.posicion,
|
|
arma.posicion
|
|
);
|
|
|
|
if (distancia < mejorDistancia)
|
|
{
|
|
mejorDistancia = distancia;
|
|
mejor = i;
|
|
}
|
|
}
|
|
|
|
return mejor;
|
|
}
|
|
|
|
void RecogerArma(
|
|
Entidad& entidad,
|
|
int indiceArma,
|
|
std::vector<Arma>& armas
|
|
)
|
|
{
|
|
if (
|
|
indiceArma < 0 ||
|
|
indiceArma >= static_cast<int>(armas.size())
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Arma& nueva =
|
|
armas[indiceArma];
|
|
|
|
if (
|
|
!nueva.activa ||
|
|
!nueva.enSuelo
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Si ya llevaba una, la tira.
|
|
if (entidad.arma >= 0)
|
|
{
|
|
Arma& vieja =
|
|
armas[entidad.arma];
|
|
|
|
vieja.enSuelo = true;
|
|
vieja.activa = true;
|
|
vieja.posicion =
|
|
entidad.posicion;
|
|
}
|
|
|
|
nueva.enSuelo = false;
|
|
|
|
entidad.arma =
|
|
indiceArma;
|
|
|
|
entidad.recargando = false;
|
|
entidad.tiempoRecarga = 0;
|
|
}
|
|
|
|
// ============================================================
|
|
// DISPARO
|
|
// ============================================================
|
|
|
|
void Disparar(
|
|
Entidad& entidad,
|
|
std::vector<Arma>& armas,
|
|
std::vector<Bala>& balas
|
|
)
|
|
{
|
|
if (!entidad.viva)
|
|
return;
|
|
|
|
if (entidad.arma < 0)
|
|
return;
|
|
|
|
if (
|
|
entidad.arma >=
|
|
static_cast<int>(armas.size())
|
|
)
|
|
{
|
|
entidad.arma = -1;
|
|
return;
|
|
}
|
|
|
|
Arma& arma =
|
|
armas[entidad.arma];
|
|
|
|
if (arma.balas <= 0)
|
|
return;
|
|
|
|
if (entidad.recargando)
|
|
return;
|
|
|
|
if (entidad.tiempoDisparo > 0)
|
|
return;
|
|
|
|
arma.balas--;
|
|
|
|
Bala bala{};
|
|
|
|
bala.posicion = {
|
|
entidad.posicion.x +
|
|
entidad.direccion.x *
|
|
(entidad.radio + 9),
|
|
|
|
entidad.posicion.y +
|
|
entidad.direccion.y *
|
|
(entidad.radio + 9)
|
|
};
|
|
|
|
bala.direccion =
|
|
Normalizar(
|
|
entidad.direccion
|
|
);
|
|
|
|
bala.velocidad =
|
|
VelocidadBala(
|
|
arma.tipo
|
|
);
|
|
|
|
bala.dano =
|
|
DanoArma(
|
|
arma.tipo
|
|
);
|
|
|
|
bala.equipo =
|
|
entidad.equipo;
|
|
|
|
bala.paredesAtraviesadas = 0;
|
|
bala.rebotes = 0;
|
|
bala.activa = true;
|
|
|
|
balas.push_back(bala);
|
|
|
|
entidad.tiempoDisparo =
|
|
CadenciaArma(
|
|
arma.tipo
|
|
);
|
|
}
|
|
|
|
// ============================================================
|
|
// RECARGA
|
|
// ============================================================
|
|
|
|
void IniciarRecarga(
|
|
Entidad& entidad,
|
|
std::vector<Arma>& armas
|
|
)
|
|
{
|
|
if (!entidad.viva)
|
|
return;
|
|
|
|
if (entidad.arma < 0)
|
|
return;
|
|
|
|
if (
|
|
entidad.arma >=
|
|
static_cast<int>(armas.size())
|
|
)
|
|
{
|
|
entidad.arma = -1;
|
|
return;
|
|
}
|
|
|
|
Arma& arma =
|
|
armas[entidad.arma];
|
|
|
|
if (entidad.recargando)
|
|
return;
|
|
|
|
if (
|
|
arma.balas >=
|
|
CapacidadArma(arma.tipo)
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Nunca se acaban.
|
|
arma.cartuchos = 999999;
|
|
|
|
entidad.recargando = true;
|
|
entidad.tiempoRecarga =
|
|
TIEMPO_RECARGA;
|
|
}
|
|
|
|
void ActualizarRecarga(
|
|
Entidad& entidad,
|
|
std::vector<Arma>& armas,
|
|
float dt
|
|
)
|
|
{
|
|
if (!entidad.recargando)
|
|
return;
|
|
|
|
entidad.tiempoRecarga -= dt;
|
|
|
|
if (entidad.tiempoRecarga <= 0)
|
|
{
|
|
entidad.recargando = false;
|
|
|
|
if (
|
|
entidad.arma >= 0 &&
|
|
entidad.arma <
|
|
static_cast<int>(armas.size())
|
|
)
|
|
{
|
|
Arma& arma =
|
|
armas[entidad.arma];
|
|
|
|
arma.balas =
|
|
CapacidadArma(
|
|
arma.tipo
|
|
);
|
|
|
|
arma.cartuchos = 999999;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================
|
|
// MARCAS DE MUERTE
|
|
// ============================================================
|
|
|
|
void CrearMarcaMuerte(
|
|
std::vector<MarcaMuerte>& marcas,
|
|
Vector2 posicion
|
|
)
|
|
{
|
|
marcas.push_back({
|
|
posicion,
|
|
0.0f,
|
|
true
|
|
});
|
|
}
|
|
|
|
// ============================================================
|
|
// BALAS
|
|
// ============================================================
|
|
|
|
void MoverBalas(
|
|
std::vector<Bala>& balas,
|
|
const std::vector<Pared>& paredes,
|
|
std::vector<Entidad>& entidades,
|
|
std::vector<MarcaMuerte>& marcas,
|
|
std::vector<Arma>& armas,
|
|
float dt
|
|
)
|
|
{
|
|
for (Bala& bala : balas)
|
|
{
|
|
if (!bala.activa)
|
|
continue;
|
|
|
|
Vector2 inicio =
|
|
bala.posicion;
|
|
|
|
Vector2 destino = {
|
|
inicio.x +
|
|
bala.direccion.x *
|
|
bala.velocidad *
|
|
dt,
|
|
|
|
inicio.y +
|
|
bala.direccion.y *
|
|
bala.velocidad *
|
|
dt
|
|
};
|
|
|
|
// ----------------------------------------------------
|
|
// BORDES
|
|
// ----------------------------------------------------
|
|
|
|
bool bordeX =
|
|
destino.x < BORDE ||
|
|
destino.x > MUNDO_ANCHO - BORDE;
|
|
|
|
bool bordeY =
|
|
destino.y < BORDE ||
|
|
destino.y > MUNDO_ALTO - BORDE;
|
|
|
|
if (bordeX)
|
|
{
|
|
if (bala.rebotes < 1)
|
|
{
|
|
bala.direccion.x *= -1.0f;
|
|
bala.rebotes++;
|
|
|
|
destino.x =
|
|
inicio.x +
|
|
bala.direccion.x *
|
|
bala.velocidad *
|
|
dt;
|
|
}
|
|
else
|
|
{
|
|
bala.activa = false;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (bordeY)
|
|
{
|
|
if (bala.rebotes < 1)
|
|
{
|
|
bala.direccion.y *= -1.0f;
|
|
bala.rebotes++;
|
|
|
|
destino.y =
|
|
inicio.y +
|
|
bala.direccion.y *
|
|
bala.velocidad *
|
|
dt;
|
|
}
|
|
else
|
|
{
|
|
bala.activa = false;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------
|
|
// PAREDES
|
|
// ----------------------------------------------------
|
|
|
|
bool chocoPared = false;
|
|
Rectangle paredGolpeada{};
|
|
|
|
for (const auto& pared : paredes)
|
|
{
|
|
if (
|
|
LineaChocaRectangulo(
|
|
inicio,
|
|
destino,
|
|
pared.rectangulo
|
|
)
|
|
)
|
|
{
|
|
chocoPared = true;
|
|
paredGolpeada =
|
|
pared.rectangulo;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (chocoPared)
|
|
{
|
|
// PRIMERA PARED:
|
|
// atraviesa sin rebotar.
|
|
if (bala.paredesAtraviesadas == 0)
|
|
{
|
|
bala.paredesAtraviesadas++;
|
|
|
|
bala.posicion =
|
|
destino;
|
|
|
|
continue;
|
|
}
|
|
|
|
// SEGUNDA PARED:
|
|
// rebota.
|
|
if (
|
|
bala.paredesAtraviesadas == 1 &&
|
|
bala.rebotes == 0
|
|
)
|
|
{
|
|
bala.paredesAtraviesadas++;
|
|
bala.rebotes++;
|
|
|
|
float izquierda =
|
|
std::fabs(
|
|
inicio.x -
|
|
paredGolpeada.x
|
|
);
|
|
|
|
float derecha =
|
|
std::fabs(
|
|
inicio.x -
|
|
(
|
|
paredGolpeada.x +
|
|
paredGolpeada.width
|
|
)
|
|
);
|
|
|
|
float arriba =
|
|
std::fabs(
|
|
inicio.y -
|
|
paredGolpeada.y
|
|
);
|
|
|
|
float abajo =
|
|
std::fabs(
|
|
inicio.y -
|
|
(
|
|
paredGolpeada.y +
|
|
paredGolpeada.height
|
|
)
|
|
);
|
|
|
|
float minimo =
|
|
std::min(
|
|
std::min(
|
|
izquierda,
|
|
derecha
|
|
),
|
|
std::min(
|
|
arriba,
|
|
abajo
|
|
)
|
|
);
|
|
|
|
if (
|
|
minimo == izquierda ||
|
|
minimo == derecha
|
|
)
|
|
{
|
|
bala.direccion.x *= -1.0f;
|
|
}
|
|
else
|
|
{
|
|
bala.direccion.y *= -1.0f;
|
|
}
|
|
|
|
bala.posicion = {
|
|
inicio.x +
|
|
bala.direccion.x * 8.0f,
|
|
|
|
inicio.y +
|
|
bala.direccion.y * 8.0f
|
|
};
|
|
|
|
continue;
|
|
}
|
|
|
|
// TERCERA PARED:
|
|
// desaparece.
|
|
bala.activa = false;
|
|
continue;
|
|
}
|
|
|
|
bala.posicion =
|
|
destino;
|
|
|
|
// ----------------------------------------------------
|
|
// GOLPEAR ENTIDADES
|
|
// ----------------------------------------------------
|
|
|
|
for (
|
|
int i = 0;
|
|
i < static_cast<int>(entidades.size());
|
|
i++
|
|
)
|
|
{
|
|
Entidad& entidad =
|
|
entidades[i];
|
|
|
|
if (!entidad.viva)
|
|
continue;
|
|
|
|
if (entidad.equipo == bala.equipo)
|
|
continue;
|
|
|
|
if (
|
|
Distancia(
|
|
bala.posicion,
|
|
entidad.posicion
|
|
) <
|
|
entidad.radio + 5.0f
|
|
)
|
|
{
|
|
entidad.vida -= bala.dano;
|
|
|
|
bala.activa = false;
|
|
|
|
if (entidad.vida <= 0)
|
|
{
|
|
entidad.vida = 0;
|
|
entidad.viva = false;
|
|
|
|
// Marca naranja si muere
|
|
// un compañero del jugador.
|
|
if (
|
|
entidad.equipo == EQUIPO_AZUL &&
|
|
!entidad.jugador
|
|
)
|
|
{
|
|
CrearMarcaMuerte(
|
|
marcas,
|
|
entidad.posicion
|
|
);
|
|
}
|
|
|
|
// Su arma cae al suelo
|
|
// conservando las balas.
|
|
if (
|
|
entidad.arma >= 0 &&
|
|
entidad.arma <
|
|
static_cast<int>(
|
|
armas.size()
|
|
)
|
|
)
|
|
{
|
|
Arma& arma =
|
|
armas[entidad.arma];
|
|
|
|
arma.enSuelo = true;
|
|
arma.activa = true;
|
|
arma.posicion =
|
|
entidad.posicion;
|
|
|
|
entidad.arma = -1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
balas.erase(
|
|
std::remove_if(
|
|
balas.begin(),
|
|
balas.end(),
|
|
[](const Bala& bala)
|
|
{
|
|
return !bala.activa;
|
|
}
|
|
),
|
|
balas.end()
|
|
);
|
|
}
|
|
|
|
// ============================================================
|
|
// PICKUPS
|
|
// ============================================================
|
|
|
|
bool PosicionLibre(
|
|
Vector2 posicion,
|
|
const std::vector<Pared>& paredes
|
|
)
|
|
{
|
|
for (const auto& pared : paredes)
|
|
{
|
|
if (
|
|
CirculoChocaRectangulo(
|
|
posicion,
|
|
18.0f,
|
|
pared.rectangulo
|
|
)
|
|
)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void CrearBotiquin(
|
|
std::vector<Botiquin>& botiquines,
|
|
const std::vector<Pared>& paredes
|
|
)
|
|
{
|
|
for (int intento = 0; intento < 100; intento++)
|
|
{
|
|
Vector2 posicion = {
|
|
static_cast<float>(
|
|
120 + rand() % 2560
|
|
),
|
|
static_cast<float>(
|
|
120 + rand() % 1660
|
|
)
|
|
};
|
|
|
|
if (
|
|
PosicionLibre(
|
|
posicion,
|
|
paredes
|
|
)
|
|
)
|
|
{
|
|
botiquines.push_back({
|
|
posicion,
|
|
true
|
|
});
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CrearMunicion(
|
|
std::vector<Municion>& municiones,
|
|
const std::vector<Pared>& paredes
|
|
)
|
|
{
|
|
for (int intento = 0; intento < 100; intento++)
|
|
{
|
|
Vector2 posicion = {
|
|
static_cast<float>(
|
|
120 + rand() % 2560
|
|
),
|
|
static_cast<float>(
|
|
120 + rand() % 1660
|
|
)
|
|
};
|
|
|
|
if (
|
|
PosicionLibre(
|
|
posicion,
|
|
paredes
|
|
)
|
|
)
|
|
{
|
|
municiones.push_back({
|
|
posicion,
|
|
true
|
|
});
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ActualizarBotiquines(
|
|
std::vector<Botiquin>& botiquines,
|
|
std::vector<Entidad>& entidades
|
|
)
|
|
{
|
|
for (auto& botiquin : botiquines)
|
|
{
|
|
if (!botiquin.activa)
|
|
continue;
|
|
|
|
for (Entidad& entidad : entidades)
|
|
{
|
|
if (!entidad.viva)
|
|
continue;
|
|
|
|
if (
|
|
Distancia(
|
|
botiquin.posicion,
|
|
entidad.posicion
|
|
) <
|
|
entidad.radio + 18.0f
|
|
)
|
|
{
|
|
if (
|
|
entidad.vida <
|
|
entidad.vidaMaxima
|
|
)
|
|
{
|
|
entidad.vida =
|
|
std::min(
|
|
entidad.vidaMaxima,
|
|
entidad.vida + 35.0f
|
|
);
|
|
|
|
botiquin.activa = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ActualizarMunicion(
|
|
std::vector<Municion>& municiones,
|
|
std::vector<Entidad>& entidades,
|
|
std::vector<Arma>& armas
|
|
)
|
|
{
|
|
for (auto& municion : municiones)
|
|
{
|
|
if (!municion.activa)
|
|
continue;
|
|
|
|
for (Entidad& entidad : entidades)
|
|
{
|
|
if (!entidad.viva)
|
|
continue;
|
|
|
|
if (entidad.arma < 0)
|
|
continue;
|
|
|
|
if (
|
|
entidad.arma >=
|
|
static_cast<int>(armas.size())
|
|
)
|
|
{
|
|
entidad.arma = -1;
|
|
continue;
|
|
}
|
|
|
|
if (
|
|
Distancia(
|
|
municion.posicion,
|
|
entidad.posicion
|
|
) <
|
|
entidad.radio + 18.0f
|
|
)
|
|
{
|
|
Arma& arma =
|
|
armas[entidad.arma];
|
|
|
|
arma.balas =
|
|
CapacidadArma(
|
|
arma.tipo
|
|
);
|
|
|
|
arma.cartuchos = 999999;
|
|
|
|
municion.activa = false;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================
|
|
// IA
|
|
// ============================================================
|
|
|
|
void ActualizarIA(
|
|
int indice,
|
|
std::vector<Entidad>& entidades,
|
|
std::vector<Arma>& armas,
|
|
std::vector<Bala>& balas,
|
|
const std::vector<Pared>& paredes,
|
|
float dt,
|
|
float tiempoPartida
|
|
)
|
|
{
|
|
Entidad& ia =
|
|
entidades[indice];
|
|
|
|
if (!ia.viva)
|
|
return;
|
|
|
|
ia.tiempoDisparo =
|
|
std::max(
|
|
0.0f,
|
|
ia.tiempoDisparo - dt
|
|
);
|
|
|
|
ActualizarRecarga(
|
|
ia,
|
|
armas,
|
|
dt
|
|
);
|
|
|
|
// --------------------------------------------------------
|
|
// BUSCAR ARMA
|
|
// --------------------------------------------------------
|
|
|
|
if (ia.arma < 0)
|
|
{
|
|
int armaCercana =
|
|
BuscarArmaCercana(
|
|
ia,
|
|
armas
|
|
);
|
|
|
|
if (armaCercana >= 0)
|
|
{
|
|
RecogerArma(
|
|
ia,
|
|
armaCercana,
|
|
armas
|
|
);
|
|
}
|
|
}
|
|
|
|
if (ia.arma < 0)
|
|
{
|
|
Vector2 direccion = {
|
|
ia.equipo == EQUIPO_AZUL
|
|
? 1.0f
|
|
: -1.0f,
|
|
0
|
|
};
|
|
|
|
MoverEntidad(
|
|
ia,
|
|
Multiplicar(
|
|
direccion,
|
|
VELOCIDAD_IA * dt
|
|
),
|
|
paredes
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
if (
|
|
ia.arma >=
|
|
static_cast<int>(armas.size())
|
|
)
|
|
{
|
|
ia.arma = -1;
|
|
return;
|
|
}
|
|
|
|
Arma& arma =
|
|
armas[ia.arma];
|
|
|
|
if (arma.balas <= 0)
|
|
{
|
|
IniciarRecarga(
|
|
ia,
|
|
armas
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
int enemigo =
|
|
BuscarEnemigo(
|
|
indice,
|
|
entidades,
|
|
paredes
|
|
);
|
|
|
|
Vector2 direccionMovimiento = {
|
|
0,
|
|
0
|
|
};
|
|
|
|
if (enemigo >= 0)
|
|
{
|
|
Entidad& objetivo =
|
|
entidades[enemigo];
|
|
|
|
Vector2 haciaObjetivo = {
|
|
objetivo.posicion.x -
|
|
ia.posicion.x,
|
|
|
|
objetivo.posicion.y -
|
|
ia.posicion.y
|
|
};
|
|
|
|
float distancia =
|
|
Distancia(
|
|
ia.posicion,
|
|
objetivo.posicion
|
|
);
|
|
|
|
haciaObjetivo =
|
|
Normalizar(
|
|
haciaObjetivo
|
|
);
|
|
|
|
ia.direccion =
|
|
haciaObjetivo;
|
|
|
|
if (distancia > 480.0f)
|
|
{
|
|
direccionMovimiento =
|
|
haciaObjetivo;
|
|
}
|
|
else if (distancia < 250.0f)
|
|
{
|
|
direccionMovimiento =
|
|
Multiplicar(
|
|
haciaObjetivo,
|
|
-1.0f
|
|
);
|
|
}
|
|
else
|
|
{
|
|
direccionMovimiento = {
|
|
-haciaObjetivo.y,
|
|
haciaObjetivo.x
|
|
};
|
|
|
|
float signo =
|
|
std::sin(
|
|
GetTime() *
|
|
1.5 +
|
|
indice * 3
|
|
);
|
|
|
|
if (signo < 0)
|
|
{
|
|
direccionMovimiento.x *= -1;
|
|
direccionMovimiento.y *= -1;
|
|
}
|
|
}
|
|
|
|
// Protección inicial:
|
|
// durante 3 segundos no disparan.
|
|
if (
|
|
tiempoPartida > 3.0f &&
|
|
distancia < 900.0f &&
|
|
arma.balas > 0
|
|
)
|
|
{
|
|
Disparar(
|
|
ia,
|
|
armas,
|
|
balas
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
float tiempo =
|
|
GetTime() +
|
|
indice * 5.0f;
|
|
|
|
direccionMovimiento = {
|
|
std::cos(
|
|
tiempo * 0.45f
|
|
),
|
|
std::sin(
|
|
tiempo * 0.37f
|
|
)
|
|
};
|
|
|
|
direccionMovimiento =
|
|
Normalizar(
|
|
direccionMovimiento
|
|
);
|
|
}
|
|
|
|
// Separación entre compañeros.
|
|
Vector2 separacion =
|
|
FuerzaSeparacion(
|
|
indice,
|
|
entidades
|
|
);
|
|
|
|
direccionMovimiento.x +=
|
|
separacion.x * 2.0f;
|
|
|
|
direccionMovimiento.y +=
|
|
separacion.y * 2.0f;
|
|
|
|
direccionMovimiento =
|
|
Normalizar(
|
|
direccionMovimiento
|
|
);
|
|
|
|
// Evitar paredes.
|
|
Vector2 prueba = {
|
|
ia.posicion.x +
|
|
direccionMovimiento.x * 80.0f,
|
|
|
|
ia.posicion.y +
|
|
direccionMovimiento.y * 80.0f
|
|
};
|
|
|
|
if (
|
|
EntidadChocaPared(
|
|
prueba,
|
|
ia.radio,
|
|
paredes
|
|
)
|
|
)
|
|
{
|
|
direccionMovimiento =
|
|
BuscarDireccionLibre(
|
|
ia,
|
|
paredes
|
|
);
|
|
}
|
|
|
|
Vector2 antes =
|
|
ia.posicion;
|
|
|
|
MoverEntidad(
|
|
ia,
|
|
Multiplicar(
|
|
direccionMovimiento,
|
|
VELOCIDAD_IA * dt
|
|
),
|
|
paredes
|
|
);
|
|
|
|
float movimiento =
|
|
Distancia(
|
|
antes,
|
|
ia.posicion
|
|
);
|
|
|
|
if (movimiento < 1.5f)
|
|
ia.tiempoAtascado += dt;
|
|
else
|
|
ia.tiempoAtascado = 0;
|
|
|
|
// Desatascar.
|
|
if (ia.tiempoAtascado > 0.45f)
|
|
{
|
|
Vector2 libre =
|
|
BuscarDireccionLibre(
|
|
ia,
|
|
paredes
|
|
);
|
|
|
|
MoverEntidad(
|
|
ia,
|
|
Multiplicar(
|
|
libre,
|
|
VELOCIDAD_IA *
|
|
dt *
|
|
3.0f
|
|
),
|
|
paredes
|
|
);
|
|
|
|
ia.tiempoAtascado = 0;
|
|
}
|
|
|
|
ia.ultimaPosicion =
|
|
ia.posicion;
|
|
}
|
|
|
|
// ============================================================
|
|
// DIBUJAR MAPA
|
|
// ============================================================
|
|
|
|
void DibujarMapa(
|
|
const std::vector<Pared>& paredes
|
|
)
|
|
{
|
|
DrawRectangle(
|
|
0,
|
|
0,
|
|
static_cast<int>(MUNDO_ANCHO),
|
|
static_cast<int>(MUNDO_ALTO),
|
|
Color{
|
|
47,
|
|
49,
|
|
54,
|
|
255
|
|
}
|
|
);
|
|
|
|
for (
|
|
int x = 0;
|
|
x < static_cast<int>(MUNDO_ANCHO);
|
|
x += 100
|
|
)
|
|
{
|
|
DrawLine(
|
|
x,
|
|
0,
|
|
x,
|
|
static_cast<int>(MUNDO_ALTO),
|
|
Color{
|
|
55,
|
|
57,
|
|
62,
|
|
255
|
|
}
|
|
);
|
|
}
|
|
|
|
for (
|
|
int y = 0;
|
|
y < static_cast<int>(MUNDO_ALTO);
|
|
y += 100
|
|
)
|
|
{
|
|
DrawLine(
|
|
0,
|
|
y,
|
|
static_cast<int>(MUNDO_ANCHO),
|
|
y,
|
|
Color{
|
|
55,
|
|
57,
|
|
62,
|
|
255
|
|
}
|
|
);
|
|
}
|
|
|
|
for (const auto& pared : paredes)
|
|
{
|
|
DrawRectangleRec(
|
|
pared.rectangulo,
|
|
Color{
|
|
25,
|
|
27,
|
|
31,
|
|
255
|
|
}
|
|
);
|
|
|
|
DrawRectangleLinesEx(
|
|
pared.rectangulo,
|
|
2,
|
|
Color{
|
|
90,
|
|
94,
|
|
100,
|
|
255
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
// ============================================================
|
|
// DIBUJAR ARMAS
|
|
// ============================================================
|
|
|
|
void DibujarArmas(
|
|
const std::vector<Arma>& armas
|
|
)
|
|
{
|
|
for (const Arma& arma : armas)
|
|
{
|
|
if (!arma.activa)
|
|
continue;
|
|
|
|
if (!arma.enSuelo)
|
|
continue;
|
|
|
|
DrawCircleV(
|
|
arma.posicion,
|
|
13,
|
|
ColorArma(arma.tipo)
|
|
);
|
|
|
|
DrawCircleLines(
|
|
static_cast<int>(arma.posicion.x),
|
|
static_cast<int>(arma.posicion.y),
|
|
15,
|
|
BLACK
|
|
);
|
|
|
|
DrawText(
|
|
NombreArma(arma.tipo),
|
|
static_cast<int>(arma.posicion.x - 35),
|
|
static_cast<int>(arma.posicion.y + 18),
|
|
10,
|
|
WHITE
|
|
);
|
|
}
|
|
}
|
|
|
|
// ============================================================
|
|
// BOTIQUINES
|
|
// ============================================================
|
|
|
|
void DibujarBotiquines(
|
|
const std::vector<Botiquin>& botiquines
|
|
)
|
|
{
|
|
for (const auto& botiquin : botiquines)
|
|
{
|
|
if (!botiquin.activa)
|
|
continue;
|
|
|
|
DrawCircleV(
|
|
botiquin.posicion,
|
|
15,
|
|
GREEN
|
|
);
|
|
|
|
DrawRectangle(
|
|
static_cast<int>(botiquin.posicion.x - 4),
|
|
static_cast<int>(botiquin.posicion.y - 10),
|
|
8,
|
|
20,
|
|
WHITE
|
|
);
|
|
|
|
DrawRectangle(
|
|
static_cast<int>(botiquin.posicion.x - 10),
|
|
static_cast<int>(botiquin.posicion.y - 4),
|
|
20,
|
|
8,
|
|
WHITE
|
|
);
|
|
}
|
|
}
|
|
|
|
// ============================================================
|
|
// MUNICIÓN
|
|
// ============================================================
|
|
|
|
void DibujarMunicion(
|
|
const std::vector<Municion>& municiones
|
|
)
|
|
{
|
|
for (const auto& municion : municiones)
|
|
{
|
|
if (!municion.activa)
|
|
continue;
|
|
|
|
DrawRectangle(
|
|
static_cast<int>(municion.posicion.x - 13),
|
|
static_cast<int>(municion.posicion.y - 10),
|
|
26,
|
|
20,
|
|
GOLD
|
|
);
|
|
|
|
DrawRectangleLines(
|
|
static_cast<int>(municion.posicion.x - 13),
|
|
static_cast<int>(municion.posicion.y - 10),
|
|
26,
|
|
20,
|
|
BLACK
|
|
);
|
|
|
|
DrawText(
|
|
"AM",
|
|
static_cast<int>(municion.posicion.x - 8),
|
|
static_cast<int>(municion.posicion.y - 7),
|
|
12,
|
|
BLACK
|
|
);
|
|
}
|
|
}
|
|
|
|
// ============================================================
|
|
// ENTIDADES
|
|
// ============================================================
|
|
|
|
void DibujarEntidades(
|
|
const std::vector<Entidad>& entidades
|
|
)
|
|
{
|
|
for (const auto& entidad : entidades)
|
|
{
|
|
if (!entidad.viva)
|
|
continue;
|
|
|
|
Color color =
|
|
entidad.equipo == EQUIPO_AZUL
|
|
? BLUE
|
|
: RED;
|
|
|
|
DrawCircleV(
|
|
entidad.posicion,
|
|
entidad.radio,
|
|
color
|
|
);
|
|
|
|
DrawCircleLines(
|
|
static_cast<int>(entidad.posicion.x),
|
|
static_cast<int>(entidad.posicion.y),
|
|
entidad.radio,
|
|
WHITE
|
|
);
|
|
|
|
DrawLineEx(
|
|
entidad.posicion,
|
|
{
|
|
entidad.posicion.x +
|
|
entidad.direccion.x *
|
|
(entidad.radio + 10),
|
|
|
|
entidad.posicion.y +
|
|
entidad.direccion.y *
|
|
(entidad.radio + 10)
|
|
},
|
|
4,
|
|
WHITE
|
|
);
|
|
|
|
float porcentaje =
|
|
entidad.vida /
|
|
entidad.vidaMaxima;
|
|
|
|
DrawRectangle(
|
|
static_cast<int>(entidad.posicion.x - 25),
|
|
static_cast<int>(entidad.posicion.y - 34),
|
|
50,
|
|
6,
|
|
DARKGRAY
|
|
);
|
|
|
|
DrawRectangle(
|
|
static_cast<int>(entidad.posicion.x - 25),
|
|
static_cast<int>(entidad.posicion.y - 34),
|
|
static_cast<int>(50 * porcentaje),
|
|
6,
|
|
GREEN
|
|
);
|
|
|
|
if (entidad.jugador)
|
|
{
|
|
DrawCircleLines(
|
|
static_cast<int>(entidad.posicion.x),
|
|
static_cast<int>(entidad.posicion.y),
|
|
entidad.radio + 5,
|
|
WHITE
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================
|
|
// MINIMAPA
|
|
// ============================================================
|
|
|
|
void DibujarMinimapa(
|
|
const std::vector<Pared>& paredes,
|
|
const std::vector<Entidad>& entidades,
|
|
const std::vector<MarcaMuerte>& marcas
|
|
)
|
|
{
|
|
const int mapaX = 820;
|
|
const int mapaY = 8;
|
|
const int mapaAncho = 440;
|
|
const int mapaAlto = 58;
|
|
|
|
DrawRectangle(
|
|
mapaX,
|
|
mapaY,
|
|
mapaAncho,
|
|
mapaAlto,
|
|
Color{
|
|
10,
|
|
12,
|
|
16,
|
|
245
|
|
}
|
|
);
|
|
|
|
DrawRectangleLines(
|
|
mapaX,
|
|
mapaY,
|
|
mapaAncho,
|
|
mapaAlto,
|
|
LIGHTGRAY
|
|
);
|
|
|
|
float escalaX =
|
|
static_cast<float>(mapaAncho) /
|
|
MUNDO_ANCHO;
|
|
|
|
float escalaY =
|
|
static_cast<float>(mapaAlto) /
|
|
MUNDO_ALTO;
|
|
|
|
// Paredes
|
|
for (const auto& pared : paredes)
|
|
{
|
|
int x =
|
|
mapaX +
|
|
static_cast<int>(
|
|
pared.rectangulo.x * escalaX
|
|
);
|
|
|
|
int y =
|
|
mapaY +
|
|
static_cast<int>(
|
|
pared.rectangulo.y * escalaY
|
|
);
|
|
|
|
int w =
|
|
std::max(
|
|
1,
|
|
static_cast<int>(
|
|
pared.rectangulo.width *
|
|
escalaX
|
|
)
|
|
);
|
|
|
|
int h =
|
|
std::max(
|
|
1,
|
|
static_cast<int>(
|
|
pared.rectangulo.height *
|
|
escalaY
|
|
)
|
|
);
|
|
|
|
DrawRectangle(
|
|
x,
|
|
y,
|
|
w,
|
|
h,
|
|
Color{
|
|
80,
|
|
83,
|
|
88,
|
|
255
|
|
}
|
|
);
|
|
}
|
|
|
|
// Muertes de compañeros.
|
|
for (const auto& marca : marcas)
|
|
{
|
|
if (!marca.activa)
|
|
continue;
|
|
|
|
int x =
|
|
mapaX +
|
|
static_cast<int>(
|
|
marca.posicion.x * escalaX
|
|
);
|
|
|
|
int y =
|
|
mapaY +
|
|
static_cast<int>(
|
|
marca.posicion.y * escalaY
|
|
);
|
|
|
|
DrawCircle(
|
|
x,
|
|
y,
|
|
5,
|
|
ORANGE
|
|
);
|
|
|
|
DrawCircleLines(
|
|
x,
|
|
y,
|
|
8,
|
|
GOLD
|
|
);
|
|
}
|
|
|
|
// Solo equipo azul.
|
|
for (const auto& entidad : entidades)
|
|
{
|
|
if (!entidad.viva)
|
|
continue;
|
|
|
|
if (entidad.equipo != EQUIPO_AZUL)
|
|
continue;
|
|
|
|
int x =
|
|
mapaX +
|
|
static_cast<int>(
|
|
entidad.posicion.x * escalaX
|
|
);
|
|
|
|
int y =
|
|
mapaY +
|
|
static_cast<int>(
|
|
entidad.posicion.y * escalaY
|
|
);
|
|
|
|
if (entidad.jugador)
|
|
{
|
|
DrawCircle(
|
|
x,
|
|
y,
|
|
5,
|
|
WHITE
|
|
);
|
|
|
|
DrawCircleLines(
|
|
x,
|
|
y,
|
|
8,
|
|
BLUE
|
|
);
|
|
}
|
|
else
|
|
{
|
|
DrawCircle(
|
|
x,
|
|
y,
|
|
4,
|
|
SKYBLUE
|
|
);
|
|
}
|
|
}
|
|
|
|
DrawText(
|
|
"MAPA",
|
|
mapaX + 6,
|
|
mapaY + 4,
|
|
9,
|
|
LIGHTGRAY
|
|
);
|
|
}
|
|
|
|
// ============================================================
|
|
// HUD
|
|
// ============================================================
|
|
|
|
void DibujarHUD(
|
|
const Entidad& jugador,
|
|
const std::vector<Arma>& armas
|
|
)
|
|
{
|
|
DrawRectangle(
|
|
0,
|
|
0,
|
|
PANTALLA_ANCHO,
|
|
74,
|
|
Color{
|
|
10,
|
|
12,
|
|
16,
|
|
245
|
|
}
|
|
);
|
|
|
|
DrawText(
|
|
TextFormat(
|
|
"VIDA: %.0f / %.0f",
|
|
jugador.vida,
|
|
jugador.vidaMaxima
|
|
),
|
|
15,
|
|
10,
|
|
18,
|
|
WHITE
|
|
);
|
|
|
|
if (
|
|
jugador.arma >= 0 &&
|
|
jugador.arma <
|
|
static_cast<int>(armas.size())
|
|
)
|
|
{
|
|
const Arma& arma =
|
|
armas[jugador.arma];
|
|
|
|
DrawText(
|
|
TextFormat(
|
|
"ARMA: %s",
|
|
NombreArma(arma.tipo)
|
|
),
|
|
15,
|
|
38,
|
|
15,
|
|
ColorArma(arma.tipo)
|
|
);
|
|
|
|
DrawText(
|
|
TextFormat(
|
|
"BALAS: %d / %d",
|
|
arma.balas,
|
|
CapacidadArma(arma.tipo)
|
|
),
|
|
220,
|
|
14,
|
|
18,
|
|
WHITE
|
|
);
|
|
|
|
DrawText(
|
|
"CARTUCHOS: INFINITOS",
|
|
220,
|
|
40,
|
|
15,
|
|
GREEN
|
|
);
|
|
}
|
|
else
|
|
{
|
|
DrawText(
|
|
"SIN ARMA",
|
|
220,
|
|
20,
|
|
18,
|
|
RED
|
|
);
|
|
}
|
|
|
|
DrawText(
|
|
TextFormat(
|
|
"FPS: %d",
|
|
GetFPS()
|
|
),
|
|
700,
|
|
12,
|
|
18,
|
|
GREEN
|
|
);
|
|
}
|
|
|
|
// ============================================================
|
|
// MAIN
|
|
// ============================================================
|
|
|
|
int main()
|
|
{
|
|
srand(
|
|
static_cast<unsigned int>(
|
|
time(nullptr)
|
|
)
|
|
);
|
|
|
|
InitWindow(
|
|
PANTALLA_ANCHO,
|
|
PANTALLA_ALTO,
|
|
"A4B1 0.0.2"
|
|
);
|
|
|
|
SetTargetFPS(60);
|
|
|
|
// ========================================================
|
|
// MAPA
|
|
// ========================================================
|
|
|
|
std::vector<Pared> paredes =
|
|
CrearMapa();
|
|
|
|
// ========================================================
|
|
// ARMAS DEL SUELO
|
|
// ========================================================
|
|
|
|
std::vector<Arma> armas;
|
|
|
|
armas.push_back(
|
|
CrearArma(
|
|
ARMA_RAPIDA,
|
|
{650, 450},
|
|
true
|
|
)
|
|
);
|
|
|
|
armas.push_back(
|
|
CrearArma(
|
|
ARMA_EQUILIBRADA,
|
|
{2150, 450},
|
|
true
|
|
)
|
|
);
|
|
|
|
armas.push_back(
|
|
CrearArma(
|
|
ARMA_PESADA,
|
|
{650, 1400},
|
|
true
|
|
)
|
|
);
|
|
|
|
armas.push_back(
|
|
CrearArma(
|
|
ARMA_PRECISA,
|
|
{2150, 1400},
|
|
true
|
|
)
|
|
);
|
|
|
|
// ========================================================
|
|
// 3 VS 3
|
|
//
|
|
// AZUL: lado izquierdo
|
|
// ROJO: lado derecho
|
|
//
|
|
// MUY SEPARADOS.
|
|
// ========================================================
|
|
|
|
std::vector<Entidad> entidades;
|
|
|
|
// Jugador azul
|
|
entidades.push_back({
|
|
{250, 500},
|
|
{0, 0},
|
|
{1, 0},
|
|
|
|
RADIO_JUGADOR,
|
|
|
|
100,
|
|
100,
|
|
|
|
EQUIPO_AZUL,
|
|
|
|
true,
|
|
true,
|
|
|
|
-1,
|
|
|
|
false,
|
|
0,
|
|
|
|
0,
|
|
0,
|
|
|
|
{250, 500}
|
|
});
|
|
|
|
// Compañero azul
|
|
entidades.push_back({
|
|
{250, 850},
|
|
{0, 0},
|
|
{1, 0},
|
|
|
|
RADIO_IA,
|
|
|
|
100,
|
|
100,
|
|
|
|
EQUIPO_AZUL,
|
|
|
|
false,
|
|
true,
|
|
|
|
-1,
|
|
|
|
false,
|
|
0,
|
|
|
|
0,
|
|
0,
|
|
|
|
{250, 850}
|
|
});
|
|
|
|
// Compañero azul
|
|
entidades.push_back({
|
|
{250, 1200},
|
|
{0, 0},
|
|
{1, 0},
|
|
|
|
RADIO_IA,
|
|
|
|
100,
|
|
100,
|
|
|
|
EQUIPO_AZUL,
|
|
|
|
false,
|
|
true,
|
|
|
|
-1,
|
|
|
|
false,
|
|
0,
|
|
|
|
0,
|
|
0,
|
|
|
|
{250, 1200}
|
|
});
|
|
|
|
// Enemigo rojo
|
|
entidades.push_back({
|
|
{2550, 500},
|
|
{0, 0},
|
|
{-1, 0},
|
|
|
|
RADIO_IA,
|
|
|
|
100,
|
|
100,
|
|
|
|
EQUIPO_ROJO,
|
|
|
|
false,
|
|
true,
|
|
|
|
-1,
|
|
|
|
false,
|
|
0,
|
|
|
|
0,
|
|
0,
|
|
|
|
{2550, 500}
|
|
});
|
|
|
|
// Enemigo rojo
|
|
entidades.push_back({
|
|
{2550, 850},
|
|
{0, 0},
|
|
{-1, 0},
|
|
|
|
RADIO_IA,
|
|
|
|
100,
|
|
100,
|
|
|
|
EQUIPO_ROJO,
|
|
|
|
false,
|
|
true,
|
|
|
|
-1,
|
|
|
|
false,
|
|
0,
|
|
|
|
0,
|
|
0,
|
|
|
|
{2550, 850}
|
|
});
|
|
|
|
// Enemigo rojo
|
|
entidades.push_back({
|
|
{2550, 1200},
|
|
{0, 0},
|
|
{-1, 0},
|
|
|
|
RADIO_IA,
|
|
|
|
100,
|
|
100,
|
|
|
|
EQUIPO_ROJO,
|
|
|
|
false,
|
|
true,
|
|
|
|
-1,
|
|
|
|
false,
|
|
0,
|
|
|
|
0,
|
|
0,
|
|
|
|
{2550, 1200}
|
|
});
|
|
|
|
// ========================================================
|
|
// UN ARMA EXCLUSIVA PARA CADA JUGADOR
|
|
// ========================================================
|
|
|
|
armas.push_back(
|
|
CrearArma(
|
|
ARMA_EQUILIBRADA,
|
|
{0, 0},
|
|
false
|
|
)
|
|
);
|
|
entidades[0].arma =
|
|
static_cast<int>(armas.size()) - 1;
|
|
|
|
armas.push_back(
|
|
CrearArma(
|
|
ARMA_RAPIDA,
|
|
{0, 0},
|
|
false
|
|
)
|
|
);
|
|
entidades[1].arma =
|
|
static_cast<int>(armas.size()) - 1;
|
|
|
|
armas.push_back(
|
|
CrearArma(
|
|
ARMA_PESADA,
|
|
{0, 0},
|
|
false
|
|
)
|
|
);
|
|
entidades[2].arma =
|
|
static_cast<int>(armas.size()) - 1;
|
|
|
|
armas.push_back(
|
|
CrearArma(
|
|
ARMA_PRECISA,
|
|
{0, 0},
|
|
false
|
|
)
|
|
);
|
|
entidades[3].arma =
|
|
static_cast<int>(armas.size()) - 1;
|
|
|
|
armas.push_back(
|
|
CrearArma(
|
|
ARMA_EQUILIBRADA,
|
|
{0, 0},
|
|
false
|
|
)
|
|
);
|
|
entidades[4].arma =
|
|
static_cast<int>(armas.size()) - 1;
|
|
|
|
armas.push_back(
|
|
CrearArma(
|
|
ARMA_PESADA,
|
|
{0, 0},
|
|
false
|
|
)
|
|
);
|
|
entidades[5].arma =
|
|
static_cast<int>(armas.size()) - 1;
|
|
|
|
// ========================================================
|
|
// BALAS
|
|
// ========================================================
|
|
|
|
std::vector<Bala> balas;
|
|
|
|
// ========================================================
|
|
// BOTIQUINES
|
|
// ========================================================
|
|
|
|
std::vector<Botiquin> botiquines;
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
CrearBotiquin(
|
|
botiquines,
|
|
paredes
|
|
);
|
|
}
|
|
|
|
// ========================================================
|
|
// MUNICIÓN
|
|
// ========================================================
|
|
|
|
std::vector<Municion> municiones;
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
CrearMunicion(
|
|
municiones,
|
|
paredes
|
|
);
|
|
}
|
|
|
|
// ========================================================
|
|
// MARCAS DE MUERTE
|
|
// ========================================================
|
|
|
|
std::vector<MarcaMuerte> marcas;
|
|
|
|
// ========================================================
|
|
// CÁMARA
|
|
// ========================================================
|
|
|
|
Camera2D camara{};
|
|
|
|
camara.offset = {
|
|
PANTALLA_ANCHO / 2.0f,
|
|
PANTALLA_ALTO / 2.0f
|
|
};
|
|
|
|
camara.target =
|
|
entidades[0].posicion;
|
|
|
|
camara.rotation = 0;
|
|
camara.zoom = 1.0f;
|
|
|
|
// ========================================================
|
|
// TIEMPO
|
|
// ========================================================
|
|
|
|
float tiempoPartida = 0.0f;
|
|
|
|
// ========================================================
|
|
// LOOP PRINCIPAL
|
|
// ========================================================
|
|
|
|
while (!WindowShouldClose())
|
|
{
|
|
float dt =
|
|
GetFrameTime();
|
|
|
|
tiempoPartida += dt;
|
|
|
|
// ====================================================
|
|
// JUGADOR
|
|
// ====================================================
|
|
|
|
Entidad& jugador =
|
|
entidades[0];
|
|
|
|
if (jugador.viva)
|
|
{
|
|
jugador.tiempoDisparo =
|
|
std::max(
|
|
0.0f,
|
|
jugador.tiempoDisparo - dt
|
|
);
|
|
|
|
ActualizarRecarga(
|
|
jugador,
|
|
armas,
|
|
dt
|
|
);
|
|
|
|
Vector2 movimiento = {
|
|
0,
|
|
0
|
|
};
|
|
|
|
if (IsKeyDown(KEY_W))
|
|
movimiento.y -= 1;
|
|
|
|
if (IsKeyDown(KEY_S))
|
|
movimiento.y += 1;
|
|
|
|
if (IsKeyDown(KEY_A))
|
|
movimiento.x -= 1;
|
|
|
|
if (IsKeyDown(KEY_D))
|
|
movimiento.x += 1;
|
|
|
|
movimiento =
|
|
Normalizar(
|
|
movimiento
|
|
);
|
|
|
|
MoverEntidad(
|
|
jugador,
|
|
Multiplicar(
|
|
movimiento,
|
|
VELOCIDAD_JUGADOR * dt
|
|
),
|
|
paredes
|
|
);
|
|
|
|
if (
|
|
movimiento.x != 0 ||
|
|
movimiento.y != 0
|
|
)
|
|
{
|
|
jugador.direccion =
|
|
movimiento;
|
|
}
|
|
|
|
if (
|
|
IsKeyDown(KEY_SPACE) &&
|
|
tiempoPartida > 3.0f
|
|
)
|
|
{
|
|
Disparar(
|
|
jugador,
|
|
armas,
|
|
balas
|
|
);
|
|
}
|
|
|
|
if (IsKeyPressed(KEY_R))
|
|
{
|
|
IniciarRecarga(
|
|
jugador,
|
|
armas
|
|
);
|
|
}
|
|
|
|
if (IsKeyPressed(KEY_E))
|
|
{
|
|
int armaCercana =
|
|
BuscarArmaCercana(
|
|
jugador,
|
|
armas
|
|
);
|
|
|
|
if (armaCercana >= 0)
|
|
{
|
|
RecogerArma(
|
|
jugador,
|
|
armaCercana,
|
|
armas
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ====================================================
|
|
// IA
|
|
// ====================================================
|
|
|
|
for (
|
|
int i = 1;
|
|
i < static_cast<int>(entidades.size());
|
|
i++
|
|
)
|
|
{
|
|
ActualizarIA(
|
|
i,
|
|
entidades,
|
|
armas,
|
|
balas,
|
|
paredes,
|
|
dt,
|
|
tiempoPartida
|
|
);
|
|
}
|
|
|
|
// ====================================================
|
|
// BALAS
|
|
// ====================================================
|
|
|
|
MoverBalas(
|
|
balas,
|
|
paredes,
|
|
entidades,
|
|
marcas,
|
|
armas,
|
|
dt
|
|
);
|
|
|
|
// ====================================================
|
|
// BOTIQUINES
|
|
// ====================================================
|
|
|
|
ActualizarBotiquines(
|
|
botiquines,
|
|
entidades
|
|
);
|
|
|
|
int botiquinesActivos = 0;
|
|
|
|
for (const auto& botiquin : botiquines)
|
|
{
|
|
if (botiquin.activa)
|
|
botiquinesActivos++;
|
|
}
|
|
|
|
while (botiquinesActivos < 5)
|
|
{
|
|
CrearBotiquin(
|
|
botiquines,
|
|
paredes
|
|
);
|
|
|
|
botiquinesActivos = 0;
|
|
|
|
for (const auto& botiquin : botiquines)
|
|
{
|
|
if (botiquin.activa)
|
|
botiquinesActivos++;
|
|
}
|
|
|
|
if (botiquines.size() > 30)
|
|
break;
|
|
}
|
|
|
|
// ====================================================
|
|
// MUNICIÓN
|
|
// ====================================================
|
|
|
|
ActualizarMunicion(
|
|
municiones,
|
|
entidades,
|
|
armas
|
|
);
|
|
|
|
int municionActiva = 0;
|
|
|
|
for (const auto& municion : municiones)
|
|
{
|
|
if (municion.activa)
|
|
municionActiva++;
|
|
}
|
|
|
|
while (municionActiva < 5)
|
|
{
|
|
CrearMunicion(
|
|
municiones,
|
|
paredes
|
|
);
|
|
|
|
municionActiva = 0;
|
|
|
|
for (const auto& municion : municiones)
|
|
{
|
|
if (municion.activa)
|
|
municionActiva++;
|
|
}
|
|
|
|
if (municiones.size() > 30)
|
|
break;
|
|
}
|
|
|
|
// ====================================================
|
|
// CÁMARA
|
|
// ====================================================
|
|
|
|
camara.target =
|
|
jugador.posicion;
|
|
|
|
// ====================================================
|
|
// ZOOM
|
|
// ====================================================
|
|
|
|
if (IsKeyDown(KEY_MINUS))
|
|
{
|
|
camara.zoom -=
|
|
0.5f * dt;
|
|
}
|
|
|
|
if (IsKeyDown(KEY_EQUAL))
|
|
{
|
|
camara.zoom +=
|
|
0.5f * dt;
|
|
}
|
|
|
|
camara.zoom =
|
|
std::clamp(
|
|
camara.zoom,
|
|
0.65f,
|
|
1.4f
|
|
);
|
|
|
|
// ====================================================
|
|
// FULLSCREEN
|
|
// ====================================================
|
|
|
|
if (IsKeyPressed(KEY_F11))
|
|
{
|
|
ToggleFullscreen();
|
|
}
|
|
|
|
// ====================================================
|
|
// DIBUJAR
|
|
// ====================================================
|
|
|
|
BeginDrawing();
|
|
|
|
ClearBackground(BLACK);
|
|
|
|
BeginMode2D(camara);
|
|
|
|
DibujarMapa(
|
|
paredes
|
|
);
|
|
|
|
DibujarBotiquines(
|
|
botiquines
|
|
);
|
|
|
|
DibujarMunicion(
|
|
municiones
|
|
);
|
|
|
|
DibujarArmas(
|
|
armas
|
|
);
|
|
|
|
// Balas
|
|
for (const Bala& bala : balas)
|
|
{
|
|
if (!bala.activa)
|
|
continue;
|
|
|
|
Color color =
|
|
bala.equipo == EQUIPO_AZUL
|
|
? SKYBLUE
|
|
: ORANGE;
|
|
|
|
DrawCircleV(
|
|
bala.posicion,
|
|
5,
|
|
color
|
|
);
|
|
}
|
|
|
|
DibujarEntidades(
|
|
entidades
|
|
);
|
|
|
|
EndMode2D();
|
|
|
|
// ====================================================
|
|
// OSCURIDAD
|
|
// ====================================================
|
|
|
|
DrawRectangle(
|
|
0,
|
|
74,
|
|
PANTALLA_ANCHO,
|
|
PANTALLA_ALTO - 74,
|
|
Color{
|
|
0,
|
|
0,
|
|
0,
|
|
115
|
|
}
|
|
);
|
|
|
|
// ====================================================
|
|
// HUD
|
|
// ====================================================
|
|
|
|
DibujarHUD(
|
|
jugador,
|
|
armas
|
|
);
|
|
|
|
// ====================================================
|
|
// MINIMAPA
|
|
// ====================================================
|
|
|
|
DibujarMinimapa(
|
|
paredes,
|
|
entidades,
|
|
marcas
|
|
);
|
|
|
|
// ====================================================
|
|
// CONTROLES
|
|
// ====================================================
|
|
|
|
DrawText(
|
|
"WASD: mover",
|
|
15,
|
|
685,
|
|
15,
|
|
LIGHTGRAY
|
|
);
|
|
|
|
DrawText(
|
|
"SPACE: disparar",
|
|
130,
|
|
685,
|
|
15,
|
|
LIGHTGRAY
|
|
);
|
|
|
|
DrawText(
|
|
"R: recargar",
|
|
275,
|
|
685,
|
|
15,
|
|
LIGHTGRAY
|
|
);
|
|
|
|
DrawText(
|
|
"E: recoger arma",
|
|
375,
|
|
685,
|
|
15,
|
|
LIGHTGRAY
|
|
);
|
|
|
|
// ====================================================
|
|
// RECARGANDO
|
|
// ====================================================
|
|
|
|
if (
|
|
jugador.viva &&
|
|
jugador.recargando
|
|
)
|
|
{
|
|
DrawText(
|
|
"RECARGANDO...",
|
|
PANTALLA_ANCHO / 2 - 90,
|
|
PANTALLA_ALTO - 55,
|
|
22,
|
|
YELLOW
|
|
);
|
|
}
|
|
|
|
// ====================================================
|
|
// MUERTO
|
|
// ====================================================
|
|
|
|
if (!jugador.viva)
|
|
{
|
|
DrawRectangle(
|
|
0,
|
|
0,
|
|
PANTALLA_ANCHO,
|
|
PANTALLA_ALTO,
|
|
Color{
|
|
0,
|
|
0,
|
|
0,
|
|
180
|
|
}
|
|
);
|
|
|
|
DrawText(
|
|
"HAS MUERTO",
|
|
PANTALLA_ANCHO / 2 - 145,
|
|
PANTALLA_ALTO / 2 - 30,
|
|
45,
|
|
RED
|
|
);
|
|
}
|
|
|
|
// ====================================================
|
|
// MARCADOR
|
|
// ====================================================
|
|
|
|
int azulesVivos = 0;
|
|
int rojosVivos = 0;
|
|
|
|
for (const auto& entidad : entidades)
|
|
{
|
|
if (!entidad.viva)
|
|
continue;
|
|
|
|
if (entidad.equipo == EQUIPO_AZUL)
|
|
azulesVivos++;
|
|
else
|
|
rojosVivos++;
|
|
}
|
|
|
|
DrawText(
|
|
TextFormat(
|
|
"AZUL %d - ROJO %d",
|
|
azulesVivos,
|
|
rojosVivos
|
|
),
|
|
1000,
|
|
685,
|
|
16,
|
|
WHITE
|
|
);
|
|
|
|
EndDrawing();
|
|
}
|
|
|
|
CloseWindow();
|
|
|
|
return 0;
|
|
} |