#include "enemy.h" #include animation_player_t get_enemy_animation(enum enemy_type type){ switch (type){ case TEST_ENEMY: return make_animation_player(&textures[T_PLAYER], 12, 8, 40, 64, 8, 0); case SKELETON: return make_animation_player(&textures[T_SKELETON_MOVE], 1, 10, 0, 10, 1, 0); default: fprintf(stderr, "get_enemy_animation() error"); return (animation_player_t){}; } } /* Vector2 get_enemy_size(enum enemy_type type){ */ /* switch(type){ */ /* case TEST_ENEMY: */ /* return (Vector2){ 13, 18 }; */ /* case SKELETON: */ /* return (Vector2){ 12, 17 }; */ /* default: */ /* return (Vector2){ 0, 0 }; */ /* } */ /* } */ Rectangle get_enemy_hitbox(enum enemy_type type){ switch(type){ case TEST_ENEMY: return (Rectangle){ 1, 5, 13, 18 }; case SKELETON: return (Rectangle){ 7, 12, 12, 17 }; default: return (Rectangle){0}; } } void flip_enemy_y_axis(enemy_t *e){ if (e->direction.x < 0){ e->animation.frame_rec.width = -abs(e->animation.frame_rec.width); e->hitbox.x = e->position.x + e->animation.frame_width - e->hb_offset.x - e->hitbox.width; } else { e->animation.frame_rec.width = abs(e->animation.frame_rec.width); e->hitbox.x = e->position.x + e->hb_offset.x; } } enemy_t make_enemy(enum enemy_type type, int max_health, int x, int y, int speed){ animation_player_t enemy_anim = get_enemy_animation(type); Rectangle hitbox = get_enemy_hitbox(type); Vector2 offset = (Vector2){ hitbox.x, hitbox.y }; hitbox.x += x; hitbox.y += y; return (enemy_t) { .animation = enemy_anim, .type = type, .health = max_health, .health_max = max_health, .position = (Vector2){ x, y }, .hitbox = hitbox, .hb_offset = offset, /* .size = get_enemy_size(type), */ /* .center = (Vector2){ x + enemy_anim.frame_width / 2, y + enemy_anim.frame_height / 2}, */ .speed = speed, .active = 1 }; } void move_enemy(enemy_t* e, float dt){ float x_move = e->direction.x * e->speed * dt; float y_move = e->direction.y * e->speed * dt; e->position.x += x_move; e->position.y += y_move; e->hitbox.x += x_move; e->hitbox.y += y_move; /* e->center.x = e->position.x + e->size.x / 2; */ /* e->center.y = e->position.y + e->size.y / 2; */ } void update_enemy_basic(enemy_t *e, Vector2 target, float dt){ float old = e->direction.x; e->direction = normalize_vector(vector_diff(target, e->position)); if (signbit(old) != signbit(e->direction.x)){ flip_enemy_y_axis(e); } } void update_test_enemy(enemy_t *e, Vector2 target, float dt){ e->direction = normalize_vector(vector_diff(target, e->position)); int new_offset = get_dir(floorf(e->direction.x + 1) + 3 * floorf(e->direction.y + 1)); if (new_offset != e->animation.index_offset){ animation_player_t *anim = &e->animation; anim->index_offset = new_offset; anim->frame_current = anim->index_start + anim->index_offset; } } void update_enemy(enemy_t *e, Vector2 target, float dt){ update_frame(&e->animation); switch (e->type){ case TEST_ENEMY: update_test_enemy(e, target, dt); break; case SKELETON: update_enemy_basic(e, target, dt); break; default: break; } if (distance(target, e->position) > 1.0f){ move_enemy(e, dt); } } /* animation_player_t *anim = &enemy->animation; */ /* DrawTextureRec(*anim->sheet, anim->frame_rec, enemy->position, WHITE); */ void draw_enemy(enemy_t *enemy){ draw_frame(&enemy->animation, enemy->position, WHITE); DrawRectangleLinesEx(enemy->hitbox, 1, LIGHTGRAY); Rectangle hb = enemy->hitbox; Rectangle health_box = { hb.x, hb.y + hb.height + 5, hb.width, 5}; float per_health_width = health_box.width / enemy->health_max; DrawRectangleLinesEx(health_box, 1, BLACK); DrawRectangleRec((Rectangle){health_box.x, health_box.y, per_health_width * enemy->health, 5}, RED); /* animation_player_t *anim = &enemy->animation; */ /* Vector2 pos = enemy->position; */ /* DrawRectangleLines(pos.x, pos.y, anim->frame_width, anim->frame_height, SKYBLUE); */ draw_frame_box(&enemy->animation, enemy->position); } /* Vector2 p = enemy->position; */ /* Vector2 s = enemy->size; */ /* Vector2 pos = (Vector2) {p.x, p.y + s.y + 5}; */ /* Rectangle rec = (Rectangle) { pos.x, pos.y, s.x, 5 }; */ /* float box_width = s.x / enemy->health_max; */ /* /\* box_width * enemy->health *\/ */ /* DrawRectangleLinesEx(rec, 1, BLACK); */ /* DrawRectangleV(pos, (Vector2){box_width * enemy->health, 5}, RED); */ /* /\* DrawRectangleLinesEx((Rectangle){ p.x, p.y, s.x, s.y }, 2, LIGHTGRAY); *\/ */ /* /\* DrawRectangleV(enemy->position, enemy->size, LIGHTGRAY); *\/ */ enemy_t spawn_enemy(enemy_spawner_t* spawner){ Rectangle *s = &spawner->border; int x = s->x, y = s->y; if (rand() % 2){ x += rand() % 2 ? 0 : s->width; y += rand() % (int)s->height; } else { x += rand() % (int)s->width; y += rand() % 2 ? 0 : s->height; } start_cooldown(spawner); return make_enemy(rand() % ENEMY_TYPE_COUNT, 3, x, y, 40); } void update_spawner(enemy_spawner_t* spawner, float dt){ spawner->cooldown -= dt; } void start_cooldown(enemy_spawner_t* spawner){ spawner->cooldown = spawner->cooldown_max; } bool can_spawn(const enemy_spawner_t* spawner){ return spawner->cooldown <= 0; } /* animation_player_t enemy_anim = { */ /* .sheet = texture, */ /* .frame_counter = 0, */ /* .frame_speed = 5, */ /* .frame_width = texture->width / 8.0, */ /* .frame_height = texture->height / 12.0, */ /* .index_start = 40, */ /* .index_end = 64, */ /* .index_increment = 8, */ /* .index_offset = 0 */ /* }; */ /* enemy_anim.frame_current = enemy_anim.index_start; */ /* enemy_anim.frame_rec = (Rectangle){ 0, 0, enemy_anim.frame_width, enemy_anim.frame_height}; */ /* enemy_t make_test_enemy(Texture2D *texture, int max_health, int x, int y, int speed){ */ /* /\* animation_player_t enemy_anim = make_animation_player(texture, 12, 8, 40, 64, 8, 0); *\/ */ /* animation_player_t enemy_anim = get_enemy_animation(TEST_ENEMY); */ /* return (enemy_t) { */ /* .animation = enemy_anim, */ /* .type = TEST_ENEMY, */ /* .health = max_health, */ /* .health_max = max_health, */ /* .position = (Vector2){ x, y }, */ /* .size = (Vector2){ enemy_anim.frame_width, enemy_anim.frame_height }, */ /* .center = (Vector2){ x + enemy_anim.frame_width / 2, y + enemy_anim.frame_height / 2}, */ /* .speed = speed */ /* }; */ /* } */