#include "Enemy.h" #include "Layers.h" #include "debug.h" #include "game_world.h" #include "physics.h" #include "physics_world.h" #include "sprite.h" START_REFLECT(Enemy) REFLECT_TYPECLASS(Enemy, Transformable) REFLECT_TYPECLASS(Enemy, Drop) REFLECT_TYPECLASS(Enemy, PhysicsEntity) REFLECT_TYPECLASS(Enemy, BehaviourEntity) REFLECT_TYPECLASS(Enemy, Damagable) END_REFLECT(Enemy) impl_Transformable_for(Enemy, EnemyGetTransform ) impl_Drop_for(Enemy, EnemyDestroy ) impl_BehaviourEntity_for(Enemy, EnemyStart, EnemyUpdate, EnemyDraw, EnemyGetDepth ) impl_PhysicsEntity_for(Enemy, EnemyGetRigidBody, EnemyOnCollision, EnemyOnOverlap ) impl_Damagable_for(Enemy, EnemyDamage ) Enemy* MakeEnemy() { Enemy* self = malloc(sizeof(Enemy)); ASSERT_RETURN(self != NULL, NULL, "Failed to allocate Enemy"); *self = (Enemy){ .transform = IdentityTransform, .behaviour = NULL, .rigidbody = NULL, .collider = NULL, .hitbox = NULL, .sprite = sprite_new_empty(), .facing = 1, .stun_time = 0.f, .idleAnim = NULL, .walkAnim = NULL, .hurtAnim = NULL, .currentAnimation = NULL, .health = 15, }; self->rigidbody = rigidbody_make(Enemy_as_PhysicsEntity(self)); self->collider = collider_new(Enemy_as_PhysicsEntity(self), shape_new_square(MakeVector(0.2f, 0.05f)), 0, PHYSICS_LAYER_DEFAULT, PHYSICS_LAYER_DEFAULT); self->collider = collider_new(Enemy_as_PhysicsEntity(self), shape_new((Vector[]){ MakeVector(-0.2f, -0.95f), MakeVector( 0.2f, -0.95f), MakeVector( 0.2f, 0.0f), MakeVector(-0.2f, 0.0f), }, 4), 1, PHYSICS_LAYER_COMBAT, 0x0); PhysicsEntity pe = Enemy_as_PhysicsEntity(self); LOG_INFO("enemy instantiated mirroring as: %s", pe.mirror->get_typestring(pe.data)); sprite_set_origin(self->sprite, MakeVector(0.45f, 0.925f)); self->idleAnim = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Idle.png", IVectorFrom(512)), 1.5f, LoopMode_Loop); self->walkAnim = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Walk.png", IVectorFrom(512)), 1.5f, LoopMode_Loop); self->hurtAnim = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Hurt.png", IVectorFrom(512)), 5.f, LoopMode_Stop); return self; } Enemy* SpawnEnemy(Vector location, const State* entryState) { Enemy* self = MakeEnemy(); self->behaviour = state_machine_init(self, entryState); rigidbody_get_transform(self->rigidbody)->position = location; game_world_add_entity(Enemy_as_BehaviourEntity(self)); physics_world_add_entity(Enemy_as_PhysicsEntity(self)); return self; } void EnemyStart(Enemy* self) {} void EnemyUpdate(Enemy* self, float deltaTime) { state_machine_update(self->behaviour, deltaTime); if(self->stun_time > 0.0f) self->stun_time -= deltaTime; } void EnemyDraw(Enemy* self) { sprite_flip_horizontal(self->sprite, self->facing == -1); animation_sprite_draw(self->currentAnimation, &self->transform); } void EnemyDestroy(Enemy* self) { state_machine_destroy(self->behaviour); collider_destroy(self->collider); rigidbody_destroy(self->rigidbody); sprite_destroy(self->sprite); physics_world_remove_entity(Enemy_as_PhysicsEntity(self)); free(self); } void EnemyOnCollision(Enemy* self, Collision collision) {} void EnemyOnOverlap(Enemy* self, Collider* other) {} Transform* EnemyGetTransform(Enemy* self) { return &self->transform; } RigidBody* EnemyGetRigidBody(Enemy* self) { return self->rigidbody; } int EnemyDamage(Enemy* self, DamageEventData* data) { self->health -= data->damageAmount; LOG_INFO("Damage received"); if(self->health <= 0) { game_world_destroy_entity(Enemy_as_BehaviourEntity(self)); return 1; } else { self->stun_time = data->stun; float direction = ((data->origin.x - self->transform.position.x) > 0) * 2 - 1; self->facing = direction; rigidbody_get_transform(self->rigidbody)->position = vaddf(self->transform.position, MakeVector(-direction * data->knockback, 0)); return 0; } }