fencer/game/src/Enemy.c

141 lines
4.2 KiB
C

#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->hitbox = collider_new(Enemy_as_PhysicsEntity(self), shape_new((Vector[]){
MakeVector(-0.1f, -0.9f),
MakeVector( 0.1f, -0.9f),
MakeVector( 0.1f, 0.0f),
MakeVector(-0.1f, 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) {
if(self->stun_time > 0.f)
return 0;
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;
}
}