Polish up AI

This commit is contained in:
2024-02-13 19:01:51 +01:00
parent 417cf081d7
commit dcd4d1940d
6 changed files with 40 additions and 22 deletions

View File

@@ -15,6 +15,8 @@ float shortestArc(float a, float b) {
}
BzBTStatus aiMoveTo(AIBlackboard *data, f32 dt) {
if (!data->shouldMoveTo)
return BZ_BT_FAIL;
Game *game = ecs_singleton_get_mut(ECS, Game);
const Vector2 pos = *ecs_get(ECS, data->entity, Position);
const HitBox hb = *ecs_get(ECS, data->entity, HitBox);
@@ -23,12 +25,15 @@ BzBTStatus aiMoveTo(AIBlackboard *data, f32 dt) {
f32 dst = Vector2Distance(center, target);
if (dst < data->proximity) {
ecs_remove(ECS, data->entity, Path);
data->shouldMoveTo = false;
return BZ_BT_SUCCESS;
}
if (!ecs_has(ECS, data->entity, Path)) {
bool pathfindSuccessful = entitySetPath(data->entity, target, game);
if (!pathfindSuccessful)
if (!pathfindSuccessful) {
data->shouldMoveTo = false;
return BZ_BT_FAIL;
}
}
if (ecs_has(ECS, data->entity, Orientation)) {
Orientation *orientation = ecs_get_mut(ECS, data->entity, Orientation);
@@ -47,18 +52,21 @@ BzBTStatus aiResetElapsed(AIBlackboard *data, f32 dt) {
return BZ_BT_SUCCESS;
}
#define ENEMY_NEARBY_DST 26.0f
#define ENEMY_NEARBY_DST 30.0f
#define ENEMY_CHASE_THRESH 25.0f
#define ENEMY_EVADE_THRESH 30.0f
BzBTStatus aiIsEnemyNearby(AIBlackboard *data, f32 dt) {
if (data->seenEnemy && ecs_is_alive(ECS, data->seenEnemy)) {
Position enemyPos = *ecs_get(ECS, data->seenEnemy, Position);
Position pos = *ecs_get(ECS, data->entity, Position);
if (Vector2Distance(enemyPos, pos) > ENEMY_NEARBY_DST)
if (Vector2Distance(enemyPos, pos) < ENEMY_NEARBY_DST)
return BZ_BT_SUCCESS;
data->seenEnemy = 0;
}
const f32 range = 20.0f;
const f32 range = 30.0f;
Position pos = *ecs_get(ECS, data->entity, Position);
HitBox hb = *ecs_get(ECS, data->entity, HitBox);
Vector2 center = entityGetCenter(pos, hb);
@@ -109,6 +117,10 @@ BzBTStatus aiAttackEnemy(AIBlackboard *data, f32 dt) {
Position enemyPos = *ecs_get(ECS, data->seenEnemy, Position);
Position pos = *ecs_get(ECS, data->entity, Position);
f32 dst = Vector2Distance(pos, enemyPos);
if (dst > ENEMY_CHASE_THRESH)
return BZ_BT_FAIL;
Vector2 dif = Vector2Subtract(enemyPos, pos);
// Overload steering
Steering *steering = ecs_get_mut(ECS, data->entity, Steering);
@@ -124,6 +136,10 @@ BzBTStatus aiEvadeEnemy(AIBlackboard *data, f32 dt) {
Position enemyPos = *ecs_get(ECS, data->seenEnemy, Position);
Position pos = *ecs_get(ECS, data->entity, Position);
f32 dst = Vector2Distance(pos, enemyPos);
if (dst > ENEMY_EVADE_THRESH)
return BZ_BT_FAIL;
Vector2 dif = Vector2Subtract(pos, enemyPos);
// Overload steering
Steering *steering = ecs_get_mut(ECS, data->entity, Steering);
@@ -141,6 +157,7 @@ BzBTStatus aiFindNextHarvestable(AIBlackboard *data, f32 dt) {
if (harvestable.harvestCount < harvestable.harvestLimit) {
// Target still alive, no need to find next harvestable
data->moveToPos = data->as.worker.harvestPos;
data->shouldMoveTo = true;
return BZ_BT_SUCCESS;
}
}
@@ -191,6 +208,7 @@ BzBTStatus aiFindNextHarvestable(AIBlackboard *data, f32 dt) {
data->as.worker.harvestTarget = closest;
data->as.worker.harvestPos = closestPos;
data->moveToPos = closestPos;
data->shouldMoveTo = true;
return BZ_BT_SUCCESS;
}
@@ -233,6 +251,7 @@ BzBTStatus aiFindNearestStorage(AIBlackboard *data, f32 dt) {
data->as.worker.depositTarget = closest;
data->moveToPos = getPositionNearBuilding(closest, pos);
data->shouldMoveTo = true;
return BZ_BT_SUCCESS;
}

View File

@@ -10,6 +10,7 @@ typedef struct AIBlackboard {
ecs_entity_t entity;
ecs_entity_t seenEnemy;
bool shouldMoveTo;
Vector2 moveToPos;
union {

View File

@@ -90,9 +90,7 @@ ecs_entity_t entityCreateSoldier(const Position position, Player player, Game *g
unit.maxDamage = 10.0f;
unit.attackCooldown = 1.0f;
ecs_set_ptr(ECS, e, Unit, &unit);
setAIBehaviour(e, game->BTs.unit, &(AIBlackboard) {
.moveToPos = position,
});
setAIBehaviour(e, game->BTs.unit, NULL);
return e;
}
ecs_entity_t entityCreateWarrior(const Position position, Player player, Game *game) {
@@ -107,9 +105,7 @@ ecs_entity_t entityCreateWarrior(const Position position, Player player, Game *g
unit.maxDamage = 22.0f;
unit.attackCooldown = 1.8f;
ecs_set_ptr(ECS, e, Unit, &unit);
setAIBehaviour(e, game->BTs.unit, &(AIBlackboard) {
.moveToPos = position,
});
setAIBehaviour(e, game->BTs.unit, NULL);
return e;
}
@@ -128,9 +124,7 @@ ecs_entity_t entityCreateWorker(const Position position, Player player, Game *ga
.lastChanged = -1000.0f
});
setAIBehaviour(e, game->BTs.unit, &(AIBlackboard) {
.moveToPos = position,
});
setAIBehaviour(e, game->BTs.unitEvasive, NULL);
return e;
}

View File

@@ -274,6 +274,8 @@ bool init(void *userData) {
game->BTs.unit = root;
BzBTNode *sel = bzBTCompSelector(nodePool, root);
node = bzBTAction(nodePool, sel, (BzBTActionFn) aiMoveTo);
bzBTNodeSetName(node, "moveTo");
BzBTNode *attackSeq = bzBTCompSequence(nodePool, sel);
{
node = bzBTAction(nodePool, attackSeq, (BzBTActionFn) aiIsEnemyNearby);
@@ -282,9 +284,7 @@ bool init(void *userData) {
node = bzBTAction(nodePool, attackSeq, (BzBTActionFn) aiAttackEnemy);
bzBTNodeSetName(node, "attackEnemy");
}
node = bzBTAction(nodePool, sel, (BzBTActionFn) aiMoveTo);
bzBTNodeSetName(node, "moveTo");
bzBTDecorDelay(nodePool, sel, 2.0f);
bzBTDecorDelay(nodePool, sel, 0.2f);
}
// Unit (evasive)
{
@@ -294,6 +294,9 @@ bool init(void *userData) {
game->BTs.unitEvasive = root;
BzBTNode *sel = bzBTCompSelector(nodePool, root);
node = bzBTAction(nodePool, sel, (BzBTActionFn) aiMoveTo);
bzBTNodeSetName(node, "moveTo");
//bzBTDecorDelay(nodePool, sel, 0.2f);
BzBTNode *evadeSeq = bzBTCompSequence(nodePool, sel);
{
node = bzBTAction(nodePool, evadeSeq, (BzBTActionFn) aiIsEnemyNearby);
@@ -302,9 +305,6 @@ bool init(void *userData) {
node = bzBTAction(nodePool, evadeSeq, (BzBTActionFn) aiEvadeEnemy);
bzBTNodeSetName(node, "evadeEnemy");
}
node = bzBTAction(nodePool, sel, (BzBTActionFn) aiMoveTo);
bzBTNodeSetName(node, "moveTo");
bzBTDecorDelay(nodePool, sel, 2.0f);
}
// evade
BzBTNode *evade = NULL;

View File

@@ -263,8 +263,12 @@ void inputUnitAction(Game *game, InputState *input) {
for (i32 i = 0; i < unitIdx; i++) {
ecs_entity_t entity = entities[i].entity;
setAIBehaviour(entity, game->BTs.unit, &(AIBlackboard) {
BzBTNode *BT = game->BTs.unit;
if (ecs_has(ECS, entity, Worker))
BT = game->BTs.unitEvasive;
setAIBehaviour(entity, BT, &(AIBlackboard) {
.moveToPos = positions[i],
.shouldMoveTo = true,
.proximity = 1.0f,
});
}

View File

@@ -406,11 +406,11 @@ void drawMainMenuUI(Game *game, f32 dt) {
if (uiMainMenuButton("Play", true)) {
setScreen(game, SCREEN_GAME);
unloadMap(game);
loadMap(game, "assets/maps/tree_test.tmj", false);
//loadMap(game, "assets/maps/tree_test.tmj", false);
//loadMap(game, "assets/maps/entity_test.tmj", false);
//loadMap(game, "assets/maps/worker_test.tmj", false);
//loadMap(game, "assets/maps/battle_test.tmj", false);
//loadMap(game, "assets/maps/map_01.tmj", false);
loadMap(game, "assets/maps/map_01.tmj", false);
}
if (uiMainMenuButton("Settings", true)) {
setScreen(game, SCREEN_SETTINGS);