diff options
Diffstat (limited to 'src/hvy_guns.c')
-rw-r--r-- | src/hvy_guns.c | 449 |
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); +} |