summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzlago2024-10-09 06:10:39 +0200
committerzlago2024-10-09 06:10:39 +0200
commit45a781a5af1107c7511fba7d4b4b66588cbf008f (patch)
treefe310f3938930e85b49cfbf2109fafcc7800699e /src
parent753cdae8c9656f2f5c8380868dca1c5e9be9b437 (diff)
start working on the first enemy
Diffstat (limited to 'src')
-rw-r--r--src/funsinit.c3
-rw-r--r--src/walker.c329
2 files changed, 332 insertions, 0 deletions
diff --git a/src/funsinit.c b/src/funsinit.c
index 25ba630..264a653 100644
--- a/src/funsinit.c
+++ b/src/funsinit.c
@@ -2,9 +2,12 @@
#include "loader.h"
#include "main.h"
+void *walker_new(struct entities *entities);
+int walker_property(void *const restrict entity, char const *const restrict property, char const *const restrict value);
void *warp_new(struct entities *entities);
int warp_property(void *const restrict entity, char const *const restrict property, char const *const restrict value);
void funs_init(void) {
+ res_push_fun(walker_new, walker_property, "walker");
res_push_fun(warp_new, warp_property, "warp");
}
diff --git a/src/walker.c b/src/walker.c
new file mode 100644
index 0000000..9a74816
--- /dev/null
+++ b/src/walker.c
@@ -0,0 +1,329 @@
+#include "main.h"
+#include "entity.h"
+#include "loader.h"
+#include "input.h"
+#include "tilemap.h"
+#include <stdbool.h>
+
+#define SIZE 4
+#define ACCELERATION 2
+#define FRICTION 3
+#define MAX_SPEED 16
+#define GRAVITY 2
+#define JUMP 40
+
+enum {
+ WALKER_NONE,
+ WALKER_IDLE,
+ WALKER_PATROL,
+ WALKER_ALERT,
+ WALKER_ATTACK,
+};
+
+enum {
+ WALKER_A_IDLE,
+ WALKER_A_IDLE2,
+ WALKER_A_WALK,
+ WALKER_A_WALK2,
+ WALKER_A_WALK3,
+ WALKER_A_WALK4,
+ WALKER_A_JUMP,
+ WALKER_A_FALL,
+ WALKER_A_FALL2,
+};
+
+struct anim walker_anims[] = {
+ {WALKER_A_IDLE2, {0, 0, 16, 16}, 300},
+ {WALKER_A_IDLE, {0, 32, 16, 16}, 2},
+ {WALKER_A_WALK2, {0, 0, 16, 16}, 6},
+ {WALKER_A_WALK3, {16, 0, 16, 16}, 6},
+ {WALKER_A_WALK4, {32, 0, 16, 16}, 6},
+ {WALKER_A_WALK, {48, 0, 16, 16}, 6},
+ {WALKER_A_JUMP, {16, 0, 16, 16}, 300},
+ {WALKER_A_FALL2, {32, 0, 16, 16}, 15},
+ {WALKER_A_FALL2, {48, 0, 16, 16}, 15},
+};
+
+static int bullet_update(struct projectile *self) {
+ self->x += self->velocity.x;
+ if (collision_solid(tilemap_tile(tilemap, from_fixed(self->x), from_fixed(self->y)))) {
+ self->velocity.x = -self->velocity.x;
+ self->x += self->velocity.x;
+ }
+
+ self->y += self->velocity.y;
+ if (collision_solid(tilemap_tile(tilemap, from_fixed(self->x), from_fixed(self->y)))) {
+ self->velocity.y = -self->velocity.y;
+ self->y += self->velocity.y;
+ }
+
+ self->hp--;
+ int x = from_fixed(self->x);
+ int y = from_fixed(self->y);
+ self->hitbox = (struct hitbox) {.left = x, .right = x, .top = y, .bottom = y};
+ #if 0
+ struct particle *part = entities.particle + entities.particles;
+ part->x = self->x + to_fixed(self->facing >= 0? sin(self->hp): -sin(self->hp)) * 6;
+ part->y = self->y - to_fixed(cos(self->hp)) * 4;
+ part->velocity = (struct vec2) {0, 0};
+ part->rect = (SDL_Rect) {0, 0, 4, 4};
+ part->acceleration = (struct vec2) {0, 0};
+ part->hp = 5;
+ entities.particles++;
+ #endif
+ if (self->hp == 0) {
+ return 1;
+ self->state = 0;
+ }
+ return 0;
+}
+
+static int bullet_draw(struct projectile *self, int camX, int camY) {
+ SDL_Rect rect = {4, 0, 4, 4};
+ SDL_RenderCopy(renderer, self->texture, &rect, &(SDL_Rect) {from_fixed(self->x) - camX - 1, from_fixed(self->y) - camY - 1, 4, 4});
+ SDL_RenderCopy(renderer, self->texture, &rect, &(SDL_Rect) {from_fixed(self->x - self->velocity.x) - camX - 1, from_fixed(self->y - self->velocity.y) - camY - 1, 4, 4});
+ //SDL_RenderFillRect(renderer, &(SDL_Rect) {from_fixed(self->x) - camX - 8, from_fixed(self->y) - camY - 12, 16, 16});
+ return 0;
+}
+
+static void bullet_free(struct projectile *self) {}
+
+static collision_T collide(struct entity *self) {
+ return tilemap_area(tilemap, from_fixed(self->x) - SIZE / 2, from_fixed(self->y) - SIZE, from_fixed(self->x) + SIZE / 2, from_fixed(self->y));
+}
+
+static int move(struct entity *self, signed direction) {
+ int on_ground = false;
+ int const dx = direction * ACCELERATION;
+ self->velocity.x += dx;
+ // deaccel
+ if (dx == 0) {
+ if (self->velocity.x < -FRICTION) {
+ self->velocity.x += FRICTION;
+ } else if (self->velocity.x > FRICTION) {
+ self->velocity.x -= FRICTION;
+ } else {
+ self->velocity.x = 0;
+ }
+ }
+ // speed cap
+ if (self->velocity.x > MAX_SPEED) {
+ self->velocity.x = MAX_SPEED;
+ } else if (self->velocity.x < -MAX_SPEED) {
+ self->velocity.x = -MAX_SPEED;
+ }
+ // x collision
+ self->x += self->velocity.x;
+ collision_T const cx = collide(self);
+ if (collision_solid(cx)) {
+ if (self->velocity.x < 0) {
+ self->x += to_fixed(8) - ((self->x - to_fixed(SIZE / 2)) % to_fixed(8)); // left
+ } else if (self->velocity.x == 0) {
+ //fputs("what?\n", stderr);
+ } else {
+ self->x -= ((self->x + to_fixed(SIZE / 2)) % to_fixed(8)); // right
+ }
+ self->velocity.x = 0;
+ }
+ if (self->velocity.x < 0) {
+ self->facing = -1;
+ } else if (self->velocity.x > 0) {
+ self->facing = +1;
+ }
+ self->velocity.y += GRAVITY;
+ // y collision
+ self->y += self->velocity.y;
+ collision_T const cy = collide(self);
+ if (collision_solid(cy)) {
+ if (self->velocity.y < 0) {
+ self->y += to_fixed(8) - ((self->y - to_fixed(SIZE)) % to_fixed(8)); // up
+ self->velocity.y = 0;
+ } else if (self->velocity.y == 0) {
+ //fputs("what?\n", stderr);
+ } else {
+ self->y -= ((self->y) % to_fixed(8)); // down
+ self->velocity.y = to_fixed(1); // crazy but it works
+ on_ground = true;
+ }
+ }
+
+ if (collision_hazard(cx | cy)) {
+ self->hurt(self, 1);
+ }
+
+ self->hitbox.left = from_fixed(self->x) - SIZE / 2;
+ self->hitbox.right = from_fixed(self->x) + SIZE / 2;
+ self->hitbox.top = from_fixed(self->y) - SIZE;
+ self->hitbox.bottom = from_fixed(self->y);
+ return on_ground;
+}
+
+static void anim(struct entity *self, unsigned anim) {
+ self->anim = walker_anims[anim];
+}
+
+static void attack(struct entity *self) {
+ entities.projectile[entities.projectiles] = (struct projectile) {
+ .update = bullet_update,
+ .draw = bullet_draw,
+ .free = bullet_free,
+ .x = self->x, .y = self->y - to_fixed(3),
+ .velocity = (struct vec2) {self->velocity.x + to_fixed(self->facing), 0},
+ .hitbox = {
+ 0, 0, 0, 0,
+ },
+ .state = WALKER_IDLE,
+ .hp = 300,
+ .timer = 0,
+ .facing = self->facing,
+ .faction = FACTION_ENEMY,
+ .iframes = 0,
+ .texture = NULL,
+ .ext = NULL,
+ };
+ //anim(entities->projectile + entities->projectiles, WALKER_A_IDLE);
+ entities.projectile[entities.projectiles].texture = res_get_texture("particles").data;
+ entities.projectiles++;
+}
+
+static int walker_update(struct entity *self) {
+ if (self->hp <= 0) {
+ self->state = 0;
+ entities.enemies--;
+ return 1;
+ }
+ switch (self->state) {
+ case WALKER_IDLE:
+ if (move(self, 0) == false) {
+ abort();
+ self->velocity.y = 0;
+ anim(self, WALKER_A_FALL);
+ //self->state = WALKER_FALL;
+ }
+ self->timer--;
+ if (self->timer == 0) {
+ self->facing = -self->facing;
+ anim(self, WALKER_A_WALK);
+ self->state = WALKER_PATROL;
+ }
+ break;
+
+ case WALKER_PATROL:
+ if (move(self, self->facing) == false) {
+ abort();
+ self->velocity.y = 0;
+ anim(self, WALKER_A_FALL);
+ //self->state = WALKER_FALL;
+ }
+ if (collision_solid(tilemap_tile(tilemap, from_fixed(self->x) + self->facing * 8, from_fixed(self->y) - 4)) ||
+ !collision_solid(tilemap_tile(tilemap, from_fixed(self->x) + self->facing * 8, from_fixed(self->y) + 4))) {
+ anim(self, WALKER_A_IDLE);
+ self->state = WALKER_IDLE;
+ self->timer = 30;
+ }
+ break;
+
+ case WALKER_ALERT:
+ attack(self);
+ if (!input_a(input_held)) {
+ self->velocity.y /= 2;
+ anim(self, WALKER_A_FALL);
+ //self->state = WALKER_FALL;
+ }
+ if (self->velocity.y > 0) {
+ anim(self, WALKER_A_FALL);
+ //self->state = WALKER_FALL;
+ }
+ if (move(self, 0) == true) {
+ anim(self, WALKER_A_IDLE);
+ self->state = WALKER_IDLE;
+ }
+ break;
+
+ case WALKER_ATTACK:
+ if (move(self, 0) == true) {
+ anim(self, WALKER_A_IDLE);
+ self->state = WALKER_IDLE;
+ }
+ break;
+ }
+ if (self->iframes > 0) {
+ self->iframes--;
+ }
+ self->anim.length--;
+ if (self->anim.length == 0) {
+ anim(self, self->anim.frame);
+ }
+ return 0;
+}
+
+static int walker_hurt(struct entity *self, int damage) {
+ if (self->iframes == 0) {
+ self->hp -= damage;
+ self->iframes = 60;
+ for (int x = -1; x <= 1; x += 2) {
+ for (int y = -1; y <= 1; y += 2) {
+ struct particle *part = entities.particle + entities.particles;
+ part->x = self->x;
+ part->y = self->y;
+ part->velocity = (struct vec2) {to_fixed(x), to_fixed(y) - 8};
+ part->rect = (SDL_Rect) {4, 0, 4, 4};
+ part->acceleration = (struct vec2) {0, 1};
+ part->hp = 30;
+ entities.particles++;
+ }
+ }
+ }
+ return 0;
+}
+
+static int walker_draw(struct entity *self, int camX, int camY) {
+ if (!(self->iframes & 0x4)) {
+ SDL_Rect rect = self->anim.rect;
+ if (self->facing == -1) {
+ rect.y += 16;
+ }
+ SDL_RenderCopy(renderer, self->texture, &rect, &(SDL_Rect) {from_fixed(self->x) - camX - 8, from_fixed(self->y) - camY - 12, 16, 16});
+ }
+ return 0;
+}
+
+static void walker_free(struct entity *self) {
+ self->state = 0;
+}
+
+struct entity *walker_new(struct entities *entities) {
+ entities->enemy[entities->enemies] = (struct entity) {
+ .update = walker_update,
+ .hurt = walker_hurt,
+ .draw = walker_draw,
+ .free = walker_free,
+ .x = 0, .y = 0,
+ .velocity = {.x = 0, .y = to_fixed(1)},
+ .hitbox = {
+ 0, 0, 0, 0,
+ },
+ .state = WALKER_PATROL,
+ .hp = 3,
+ .timer = 0,
+ .facing = 1,
+ .faction = FACTION_ENEMY,
+ .iframes = 0,
+ .texture = NULL,
+ .ext = NULL,
+ };
+ anim(entities->enemy + entities->enemies, WALKER_A_IDLE);
+ entities->enemy[entities->enemies].texture = res_get_texture("fywi").data;
+ return entities->enemy + entities->enemies++;
+}
+
+int walker_property(struct entity *const restrict self, char const *const restrict property, char const *const restrict value) {
+ if (strcmp(property, "x") == 0) {
+ self->x = to_fixed(atoi(value));
+ } else if (strcmp(property, "y") == 0) {
+ self->y = to_fixed(atoi(value));
+ } else {
+ return 1;
+ }
+ return 0;
+}