Files
Attacks-for-Bombs-1/source/A4B1/enemy.cpp
T
2026-09-27 00:12:17 -03:00

416 lines
6.0 KiB
C++

#include "raylib.h"
#include <cmath>
extern Vector3 playerPosition;
extern bool IsSolidAt(Vector3 position, float radius);
const int NPC_COUNT = 12;
Vector3 enemyPosition[NPC_COUNT] =
{
{ -72.0f, 1.0f, -72.0f },
{ 72.0f, 1.0f, -72.0f },
{ -72.0f, 1.0f, 72.0f },
{ 72.0f, 1.0f, 72.0f },
{ -48.0f, 1.0f, -36.0f },
{ 48.0f, 1.0f, -36.0f },
{ -48.0f, 1.0f, 36.0f },
{ 48.0f, 1.0f, 36.0f },
{ -28.0f, 1.0f, -68.0f },
{ 28.0f, 1.0f, -68.0f },
{ -28.0f, 1.0f, 68.0f },
{ 28.0f, 1.0f, 68.0f }
};
float enemyWalkTime[NPC_COUNT] = {};
float enemyStunTime[NPC_COUNT] = {};
float enemySpin[NPC_COUNT] = {};
const float enemySpeed = 2.4f;
const float enemyStunDuration = 2.5f;
bool enemyMoving[NPC_COUNT] = {};
void MoveEnemyWithCollision(
int index,
float moveX,
float moveZ
)
{
Vector3 nextX = enemyPosition[index];
nextX.x += moveX;
if (!IsSolidAt(nextX, 0.45f))
enemyPosition[index].x = nextX.x;
Vector3 nextZ = enemyPosition[index];
nextZ.z += moveZ;
if (!IsSolidAt(nextZ, 0.45f))
enemyPosition[index].z = nextZ.z;
}
void UpdateEnemy(float deltaTime)
{
for (int i = 0; i < NPC_COUNT; i++)
{
float dx =
playerPosition.x -
enemyPosition[i].x;
float dz =
playerPosition.z -
enemyPosition[i].z;
float distance =
std::sqrt(
dx * dx +
dz * dz
);
// =========================================
// MAREADO
// =========================================
if (enemyStunTime[i] > 0.0f)
{
enemyStunTime[i] -= deltaTime;
enemySpin[i] += deltaTime * 18.0f;
enemyMoving[i] = false;
if (enemyStunTime[i] < 0.0f)
enemyStunTime[i] = 0.0f;
continue;
}
// =========================================
// EMPUJAR JUGADOR
// =========================================
if (distance > 0.001f &&
distance < 1.5f)
{
float pushX =
(dx / distance) *
10.0f *
deltaTime;
float pushZ =
(dz / distance) *
10.0f *
deltaTime;
Vector3 next = playerPosition;
next.x += pushX;
next.z += pushZ;
if (!IsSolidAt(next, 0.45f))
playerPosition = next;
}
// =========================================
// SEGUIR JUGADOR
// =========================================
if (distance > 1.8f)
{
dx /= distance;
dz /= distance;
MoveEnemyWithCollision(
i,
dx * enemySpeed * deltaTime,
dz * enemySpeed * deltaTime
);
enemyWalkTime[i] +=
deltaTime * 9.0f;
enemyMoving[i] = true;
}
else
{
enemyMoving[i] = false;
enemyWalkTime[i] = 0.0f;
}
}
// =========================================
// CLICK DERECHO
// =========================================
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT))
{
for (int i = 0; i < NPC_COUNT; i++)
{
float dx =
enemyPosition[i].x -
playerPosition.x;
float dz =
enemyPosition[i].z -
playerPosition.z;
float distance =
std::sqrt(
dx * dx +
dz * dz
);
if (distance < 4.0f &&
distance > 0.001f)
{
dx /= distance;
dz /= distance;
MoveEnemyWithCollision(
i,
dx * 3.5f,
dz * 3.5f
);
enemyStunTime[i] =
enemyStunDuration;
enemySpin[i] = 0.0f;
enemyWalkTime[i] = 0.0f;
}
}
}
}
void TeleportEnemyNearPlayer(
int index,
float yaw
)
{
if (index < 0 ||
index >= NPC_COUNT)
return;
// =========================================
// CONSERVAR LA DISTANCIA ACTUAL
// =========================================
float dx =
enemyPosition[index].x -
playerPosition.x;
float dz =
enemyPosition[index].z -
playerPosition.z;
float oldDistance =
std::sqrt(
dx * dx +
dz * dz
);
if (oldDistance < 3.0f)
oldDistance = 3.0f;
// =========================================
// BUSCAR OTRA DIRECCIÓN
// =========================================
float baseAngle =
std::atan2(
dz,
dx
);
for (int attempt = 0; attempt < 16; attempt++)
{
float angle =
baseAngle +
PI +
attempt * 0.4f;
Vector3 newPosition =
{
playerPosition.x +
std::cos(angle) * oldDistance,
1.0f,
playerPosition.z +
std::sin(angle) * oldDistance
};
if (!IsSolidAt(newPosition, 0.45f))
{
enemyPosition[index] =
newPosition;
enemyStunTime[index] = 0.0f;
enemySpin[index] = 0.0f;
enemyWalkTime[index] = 0.0f;
return;
}
}
}
int CheckEnemyHit(Vector3 bulletPosition)
{
for (int i = 0; i < NPC_COUNT; i++)
{
float hitX =
bulletPosition.x -
enemyPosition[i].x;
float hitY =
bulletPosition.y -
1.2f;
float hitZ =
bulletPosition.z -
enemyPosition[i].z;
float distance =
std::sqrt(
hitX * hitX +
hitY * hitY +
hitZ * hitZ
);
if (distance < 0.8f)
return i;
}
return -1;
}
void DrawEnemy()
{
for (int i = 0; i < NPC_COUNT; i++)
{
float legMove = 0.0f;
float armMove = 0.0f;
if (enemyMoving[i])
{
legMove =
std::sin(enemyWalkTime[i]) *
0.18f;
armMove =
std::sin(enemyWalkTime[i]) *
0.25f;
}
float spinX = 0.0f;
float spinZ = 0.0f;
if (enemyStunTime[i] > 0.0f)
{
spinX =
std::sin(enemySpin[i]) *
0.25f;
spinZ =
std::cos(enemySpin[i]) *
0.25f;
}
DrawCube(
{
enemyPosition[i].x -
0.22f +
spinX,
0.45f,
enemyPosition[i].z +
legMove +
spinZ
},
0.25f,
0.9f,
0.25f,
DARKGRAY
);
DrawCube(
{
enemyPosition[i].x +
0.22f -
spinX,
0.45f,
enemyPosition[i].z -
legMove -
spinZ
},
0.25f,
0.9f,
0.25f,
DARKGRAY
);
DrawCube(
{
enemyPosition[i].x,
1.25f,
enemyPosition[i].z
},
0.8f,
1.0f,
0.45f,
BLUE
);
DrawSphere(
{
enemyPosition[i].x + spinX,
2.05f,
enemyPosition[i].z + spinZ
},
0.38f,
BEIGE
);
DrawCube(
{
enemyPosition[i].x -
0.55f +
spinX,
1.25f + armMove,
enemyPosition[i].z +
spinZ
},
0.18f,
0.75f,
0.18f,
BLUE
);
DrawCube(
{
enemyPosition[i].x +
0.55f -
spinX,
1.25f - armMove,
enemyPosition[i].z -
spinZ
},
0.18f,
0.75f,
0.18f,
BLUE
);
}
}