diff options
Diffstat (limited to 'enemy.c')
-rw-r--r-- | enemy.c | 198 |
1 files changed, 198 insertions, 0 deletions
@@ -0,0 +1,198 @@ +#include "enemy.h" +#include <stdlib.h> + +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 */ +/* }; */ +/* } */ |