#include "loader.h" #include "tilemap.h" #include #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); }