Skip to content

Commit f06c274

Browse files
Enhance actor and enemy systems with spawner logic
Added a cachedActors list to ActorBehaviour for unified entity tracking. Refactored EnemyController to target both player and enemy entities, introduced wander behavior, and linked enemies to their spawner. Implemented EnemySpawner health bar, attack, and death coroutines, and improved attack handling for both player and spawner. Added random_float utility and suppressed warnings in build scripts.
1 parent 1c36f6b commit f06c274

File tree

8 files changed

+204
-21
lines changed

8 files changed

+204
-21
lines changed

ext/glad/Makefile

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,22 +47,22 @@ endef
4747
ifeq ($(config),debug)
4848
OBJDIR = build/Debug
4949
DEFINES += -D_CRT_SECURE_NO_WARNINGS -DDEBUG
50-
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -m64 -g -std=c11 -Wall -fcompare-debug-second
51-
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -m64 -g -Wall -fcompare-debug-second
50+
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -m64 -g -std=c11 -Wno-warnings -Wall -fcompare-debug-second
51+
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -m64 -g -Wno-warnings -Wall -fcompare-debug-second
5252
ALL_LDFLAGS += $(LDFLAGS) -L/usr/lib64 -m64
5353

5454
else ifeq ($(config),debug_(renderdoc))
5555
OBJDIR = build/Debug (RenderDoc)
5656
DEFINES += -D_CRT_SECURE_NO_WARNINGS -DDEBUG
57-
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -m64 -g -std=c11 -Wall -fcompare-debug-second
58-
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -m64 -g -Wall -fcompare-debug-second
57+
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -m64 -g -std=c11 -Wno-warnings -Wall -fcompare-debug-second
58+
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -m64 -g -Wno-warnings -Wall -fcompare-debug-second
5959
ALL_LDFLAGS += $(LDFLAGS) -L/usr/lib64 -m64
6060

6161
else ifeq ($(config),release)
6262
OBJDIR = build/Release
6363
DEFINES += -D_CRT_SECURE_NO_WARNINGS -DNDEBUG
64-
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -m64 -O2 -std=c11 -Wall -fcompare-debug-second
65-
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -m64 -O2 -Wall -fcompare-debug-second
64+
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -m64 -O2 -std=c11 -Wno-warnings -Wall -fcompare-debug-second
65+
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -m64 -O2 -Wno-warnings -Wall -fcompare-debug-second
6666
ALL_LDFLAGS += $(LDFLAGS) -L/usr/lib64 -m64 -s
6767

6868
endif

include/borealis/util/random.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ namespace brl
88
inline int random(int min, int max) {
99
return min + (std::rand() % (max - min + 1));
1010
}
11+
12+
inline float random_float(float min, float max) {
13+
float scale = static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX);
14+
return min + scale * (max - min);
15+
}
16+
1117
} // namespace brl
1218

1319

premake5.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ workspace "borealis"
1515
filter "system:windows"
1616
systemversion "latest"
1717
defines { "_CRT_SECURE_NO_WARNINGS" }
18+
disablewarnings { "warnings" }
1819

1920

2021
project "borealis"

test/include/actor.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ struct ActorBehaviour : brl::EcsEntity
1212
void update() override;
1313
virtual void handleAttack(glm::vec3 dir, float power);
1414

15+
static std::vector<ActorBehaviour*> cachedActors;
16+
17+
1518
protected:
1619
float health = 1.f;
1720
bool isAlive = true;

test/include/enemy.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@
77
#include "borealis/gfx/texture.hpp"
88
#include "actor.h"
99

10-
enum EnemyTeam
10+
enum EnemyTeam : int
1111
{
1212
Red = 0,
1313
Blue,
1414
Yellow,
1515
Black
1616
};
1717

18+
struct EnemySpawner;
19+
1820
struct EnemyController : ActorBehaviour
1921
{
2022

@@ -29,14 +31,18 @@ struct EnemyController : ActorBehaviour
2931
EnemyTeam Team = Red;
3032

3133
private:
34+
friend EnemySpawner;
3235
brl::GfxMaterial* material = nullptr;
3336
brl::GfxMeshRenderer* renderer;
3437

3538
HealthBarBehavior* healthBar;
3639

40+
EnemySpawner* spawner;
41+
3742
static brl::GfxTexture2dArray *idleSprites, *walkSprites, *attackSprites, *guardSprites;
3843

3944
glm::vec2 velocity = glm::vec2{0};
45+
glm::vec3 wanderPosition;
4046
float attackDelay = 3.0f;
4147
float attackTimer = 0;
4248

@@ -56,9 +62,24 @@ struct EnemySpawner : ActorBehaviour
5662
void start() override;
5763
void update() override;
5864

65+
void onDeath() override;
66+
5967
float radius = 3.0f;
6068
int count = 3;
6169
EnemyTeam team = Red;
70+
71+
72+
HealthBarBehavior* healthBar;
73+
74+
std::vector<EnemyController*>enemies;
75+
std::vector<brl::GfxMaterial*> materials;
76+
brl::GfxMeshRenderer* renderer;
77+
78+
void handleAttack(glm::vec3 dir, float power) override;
79+
private:
80+
brl::UtilCoroutine AttackCoroutine(glm::vec3 dir, float power);
81+
brl::UtilCoroutine DeathCoroutine();
82+
6283
};
6384

