summaryrefslogtreecommitdiff
path: root/src/hvy_guns.c
diff options
context:
space:
mode:
authorzlago2024-10-28 10:27:19 +0100
committerzlago2024-10-28 10:29:08 +0100
commitf7e4de7c45ed848312690ce6cfb62ae562e8347c (patch)
tree23d4afd3af64690c789249ce7eebb30137581657 /src/hvy_guns.c
parentee316a07cdfb01e52694edef2cc998e672e2885b (diff)
pacer enemy [wip]
Diffstat (limited to 'src/hvy_guns.c')
-rw-r--r--src/hvy_guns.c449
1 files changed, 449 insertions, 0 deletions
diff --git a/src/hvy_guns.c b/src/hvy_guns.c
new file mode 100644
index 0000000..43fd1f1
--- /dev/null
+++ b/src/hvy_guns.c
@@ -0,0 +1,449 @@
+#include "loader.h"
+#include "tilemap.h"
+#include <math.h>
+#include "particles.h"
+#include "gun.h"
+
+#define POS_X (parent->x + self->x * parent->facing)
+#define POS_Y (parent->y + self->y)
+
+#define HVY_BLASTER_RELOAD 120
+
+#define HVY_SHOTGUN_RELOAD 150
+
+#define HVY_REPEATER_RELOAD 60
+#define HVY_REPEATER_ROUNDS 3
+
+#define HVY_CHAINGUN_RELOAD 30
+#define HVY_CHAINGUN_MIN_RELOAD 5
+
+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 (hitbox_overlap(self->hitbox, entities.player[0].hitbox)) {
+ if (entities.player[0].hurt(entities.player + 0, (struct damage) {1, 60})) {
+ //return 1;
+ }
+ }
+ if (self->hp == 0) {
+ return 1;
+ self->state = 0;
+ }
+ return 0;
+}
+
+static int projectile_update(struct projectile *self) {
+ self->x += self->velocity.x;
+ if (collision_solid(tilemap_tile(tilemap, from_fixed(self->x), from_fixed(self->y)))) {
+ goto explod;
+ }
+
+ self->y += self->velocity.y;
+ if (collision_solid(tilemap_tile(tilemap, from_fixed(self->x), from_fixed(self->y)))) {
+ goto explod;
+ }
+
+ 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 (hitbox_overlap(self->hitbox, entities.player[0].hitbox)) {
+ entities.player[0].hurt(entities.player + 0, (struct damage) {1, 60});
+ goto explod;
+ }
+ if (self->hp == 0) {
+ goto explod;
+ }
+ return 0;
+ explod:
+ for (float r = 0; r < M_PI * 2; r += M_PI / 6) {
+ struct particle *part = entities.particle + entities.particles;
+ part->x = self->x;
+ part->y = self->y;
+ part->velocity = (struct vec2) {sin(r) * 24, cos(r) * 24};
+ part->rect = particle_red;
+ part->acceleration = (struct vec2) {0, 0};
+ part->hp = 15;
+ entities.particles++;
+ }
+ return 1;
+}
+
+static int laser_update(struct projectile *self) {
+ for (int i = 0; i < 15; i++) {
+ 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;
+ }
+
+ 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 (hitbox_overlap(self->hitbox, entities.player[0].hitbox)) {
+ if (entities.player[0].hurt(entities.player + 0, (struct damage) {1, 60})) {
+ return 1;
+ }
+ }
+ struct particle *part = entities.particle + entities.particles;
+ part->x = self->x;
+ part->y = self->y;
+ part->velocity = (struct vec2) {0, 0};
+ part->rect = particle_red;
+ part->acceleration = (struct vec2) {0, 0};
+ part->hp = i & 15;
+ entities.particles++;
+ }
+ self->hp -= 15;
+ if (self->hp <= 0) {
+ return 1;
+ self->state = 0;
+ }
+ return 0;
+}
+
+static int bullet_draw(struct projectile *self, int camX, int camY) {
+ SDL_Rect const *rect;
+ if (self->hp & 0x2) {
+ rect = &particle_red;
+ } else {
+ rect = &particle_white;
+ }
+ 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) {}
+
+int hvy_blaster(struct gun *self, struct entity *parent, struct entity *target) {
+ if (self->timer > 0) {
+ self->timer--;
+ return 0;
+ }
+ if (target != NULL) {
+ entities.projectile[entities.projectiles] = (struct projectile) {
+ .update = bullet_update,
+ .draw = bullet_draw,
+ .free = bullet_free,
+ .x = POS_X, .y = POS_Y,
+ .velocity = (struct vec2) {parent->velocity.x + to_fixed(parent->facing), 1},
+ .hitbox = {
+ 0, 0, 0, 0,
+ },
+ .state = 1,
+ .hp = 300,
+ .timer = 0,
+ .facing = parent->facing,
+ .faction = parent->faction,
+ .iframes = 0,
+ .texture = NULL,
+ .ext = NULL,
+ };
+ //anim(entities->projectile + entities->projectiles, PACER_A_IDLE);
+ entities.projectile[entities.projectiles].texture = res_get_texture("particles").data;
+ entities.projectiles++;
+ self->timer = HVY_BLASTER_RELOAD;
+ }
+ return 1;
+}
+
+void hvy_blaster_new(struct gun *self, int x, int y) {
+ self->update = hvy_blaster;
+ self->timer = HVY_BLASTER_RELOAD;
+ self->counter = 0;
+ self->x = to_fixed(x);
+ self->y = to_fixed(y);
+}
+
+int hvy_shotgun(struct gun *self, struct entity *parent, struct entity *target) {
+ if (self->timer > 0) {
+ self->timer--;
+ return 0;
+ }
+ if (target != NULL) {
+ float angle = atan2(target->x - POS_X, target->y - POS_Y);
+ for (int i = -2; i <= 2; i++) {
+ entities.projectile[entities.projectiles] = (struct projectile) {
+ .update = bullet_update,
+ .draw = bullet_draw,
+ .free = bullet_free,
+ .x = POS_X, .y = POS_Y,
+ .velocity = (struct vec2) {parent->velocity.x + to_fixed(sin(angle + i * 0.1)), to_fixed(cos(angle + i * 0.1))},
+ .hitbox = {
+ 0, 0, 0, 0,
+ },
+ .state = 1,
+ .hp = 300,
+ .timer = 0,
+ .facing = parent->facing,
+ .faction = parent->faction,
+ .iframes = 0,
+ .texture = NULL,
+ .ext = NULL,
+ };
+ //anim(entities->projectile + entities->projectiles, PACER_A_IDLE);
+ entities.projectile[entities.projectiles].texture = res_get_texture("particles").data;
+ entities.projectiles++;
+ }
+ self->timer = HVY_SHOTGUN_RELOAD;
+ }
+ return 1;
+}
+
+void hvy_shotgun_new(struct gun *self, int x, int y) {
+ self->update = hvy_shotgun;
+ self->timer = HVY_SHOTGUN_RELOAD;
+ self->counter = 0;
+ self->x = to_fixed(x);
+ self->y = to_fixed(y);
+}
+
+int hvy_repeater(struct gun *self, struct entity *parent, struct entity *target) {
+ if (self->timer > 0) {
+ self->timer--;
+ return 0;
+ }
+ if (target != NULL && self->counter == 0) {
+ self->counter = HVY_REPEATER_ROUNDS;
+ }
+ if (self->counter > 0) {
+ entities.projectile[entities.projectiles] = (struct projectile) {
+ .update = bullet_update,
+ .draw = bullet_draw,
+ .free = bullet_free,
+ .x = POS_X, .y = POS_Y,
+ .velocity = (struct vec2) {parent->velocity.x + to_fixed(parent->facing), (int []) {0, 1, 0, -1}[self->counter % 4]},
+ .hitbox = {
+ 0, 0, 0, 0,
+ },
+ .state = 1,
+ .hp = 300,
+ .timer = 0,
+ .facing = parent->facing,
+ .faction = parent->faction,
+ .iframes = 0,
+ .texture = NULL,
+ .ext = NULL,
+ };
+ //anim(entities->projectile + entities->projectiles, PACER_A_IDLE);
+ entities.projectile[entities.projectiles].texture = res_get_texture("particles").data;
+ entities.projectiles++;
+ self->counter--;
+ if (self->counter > 0) {
+ self->timer = 6;
+ } else {
+ self->timer = HVY_REPEATER_RELOAD;
+ if (target != NULL) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+ return 1;
+}
+
+void hvy_repeater_new(struct gun *self, int x, int y) {
+ self->update = hvy_repeater;
+ self->timer = HVY_REPEATER_RELOAD;
+ self->counter = 0;
+ self->x = to_fixed(x);
+ self->y = to_fixed(y);
+}
+
+int hvy_chaingun(struct gun *self, struct entity *parent, struct entity *target) {
+ if (self->timer > 0) {
+ self->timer--;
+ return 0;
+ }
+ if (target != NULL) {
+ entities.projectile[entities.projectiles] = (struct projectile) {
+ .update = bullet_update,
+ .draw = bullet_draw,
+ .free = bullet_free,
+ .x = POS_X, .y = POS_Y,
+ .velocity = (struct vec2) {parent->velocity.x + to_fixed(parent->facing), (int []) {0, 1, 0, -1}[self->counter % 4]},
+ .hitbox = {
+ 0, 0, 0, 0,
+ },
+ .state = 1,
+ .hp = 300,
+ .timer = 0,
+ .facing = parent->facing,
+ .faction = parent->faction,
+ .iframes = 0,
+ .texture = NULL,
+ .ext = NULL,
+ };
+ //anim(entities->projectile + entities->projectiles, PACER_A_IDLE);
+ entities.projectile[entities.projectiles].texture = res_get_texture("particles").data;
+ entities.projectiles++;
+ if (self->counter > HVY_CHAINGUN_MIN_RELOAD) {
+ self->counter--;
+ }
+ self->timer = self->counter;
+ } else {
+ self->counter = HVY_CHAINGUN_RELOAD;
+ }
+ return 1;
+}
+
+void hvy_chaingun_new(struct gun *self, int x, int y) {
+ self->update = hvy_chaingun;
+ self->timer = HVY_CHAINGUN_RELOAD;
+ self->counter = 0;
+ self->x = to_fixed(x);
+ self->y = to_fixed(y);
+}
+
+int hvy_launcher(struct gun *self, struct entity *parent, struct entity *target) {
+ if (self->timer > 0) {
+ self->timer--;
+ return 0;
+ }
+ if (target != NULL) {
+ entities.projectile[entities.projectiles] = (struct projectile) {
+ .update = projectile_update,
+ .draw = bullet_draw,
+ .free = bullet_free,
+ .x = POS_X, .y = POS_Y,
+ .velocity = (struct vec2) {parent->velocity.x + to_fixed(parent->facing), 1},
+ .hitbox = {
+ 0, 0, 0, 0,
+ },
+ .state = 1,
+ .hp = 300,
+ .timer = 0,
+ .facing = parent->facing,
+ .faction = parent->faction,
+ .iframes = 0,
+ .texture = NULL,
+ .ext = NULL,
+ };
+ //anim(entities->projectile + entities->projectiles, PACER_A_IDLE);
+ entities.projectile[entities.projectiles].texture = res_get_texture("particles").data;
+ entities.projectiles++;
+ self->timer = HVY_BLASTER_RELOAD;
+ }
+ return 1;
+}
+
+void hvy_launcher_new(struct gun *self, int x, int y) {
+ self->update = hvy_launcher;
+ self->timer = HVY_BLASTER_RELOAD;
+ self->counter = 0;
+ self->x = to_fixed(x);
+ self->y = to_fixed(y);
+}
+
+int hvy_laser(struct gun *self, struct entity *parent, struct entity *target) {
+ if (self->counter == 0) {
+ if (self->timer > 0) {
+ self->timer--;
+ return 0;
+ }
+ if (target != NULL) {
+ float angle = atan2(target->x - POS_X, target->y - POS_Y);
+ #if 0
+ entities.projectile[entities.projectiles] = (struct projectile) {
+ .update = laser_update,
+ .draw = bullet_draw,
+ .free = bullet_free,
+ .x = POS_X, .y = POS_Y,
+ .velocity = (struct vec2) {parent->velocity.x + to_fixed(sin(angle)), to_fixed(cos(angle))},
+ .hitbox = {
+ 0, 0, 0, 0,
+ },
+ .state = 1,
+ .hp = 500,
+ .timer = 0,
+ .facing = parent->facing,
+ .faction = parent->faction,
+ .iframes = 0,
+ .texture = NULL,
+ .ext = NULL,
+ };
+ //anim(entities->projectile + entities->projectiles, PACER_A_IDLE);
+ entities.projectile[entities.projectiles].texture = res_get_texture("particles").data;
+ entities.projectiles++;
+ self->timer = HVY_BLASTER_RELOAD;
+ #endif
+ self->counter = 25;
+ self->timer = angle * 128;
+ return 0;
+ }
+ } else {
+ if (target != NULL) {
+ self->counter--;
+ float angle = self->timer / 128.0;
+ if (self->counter != 0) {
+ float r = angle + (self->counter & 1? self->counter: -self->counter) * 0.05;
+ int const x = sin(r) * 16, y = cos(r) * 16;
+ struct particle *part = entities.particle + entities.particles;
+ part->x = POS_X + x * self->counter;
+ part->y = POS_Y + y * self->counter;
+ part->velocity = (struct vec2) {-x, -y};
+ part->rect = particle_white;
+ part->acceleration = (struct vec2) {0, 0};
+ part->hp = self->counter;
+ entities.particles++;
+ return 0;
+ }
+ entities.projectile[entities.projectiles] = (struct projectile) {
+ .update = laser_update,
+ .draw = bullet_draw,
+ .free = bullet_free,
+ .x = POS_X, .y = POS_Y,
+ .velocity = (struct vec2) {parent->velocity.x + to_fixed(sin(angle)), to_fixed(cos(angle))},
+ .hitbox = {
+ 0, 0, 0, 0,
+ },
+ .state = 1,
+ .hp = 500,
+ .timer = 0,
+ .facing = parent->facing,
+ .faction = parent->faction,
+ .iframes = 0,
+ .texture = NULL,
+ .ext = NULL,
+ };
+ //anim(entities->projectile + entities->projectiles, PACER_A_IDLE);
+ entities.projectile[entities.projectiles].texture = res_get_texture("particles").data;
+ entities.projectiles++;
+ self->timer = HVY_BLASTER_RELOAD;
+ } else {
+ self->counter = 0;
+ self->timer = 0;
+ }
+ }
+ return 1;
+}
+
+void hvy_laser_new(struct gun *self, int x, int y) {
+ self->update = hvy_laser;
+ self->timer = HVY_BLASTER_RELOAD;
+ self->counter = 0;
+ self->x = to_fixed(x);
+ self->y = to_fixed(y);
+}