Enemy swarm movement
This commit is contained in:
@@ -256,6 +256,110 @@ void entityMoveToTarget(ecs_iter_t *it) {
|
||||
}
|
||||
}
|
||||
|
||||
void entityMoveSwarm(ecs_iter_t *it) {
|
||||
Game *game = ecs_singleton_get_mut(ECS, Game);
|
||||
Position *pos = ecs_field(it, Position, 1);
|
||||
Velocity *vel = ecs_field(it, Velocity, 2);
|
||||
HitBox *hb = ecs_field(it, HitBox, 3);
|
||||
Swarm *swarm = ecs_field(it, Swarm, 4);
|
||||
Owner *owner = ecs_field(it, Owner, 5);
|
||||
Steering *steer = ecs_field(it, Steering, 6);
|
||||
|
||||
for (i32 i = 0; i < it->count; i++) {
|
||||
|
||||
// Vector2 align = Vector2Zero(); // Alignment (match velocity)
|
||||
Vector2 avoid = Vector2Zero(); // Separation
|
||||
Vector2 target = Vector2Zero();
|
||||
Vector2 cohesion = Vector2Zero(); // Cohesion (move towards center)
|
||||
|
||||
const f32 FRIEND_RADIUS = 22.0f;
|
||||
const f32 ENEMY_RADIUS = 52.0f;
|
||||
|
||||
const Vector2 center = entityGetCenter(pos[i], hb[i]);
|
||||
|
||||
const f32 RANGE = BZ_MAX(FRIEND_RADIUS, ENEMY_RADIUS);
|
||||
BzSpatialGridIter spatialIt = bzSpatialGridIter(game->entityGrid,
|
||||
center.x - RANGE, center.y - RANGE,
|
||||
RANGE * 2.0f, RANGE * 2.0f);
|
||||
|
||||
i32 numFriends = 0;
|
||||
while (bzSpatialGridQueryNext(&spatialIt)) {
|
||||
ecs_entity_t other = *(ecs_entity_t *) spatialIt.data;
|
||||
if (!ecs_has(ECS, other, Owner))
|
||||
continue;
|
||||
Owner otherOwner = *ecs_get(ECS, other, Owner);
|
||||
bool isFriend = owner[i].player == otherOwner.player;
|
||||
|
||||
if (!ecs_has(ECS, other, Position) || !ecs_has(ECS, other, HitBox))
|
||||
continue;
|
||||
Position otherPos = *ecs_get(ECS, other, Position);
|
||||
Rectangle otherHB = *ecs_get(ECS, other, HitBox);;
|
||||
Vector2 otherCenter = entityGetCenter(otherPos, otherHB);
|
||||
f32 dst = Vector2Distance(center, otherCenter);
|
||||
const f32 MIN_AVOID_DST = 18.0f;
|
||||
const f32 MIN_ENEMY_DST = ENEMY_RADIUS;
|
||||
if (isFriend) {
|
||||
if (dst < MIN_AVOID_DST) {
|
||||
Vector2 dif = Vector2Subtract(center, otherCenter);
|
||||
dif = Vector2Scale(Vector2Normalize(dif), MIN_AVOID_DST - dst);
|
||||
avoid = Vector2Add(avoid, dif);
|
||||
}
|
||||
Vector2Add(cohesion, otherCenter);
|
||||
numFriends++;
|
||||
} else {
|
||||
if (dst < MIN_ENEMY_DST) {
|
||||
//DrawCircleV(otherCenter, 2.0f, RED);
|
||||
Vector2 dif = Vector2Subtract(otherCenter, center);
|
||||
dif = Vector2Scale(Vector2Normalize(dif), MIN_ENEMY_DST - dst);
|
||||
target = Vector2Add(target, dif);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numFriends > 0) {
|
||||
cohesion = Vector2Divide(cohesion, (Vector2) { numFriends, numFriends });
|
||||
cohesion = Vector2Subtract(cohesion, center);
|
||||
}
|
||||
|
||||
|
||||
//bzLogInfo("%d %d", numFriends, numEnemies);
|
||||
|
||||
const f32 noiseRange = 10.0f;
|
||||
Vector2 noise = {
|
||||
randFloatRange(-noiseRange, noiseRange),
|
||||
randFloatRange(-noiseRange, noiseRange)
|
||||
};
|
||||
Vector2 followWaypoint = Vector2Zero();
|
||||
if (swarm[i].currWaypoint < game->swamNumWaypoints) {
|
||||
Vector2 waypoint = game->swarmWaypoints[swarm[i].currWaypoint];
|
||||
Vector2 waypointDir = Vector2Subtract(waypoint, center);
|
||||
followWaypoint = waypointDir;
|
||||
|
||||
f32 dst = Vector2Distance(center, waypoint);
|
||||
const f32 WAYPOINT_THRESHOLD = 54.0f;
|
||||
if (dst < WAYPOINT_THRESHOLD) {
|
||||
swarm[i].currWaypoint++;
|
||||
}
|
||||
}
|
||||
const f32 AVOID_FACTOR = 1.0f;
|
||||
const f32 TARGET_FACTOR = 2.2f;
|
||||
const f32 COHESION_FACTOR = 0.10f;
|
||||
const f32 WAYPOINT_FACTOR = 0.45f;
|
||||
const f32 NOISE_FACTOR = 0.2f;
|
||||
Vector2 move = Vector2Zero();
|
||||
move = Vector2Add(move, Vector2Scale(avoid, AVOID_FACTOR));
|
||||
move = Vector2Add(move, Vector2Scale(target, TARGET_FACTOR));
|
||||
//move = Vector2Add(move, Vector2Scale(cohesion, COHESION_FACTOR));
|
||||
move = Vector2Add(move, Vector2Scale(followWaypoint, WAYPOINT_FACTOR));
|
||||
move = Vector2Add(move, Vector2Scale(noise, NOISE_FACTOR));
|
||||
|
||||
//bzLogInfo("%.2f %.2f", move.x, move.y);
|
||||
//DrawLineV(center, Vector2Add(center, Vector2Scale(Vector2Normalize(avoid), 100)), ORANGE);
|
||||
|
||||
steer[i] = move;
|
||||
}
|
||||
}
|
||||
|
||||
void entityFollowPath(ecs_iter_t *it) {
|
||||
const Game *game = ecs_singleton_get(ECS, Game);
|
||||
|
||||
@@ -307,7 +411,7 @@ void updateBuildingRecruitment(ecs_iter_t *it) {
|
||||
slot->elapsed = 0;
|
||||
PlayerResources *playerRes = &game->playerResources[player];
|
||||
playerRes->pop--;
|
||||
entityRecruit(slot->entityType, placePos, player, game);
|
||||
entityCreate(slot->entityType, placePos, player, game);
|
||||
slot->numRecruiting--;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user