6485
#endif // ENEMY_H

test/src/actor.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
#include "map.h"
44
#include "borealis/gfx/camera.hpp"
55

6+
std::vector<ActorBehaviour*> ActorBehaviour::cachedActors;
7+
8+
69
ActorBehaviour::ActorBehaviour()
710
{
8-
11+
cachedActors.push_back(this);
912
}
1013

1114
void ActorBehaviour::update()

test/src/enemy.cpp

Lines changed: 155 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -115,33 +115,51 @@ void EnemyController::update()
115115

116116
auto entityPosition = glm::vec3(0);
117117
float entityDistance = 0;
118-
PlayerEntity* playerEntity = nullptr;
118+
ActorBehaviour* targetEntity = nullptr;
119119

120-
for (auto cachedEntity : PlayerEntity::cachedEntities)
120+
for (auto cachedEntity : EnemyController::cachedEnemies)
121121
{
122122
glm::vec3 pos = cachedEntity->position();
123123

124124
float distance = glm::distance(pos, position());
125125

126126
if (distance < 7.5f && cachedEntity->Team != Team)
127127
{
128-
playerEntity = cachedEntity;
128+
targetEntity = cachedEntity;
129129
entityPosition = pos;
130130
entityDistance = distance;
131131
}
132132

133133
}
134134

135-
velocity = glm::vec2(0);
135+
if (!targetEntity) {
136+
for (auto cachedEntity : PlayerEntity::cachedEntities)
137+
{
138+
glm::vec3 pos = cachedEntity->position();
139+
140+
float distance = glm::distance(pos, position());
141+
142+
if (distance < 7.5f && cachedEntity->Team != Team)
143+
{
144+
targetEntity = cachedEntity;
145+
entityPosition = pos;
146+
entityDistance = distance;
147+
}
148+
149+
}
150+
}
151+
152+
153+
136154
bool attack = false;
137155
isGuarding = false;
138156

139157
attackTimer += deltaTime;
140158
attackDelay = 5.0f;
141159

142-
if (playerEntity && length(velocity) <= 0.1f)
160+
if (targetEntity)
143161
{
144-
162+
wanderPosition = position();
145163
if (entityDistance > 2.5f)
146164
{
147165
glm::vec3 diff = entityPosition - position();
@@ -152,13 +170,14 @@ void EnemyController::update()
152170
}
153171
else if (entityDistance <= 2.5f)
154172
{
173+
velocity = glm::vec2(0);
155174
if (attackTimer >= attackDelay)
156175
{
157176
startAttackDistance = entityDistance;
158177
glm::vec3 diff = entityPosition - position();
159178
diff = normalize(diff);
160-
float power = playerEntity->isGuarding ? 5.0f : 12.5f;
161-
playerEntity->handleAttack(diff, power);
179+
float power = 12.5f;
180+
targetEntity->handleAttack(diff, power);
162181
attack = true;
163182
attackTimer = 0.f;
164183
}
@@ -167,6 +186,36 @@ void EnemyController::update()
167186
isGuarding = true;
168187
}
169188
}
189+
} else {
190+
float spawnerDistance = glm::distance(position(), spawner->position());
191+
192+
if (spawnerDistance > 5.f)
193+
{
194+
glm::vec3 diff = spawner->position() - position();
195+
diff = normalize(diff);
196+
197+
velocity.x = diff.x;
198+
velocity.y = diff.z;
199+
wanderPosition = position();
200+
} else {
201+
if (glm::distance(position(),wanderPosition) < 1.0f) {
202+
glm::vec3 pos = spawner->position();
203+
float angle = brl::random(0,360);
204+
angle = glm::radians(angle);
205+
206+
float radius = brl::random_float(2.5f,5);
207+
208+
pos.x += radius * glm::cos(angle);
209+
pos.z += radius * glm::sin(angle);
210+
211+
wanderPosition = pos;
212+
}
213+
glm::vec3 diff = wanderPosition - position();
214+
diff = normalize(diff);
215+
216+
velocity.x = diff.x;
217+
velocity.y = diff.z;
218+
}
170219
}
171220

172221
float horizontal = velocity.x;
@@ -237,6 +286,8 @@ void EnemyController::onDeath()
237286

