summary refs log tree commit diff
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);
+}