@@ -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
238287brl::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
339412void 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
362438void 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