238287
brl::UtilCoroutine EnemyController::AttackCoroutine(glm::vec3 dir, float power)
239288
{
289+
if (isGuarding)
290+
power *= 0.5f;
240291
float start = glfwGetTime();
241292

242293
float diff = 0;
@@ -319,7 +370,7 @@ EnemySpawner::EnemySpawner(EnemyTeam t)
319370

320371
const auto& towerEntity = tower->createEntity();
321372

322-
auto renderer = towerEntity->getEntityInChildren<brl::GfxMeshRenderer>();
373+
renderer = towerEntity->getEntityInChildren<brl::GfxMeshRenderer>();
323374
for (int i = 0; i < renderer->materials.size(); ++i)
324375
{
325376
auto material = new brl::GfxMaterial(*renderer->materials[i]);
@@ -328,18 +379,40 @@ EnemySpawner::EnemySpawner(EnemyTeam t)
328379

329380
renderer->materials[i] = material;
330381
}
382+
materials = renderer->materials;
331383

332384
towerEntity->setEulerAngles({0, 180, 0});
333385
towerEntity->localScale = glm::vec3(1.0f);
334386

335387
towerEntity->setParent(this);
336388

389+
healthBar = new HealthBarBehavior;
390+
healthBar->localPosition = {0, 5.f, 0};
391+
switch (team)
392+
{
393+
394+
case Red:
395+
healthBar->color = glm::vec3(212, 28, 64);
396+
break;
397+
case Blue:
398+
healthBar->color = glm::vec3(66, 93, 245);
399+
break;
400+
case Yellow:
401+
healthBar->color = glm::vec3(245, 188, 66);
402+
break;
403+
case Black:
404+
healthBar->color = glm::vec3(28, 36, 48);
405+
break;
406+
}
407+
408+
healthBar->setParent(this);
409+
337410
}
338411

339412
void EnemySpawner::start()
340413
{
341414
ActorBehaviour::start();
342-
415+
health = 1;
343416

344417
auto pos = position();
345418
for (int i = 0; i < count; ++i)
@@ -355,17 +428,88 @@ void EnemySpawner::start()
355428
auto enemy = new EnemyController(team);
356429
enemy->localPosition = startPosition;
357430
enemy->Team = team;
431+
enemy->spawner = this;
432+
433+
enemies.push_back(enemy);
358434
}
359435
}
360436

361437

362438
void EnemySpawner::update()
363439
{
364440
ActorBehaviour::update();
365-
health = 1;
441+
float deltaTime = brl::GfxEngine::instance->getDeltaTime();
442+
443+
healthBar->health = glm::mix(healthBar->health, health, deltaTime * 15.f);
444+
445+
if (!isAlive)
446+
return;
447+
366448

367449
brl_debug::drawMesh(brl::GfxMesh::GetPrimitive(brl::CIRCLE)->GetSubMesh(0)->buffer,
368450
glm::translate(position())*glm::scale(scale()*radius));
369451

370452
brl_debug::drawLine(position(), glm::vec3(0,5,0));
453+
454+
if (enemies.size() > 0) {
455+
456+
}
457+
}
458+
459+
void EnemySpawner::onDeath() {
460+
ActorBehaviour::onDeath();
461+
462+
brl::GfxEngine::instance->active_coroutines.push_back(DeathCoroutine());
463+
464+
}
465+
466+
void EnemySpawner::handleAttack(glm::vec3 dir, float power) {
467+
ActorBehaviour::handleAttack(dir, power);
468+
brl::GfxEngine::instance->active_coroutines.push_back(AttackCoroutine(dir, power));
469+
470+
}
471+
472+
brl::UtilCoroutine EnemySpawner::AttackCoroutine(glm::vec3 dir, float power)
473+
{
474+
float start = glfwGetTime();
475+
476+
float diff = 0;
477+
478+
while (diff * 10 <= 2.0f)
479+
{
480+
diff = glfwGetTime() - start;
481+
co_yield brl::GfxEngine::instance->getDeltaTime();
482+
}
483+
484+
for (const auto & material : materials)
485+
material->setFloat("damageTime", glfwGetTime());
486+
487+
while (diff * 10.0f > 2.0f && diff * 10.0f < 4.0f)
488+
{
489+
localPosition += (dir * power) * brl::GfxEngine::instance->getDeltaTime();
490+
co_yield brl::GfxEngine::instance->getDeltaTime();
491+
492+
diff = glfwGetTime() - start;
493+
}
494+
495+
health -= power /= 50.0f;
496+
}
497+
498+
brl::UtilCoroutine EnemySpawner::DeathCoroutine() {
499+
glm::vec3 startScale = renderer->localScale;
500+
glm::vec3 startPos = renderer->localPosition;
501+
502+
float timeToReach = 0.5f;
503+
float t = 0;
504+
while (t < timeToReach)
505+
{
506+
renderer->localScale = mix(startScale, glm::vec3(0.1f), t / timeToReach);
507+
renderer->localPosition = mix(startPos, glm::vec3(0), t / timeToReach);
508+
509+
t += brl::GfxEngine::instance->getDeltaTime();
510+
511+
co_yield brl::GfxEngine::instance->getDeltaTime();
512+
}
513+
514+
destroy();
371515
}

0 commit comments

Comments
 (0)