aboutsummaryrefslogtreecommitdiff
path: root/enemy.c
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2024-09-30 22:13:31 +1000
committerquou <quou@disroot.org>2024-09-30 22:13:31 +1000
commitee655819d44307d974fb27e1fa04d079a3810d63 (patch)
treefaa7c7c833dab0ed83dece311576b53bd2e4b840 /enemy.c
parentde9a4fd93343d4654dfe7e2a566704644a9f306f (diff)
enemy
Diffstat (limited to 'enemy.c')
-rw-r--r--enemy.c207
1 files changed, 207 insertions, 0 deletions
diff --git a/enemy.c b/enemy.c
new file mode 100644
index 0000000..bc0bbba
--- /dev/null
+++ b/enemy.c
@@ -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);
+}