diff options
Diffstat (limited to 'enemy.c')
-rw-r--r-- | enemy.c | 207 |
1 files changed, 207 insertions, 0 deletions
@@ -0,0 +1,207 @@ +#include "animation.h" +#include "asset.h" +#include "config.h" +#include "maths.h" +#include "obj.h" +#include "physics.h" +#include "render.h" +#include "world.h" + +enum { + enemy_state_patrol, + enemy_state_approach, + enemy_state_approach2, + enemy_state_attack +}; + +int get_enemy_hp(Enemy_Type t) { + switch (t) { + case enemy_demon: + return 3; + } + return 0; +} + +void get_enemy_rect(Enemy_Type t, Rect* d) { + switch (t) { + case enemy_demon: + d->x = 2; + d->y = 2; + d->w = 12; + d->h = 14; + break; + } +} + +void init_enemy(Enemy* e, Enemy_Type t, int x, int y) { + e->t = t; + e->x = x; + e->y = y; + e->vx = 0; + e->vy = 0; + e->hp = get_enemy_hp(t); + e->frame = 0; + e->anim = asset_id_demon_idle_left_anm; + e->face = face_left; + e->state = enemy_state_patrol; +} + +void update_enemy_anim(Enemy* e) { + int done; + const Animation* anim = get_animation(e->anim); + done = update_anim(anim, &e->frame, &e->rect); + if ( + done && + e->t == enemy_demon && + e->state == enemy_state_approach + ) { + e->state = enemy_state_approach2; + } +} + +void update_enemy_phys(Enemy* e, const Map* map) { + Rect r; + get_enemy_rect(e->t, &r); + r.x <<= fbits; + r.y <<= fbits; + r.w <<= fbits; + r.h <<= fbits; + update_body( + map, + &e->x, + &e->y, + &e->vx, + &e->vy, + &e->grounded, + &e->headbutted, + &e->on_ramp, + &r + ); +} + +void update_enemy_hurt(Enemy* e, const World* w) { + Rect a; + int i; + get_enemy_rect(e->t, &a); + a.x += e->x >> fbits; + a.y += e->y >> fbits; + for (i = 0; i < w->deathzone_count; i++) { + const Deathzone* dz = &w->deathzones[i]; + if (rects_overlap(&a, &dz->r)) { + e->hp -= dz->hp; + e->vx -= dz->vx; + e->vy -= dz->vy; + } + } +} + +int tile_at(const Map* m, int x, int y) { + return + x < 0 || + y < 0 || + x >= map_w || + y >= map_h || + m->collision[x + y * map_w] == 1; +} + +void update_demon_move(Enemy* e, const World* w) { + int nanim = e->anim; + const Player* p = &w->player; + if (e->state == enemy_state_patrol) { + int dx = e->x - p->x; + int dy = e->y - p->y; + int dx2 = dx >> fbits; + int dy2 = dy >> fbits; + int dist = fxsqrt(dx * dx2 + dy * dy2) >> fbits; + if (e->grounded < 3) { + int tx, ty = + ((e->y >> fbits) - (map_tile_size >> 1)) / + map_tile_size; + int ty2 = ty + 2; + if (e->face == face_left) { + tx = ( + (e->x >> fbits) - (map_tile_size >> 1)) / + map_tile_size; + } else { + tx = ( + (e->x >> fbits) + map_tile_size + + (map_tile_size >> 1)) / + map_tile_size; + } + if ( + tile_at(&w->map, tx, ty) || + (ty2 < map_h && !tile_at(&w->map, tx, ty2)) + ) + e->face = !e->face; + if (e->face == face_left) { + e->vx -= enemy_demon_move_force; + } else { + e->vx += enemy_demon_move_force; + } + } + if (dist < enemy_demon_attack_dist) { + e->state = enemy_state_approach; + } + } else if (e->state == enemy_state_approach) { + if (p->x < e->x) + e->face = face_left; + else + e->face = face_right; + } else if (e->state == enemy_state_approach2) { + if (e->grounded < 3) { + e->vx = (p->x - e->vx) / 100; + if (e->face == face_left) + e->vx = -e->vx; + e->vy = -enemy_demon_jump_force; + e->grounded = 100; + e->state = enemy_state_attack; + } + } else if (e->state == enemy_state_attack) { + if (e->grounded < 3) { + e->state = enemy_state_patrol; + } + } + switch (e->face) { + case face_left: + nanim = + e->state == enemy_state_patrol? + asset_id_demon_walk_left_anm: + e->state == enemy_state_approach? + asset_id_demon_jump_left_anm: + asset_id_demon_idle_left_anm; + break; + case face_right: + nanim = + e->state == enemy_state_patrol? + asset_id_demon_walk_right_anm: + e->state == enemy_state_approach? + asset_id_demon_jump_right_anm: + asset_id_demon_idle_right_anm; + break; + } + if (nanim != e->anim) { + e->frame = 0; + e->anim = nanim; + } +} + +void update_enemy_move(Enemy* e, const World* w) { + switch (e->t) { + case enemy_demon: + update_demon_move(e, w); + break; + } +} + +int update_enemy(Enemy* e, World* w) { + update_enemy_anim(e); + update_enemy_hurt(e, w); + update_enemy_move(e, w); + update_enemy_phys(e, &w->map); + return e->hp <= 0; +} + +void ren_enemy(const Enemy* e, struct Renderer* r) { + const Bitmap* b = get_bitmap(asset_id_npc_img); + ren_map(r, e->x >> fbits, e->y >> fbits, &e->rect, b); +} |