From 43e31b6e124da754ef928d22fbb9a1d7640aab4b Mon Sep 17 00:00:00 2001
From: nathansmithsmith <thenathansmithsmith@gmail.com>
Date: Thu, 20 Jul 2023 03:08:57 -0600
Subject: New bullet system

---
 src/bullets.c             | 181 +++++++++++++++-------------------------------
 src/bullets.h             |  29 +++-----
 src/entities/antifaShip.c |  22 +++---
 src/entity.c              |  28 ++++++-
 src/entity.h              |  16 ++++
 src/game.c                |  13 ++--
 src/game.h                |   1 -
 src/gameScreen.c          |  31 ++++++--
 src/playerCamera.c        |  27 +++----
 src/playerCamera.h        |   2 +-
 src/world.c               |  54 ++++++++++++++
 11 files changed, 217 insertions(+), 187 deletions(-)

diff --git a/src/bullets.c b/src/bullets.c
index 10116c2..ea913c7 100644
--- a/src/bullets.c
+++ b/src/bullets.c
@@ -1,138 +1,59 @@
 #include "bullets.h"
 #include "game.h"
 
-Bullet createBullet(Entity entity, Vector3 direction, Vector3 offset, float damage) {
-	Bullet bullet = (Bullet){
-		.hit = false,
+Bullet createBulletFromEntity(Entity entity, float damage) {
+	return (Bullet){
 		.ray = (Ray){
-			.position = Vector3Add(entity.position, offset),
-			.direction = direction,
+			entity.position,
+			Vector3RotateByQuaternion((Vector3){0.0, 0.0, 1.0}, entity.rotation)
 		},
 		.fromId = entity.id,
 		.fromFingerprint = entity.fingerprint,
 		.damage = damage
 	};
-
-	return bullet;
-}
-
-void initBullets(Bullets * bullets) {
-	bullets->bullets = NULL;
-	bullets->bulletsCount = 0;
-}
-
-void freeBullets(Bullets * bullets) {
-	if (bullets->bullets != NULL)
-		KF_FREE(bullets->bullets);
-}
-
-KfError addBullet(Bullets * bullets, Bullet bullet) {
-	// Not allocated yet.
-	if (bullets->bullets == NULL) {
-		bullets->bullets = (Bullet*)KF_CALLOC(1, sizeof(Bullet));
-
-		if (bullets->bullets == NULL) {
-			ALLOCATION_ERROR;
-			return KFERROR;
-		}
-
-		bullets->bulletsCount = 1;
-		bullets->bullets[0] = bullet;
-		return KFSUCCESS;
-	}
-
-	++bullets->bulletsCount;
-
-	// Reallocate.
-	bullets->bullets = (Bullet*)KF_REALLOCARRAY(
-		bullets->bullets, 
-		bullets->bulletsCount,
-		sizeof(Bullet)
-	);
-
-	if (bullets->bullets == NULL) {
-		ALLOCATION_ERROR;
-		return KFERROR;
-	}
-	
-	bullets->bullets[bullets->bulletsCount - 1] = bullet;
-	return KFSUCCESS;
-}
-
-KfError popBackBullets(Bullets * bullets) {
-	if (bullets->bullets == NULL)
-		return KFSUCCESS;
-
-	// At one.
-	if (bullets->bulletsCount == 1) {
-		KF_FREE(bullets->bullets);
-		bullets->bullets = NULL;
-		bullets->bulletsCount = 0;
-		return KFSUCCESS;
-	}
-
-	--bullets->bulletsCount;
-
-	// Reallocate.
-	bullets->bullets = (Bullet*)KF_REALLOCARRAY(
-		bullets->bullets, 
-		bullets->bulletsCount,
-		sizeof(Bullet)
-	);
-
-	if (bullets->bullets == NULL) {
-		ALLOCATION_ERROR;
-		return KFERROR;
-	}
-
-	return KFSUCCESS;
 }
 
-void updateBullets(Game * game, Bullets * bullets) {
-	int i;
-	Bullet * last = NULL;
-
-	if (bullets->bullets == NULL)
-		return;
-
-	// Update each bullet.
-	for (i = 0; i < bullets->bulletsCount; ++i)
-		updateBullet(game, &bullets->bullets[i]);
-
-	// Remove end if hit or out of bounds.
-	last = &bullets->bullets[bullets->bulletsCount - 1];
+BulletHitInfo handleBulletHit(Entity * entity, Bullet bullet) {
+	// Handle health.
+	entity->health -= bullet.damage;
+	entity->health = Clamp(entity->health, ENTITY_MIN_HEALTH, ENTITY_MAX_HEALTH);
+
+	// Check hit info.
+	BulletHitInfo hitInfo = (BulletHitInfo){
+		.hit = true,
+		.killed = entity->health == 0.0,
+		.hitId = entity->id,
+		.hitFingerprint = entity->fingerprint
+	};
 
-	if (last->hit)
-		popBackBullets(bullets);
-	else if (Vector3Length(last->ray.position) >= GAME_BOUNDS)
-		popBackBullets(bullets);
+	return hitInfo;
 }
 
-void updateBullet(Game * game, Bullet * bullet) {
+BulletHitInfo shootBullet(World * world, Bullet bullet) {
 	int i, j;
 	RayCollision collision;
-	Ray ray;
 	Entity * currentEntity;
-
-	// Already hit.
-	if (bullet->hit)
-		return;
+	Ray ray;
 
 	// Set direction.
-	ray.direction = bullet->ray.direction;
+	ray.direction = bullet.ray.direction;
+
+	// Stores all the hits so we can find closest one.
+	int hits[world->entitiesCount];
+	size_t hitsSize = 0;
 
-	// Check collision.
-	for (i = 0; i < game->world.entitiesCount; ++i) {
-		currentEntity = &game->world.entities[i];
+	// Loop through entities.
+	for (i = 0; i < world->entitiesCount; ++i) {
+		currentEntity = &world->entities[i];
 
 		// This was the entity that shot it.
-		if (currentEntity->fingerprint == bullet->fromFingerprint)
+		if (currentEntity->fingerprint == bullet.fromFingerprint)
 			continue;
 		else if (currentEntity->model == NULL) // Null model indeed.
 			continue;
 
 		// Set position relative to entity.
-		ray.position = Vector3Subtract(bullet->ray.position, currentEntity->position);
+		ray.position = Vector3Subtract(bullet.ray.position, currentEntity->position);
 
 		// Loop through meshes.
 		for (j = 0; j < currentEntity->model->meshCount; ++j) {
@@ -143,23 +64,37 @@ void updateBullet(Game * game, Bullet * bullet) {
 			);
 
 			// Did hit.
-			if (!collision.hit)
-				continue;
-
-			currentEntity->health -= bullet->damage;
-			bullet->hit = true;
-			goto afterCollisionCheck;
+			if (collision.hit) {
+				hits[hitsSize] = i;
+				++hitsSize;
+				break;
+			}
 		}
 	}
 
-afterCollisionCheck:
-
-	// Update position.
-	bullet->ray.position = Vector3Add(
-		bullet->ray.position,
-		bullet->ray.direction
-	);
+	// No hits.
+	if (hitsSize == 0)
+		return (BulletHitInfo){
+			.hit = false,
+			.killed = false,
+			.hitId = ENTITY_NONE,
+		};
+
+	float dis = Vector3Distance(world->entities[hits[0]].position, bullet.ray.position);
+	float closest = dis;
+	int closestNum = 0;
+
+	// Find closest.
+	for (i = 0; i < hitsSize; ++i) {
+		dis = Vector3Distance(world->entities[hits[i]].position, bullet.ray.position);
+
+		// This fucker is closer.
+		if (dis < closest) {
+			closest = dis;
+			closestNum = i;
+		}
+	}
 
-	// Debug ray (:
-	//DrawRay(bullet->ray, BLUE);
+	// Handle closest bullet.
+	return handleBulletHit(&world->entities[hits[closestNum]], bullet);
 }
diff --git a/src/bullets.h b/src/bullets.h
index a01a967..eb6c15c 100644
--- a/src/bullets.h
+++ b/src/bullets.h
@@ -1,34 +1,29 @@
 #include "gameCommon.h"
 #include "entity.h"
+#include "world.h"
 
 #ifndef BULLET_H
 #define BULLET_H
 
 // Just a simple, deadly, bullet.
 typedef struct Bullet {
-	bool hit;
 	Ray ray;
 	EntityId fromId;
-	EntityFingerprint fromFingerprint; // Shooter gets shot before bullet hits object hehe.
+	EntityFingerprint fromFingerprint;
 	float damage;
 } Bullet;
 
-// All the simple, deadly, bullets.
-typedef struct Bullets {
-	Bullet * bullets;
-	size_t bulletsCount;
-} Bullets;
-
-// Create the simple, deadly, bullet. offset is the bullet offset from the entity.
-Bullet createBullet(Entity entity, Vector3 direction, Vector3 offset, float damage);
-
-void initBullets(Bullets * bullets);
-void freeBullets(Bullets * bullets);
+typedef struct BulletHitInfo {
+	bool hit;
+	bool killed;
+	EntityId hitId;
+	EntityFingerprint hitFingerprint;
+} BulletHitInfo;
 
-KfError addBullet(Bullets * bullets, Bullet bullet);
-KfError popBackBullets(Bullets * bullets);
+// Uses entity postion and direction to create bullet ray.
+Bullet createBulletFromEntity(Entity entity, float damage);
 
-void updateBullets(Game * game, Bullets * bullets);
-void updateBullet(Game * game, Bullet * bullet);
+// Shoot this fucker.
+BulletHitInfo shootBullet(World * world, Bullet bullet);
 
 #endif
diff --git a/src/entities/antifaShip.c b/src/entities/antifaShip.c
index 2d58510..1b90ea7 100644
--- a/src/entities/antifaShip.c
+++ b/src/entities/antifaShip.c
@@ -44,19 +44,15 @@ void controlAntifaShipJoystick(Game * game, Entity * entity) {
 
 	// Shoot button.
 	if (IsGamepadButtonPressed(gamePadNum, 8)) {
-		Vector3 dir = Vector3Normalize(Vector3Subtract(
-			getEntityFromWorld(game->world, 1)->position, 
-			entity->position
-		));
-
-		Bullet bullet = createBullet(
-			*entity,
-			dir,
-			Vector3Zero(),
-			0.1
-		);
-
-		addBullet(&game->bullets, bullet);
+		Bullet bullet = createBulletFromEntity(*entity, 1.0);
+		BulletHitInfo info = shootBullet(&game->world, bullet);
+
+		if (info.hit) {
+			Entity * hitEntity = getEntityFromWorld(game->world, info.hitId);
+			printVector3(hitEntity->position);
+		} else {
+			puts("no stink");
+		}
 	}
 
 	Vector3 stick = (Vector3){
diff --git a/src/entity.c b/src/entity.c
index 285744d..9c6e5e3 100644
--- a/src/entity.c
+++ b/src/entity.c
@@ -60,7 +60,8 @@ Entity createEntity(EntityType type, Game * game) {
 		.useAcceleration = false,
 		.updateCb = info.updateCb,
 		.drawCb = info.drawCb,
-		.health = 1.0,
+		.health = ENTITY_MAX_HEALTH,
+		.collision.hit = false,
 		.data = NULL
 	};
 
@@ -74,6 +75,28 @@ void closeEntity(Entity * entity) {
 	entityTypeInfo[entity->type].closeCb(entity);
 }
 
+bool entitiesCollide(Entity entity1, Entity entity2) {
+	int i;
+	Vector3 triangle[3];
+
+	/*
+	for (i = 0; i < mesh.triangleCount; ++i) {
+
+		for (j = 0; j < 3; ++j)
+			triangle[j] = (Vector3){
+				mesh.vertices[(i * 9) + (j * 3)],
+				mesh.vertices[(i * 9) + (j * 3) + 1],
+				mesh.vertices[(i * 9) + (j * 3) + 2],
+			};
+
+		DrawLine3D(triangle[0], triangle[1], BLUE);
+		DrawLine3D(triangle[1], triangle[2], BLUE);
+		DrawLine3D(triangle[2], triangle[0], BLUE);
+	}
+	*/
+	return false;
+}
+
 // Basic wireframe drawing.
 void entityDraw(Entity * entity) {
 	entity->model->transform = QuaternionToMatrix(entity->rotation);
@@ -81,7 +104,7 @@ void entityDraw(Entity * entity) {
 	DrawModelWires(
 		*entity->model,
 		entity->position,
-		1,
+		1.0,
 		GREEN
 	);
 }
@@ -107,6 +130,7 @@ void entityUpdateRotation(Entity * entity) {
 	);
 
     entity->rotation = QuaternionMultiply(entity->rotation, angularRotation);
+	entity->rotation = QuaternionNormalize(entity->rotation);
 }
 
 void entityJoystickControl(Entity * entity, Vector3 stick, float speed) {
diff --git a/src/entity.h b/src/entity.h
index dc6be72..844386c 100644
--- a/src/entity.h
+++ b/src/entity.h
@@ -45,11 +45,23 @@ typedef struct EntityVelocity {
 
 EntityVelocity entityVelocityIdentity();
 
+// This fucker hit something.
+typedef struct EntityCollision {
+	bool hit;
+	EntityId fromId;
+	EntityFingerprint fromFingerprint;
+} EntityCollision;
+
+// Health stuff.
+#define ENTITY_MIN_HEALTH 0.0
+#define ENTITY_MAX_HEALTH 1.0
+
 // This fucker is a entity.
 typedef struct Entity {
 	EntityId id;
 	EntityFingerprint fingerprint;
 	EntityType type;
+
 	Model * model;
 
 	Vector3 position;
@@ -67,6 +79,8 @@ typedef struct Entity {
 	// Health is a percent from 1.0 to 0.0.
 	float health;
 
+	EntityCollision collision;
+
 	// Used for whatever.
 	void * data;
 } Entity;
@@ -88,6 +102,8 @@ const extern EntityTypeInfo entityTypeInfo[ENTITY_TYPE_COUNT];
 Entity createEntity(EntityType type, Game * game);
 void closeEntity(Entity * entity);
 
+bool entitiesCollide(Entity entity1, Entity entity2);
+
 // Helper functions for updating and drawing.
 void entityDraw(Entity * entity);
 void entityUpdatePosition(Entity * entity);
diff --git a/src/game.c b/src/game.c
index 5bf35c4..5141270 100644
--- a/src/game.c
+++ b/src/game.c
@@ -19,19 +19,19 @@ void initGame(Game * game) {
 
 	// Camera.
 	initPlayerCamera(&game->playerCamera);
-
-	// Bullets.
-	initBullets(&game->bullets);
 	
 	// World.
 	initWorld(&game->world);
 
 	// Debug.
-	WorldEntry entries[] = {
-		(WorldEntry){ENTITY_ANTIFA, Vector3Zero(), QuaternionIdentity()},
-		(WorldEntry){ENTITY_SOLDATO, (Vector3){0.0, 0.0, 10.0}, QuaternionIdentity()}
+	WorldEntry entries[101] = {
+		(WorldEntry){ENTITY_ANTIFA, Vector3Zero(), QuaternionIdentity()},	
 	};
 
+	for (int i = 1; i < 101; ++i) {
+		entries[i] = (WorldEntry){ENTITY_CAPORALE, (Vector3){0.0, 0.0, i*10}, QuaternionIdentity()};
+	}
+
 	addEntriesToWorld(
 		&game->world,
 		game,
@@ -42,7 +42,6 @@ void initGame(Game * game) {
 
 void closeGame(Game * game) {
 	unloadAssets(&game->assets);
-	freeBullets(&game->bullets);
 	freeWorld(&game->world);
 
 	// Close window last.
diff --git a/src/game.h b/src/game.h
index 555b5b4..063a1cc 100644
--- a/src/game.h
+++ b/src/game.h
@@ -24,7 +24,6 @@ typedef struct Game {
 	Assets assets;
 	World world;
 	Settings settings;
-	Bullets bullets;
 } Game;
 
 void initGame(Game * game);
diff --git a/src/gameScreen.c b/src/gameScreen.c
index 286a026..65b020c 100644
--- a/src/gameScreen.c
+++ b/src/gameScreen.c
@@ -3,27 +3,46 @@
 #include "world.h"
 #include "bullets.h"
 
+void drawCrossHair(float size, float thick, Color color) {
+	Vector3 center = (Vector3){GetScreenWidth() / 2.0, GetScreenHeight() / 2.0};
+
+	// Left to right.
+	DrawLineEx(
+		(Vector2){center.x - size, center.y},
+		(Vector2){center.x + size, center.y},
+		thick,
+		color
+	);
+
+	// Top to bottom.
+	DrawLineEx(
+		(Vector2){center.x, center.y - size},
+		(Vector2){center.x, center.y + size},
+		thick,
+		color
+	);
+}
+
 void updateGameScreen(Game * game) {
+	ClearBackground(BLACK);
+
+	// Draw cross hair.
+	drawCrossHair(10.0, 2.0, BLUE);
 
 	// Update world.
 	updateWorld(&game->world, game);
 
-	ClearBackground(BLACK);
-
 	// Camera.
 	updatePlayerCamera(&game->playerCamera, game);
 
+	// Draw.
 	BeginMode3D(game->playerCamera);
 
 	DrawGrid(50, 25.0);
 
-	//DrawSphereWires(Vector3Zero(), GAME_BOUNDS, 32, 32, WHITE);
-
 	// Draw world.
 	drawWorld(&game->world, game);
 
-	updateBullets(game, &game->bullets);
-
 	EndMode3D();
 }
 
diff --git a/src/playerCamera.c b/src/playerCamera.c
index ded59b7..6b165f3 100644
--- a/src/playerCamera.c
+++ b/src/playerCamera.c
@@ -12,25 +12,18 @@ void initPlayerCamera(Camera3D * camera) {
 void updatePlayerCamera(Camera3D * camera, Game * game) {
 	Entity * player = getEntityFromWorld(game->world, 0);
 
-	camera->target = player->position;
+	Vector3 direction = Vector3RotateByQuaternion((Vector3){0.0, 0.0, 1.0}, player->rotation);
 
-	Matrix m = QuaternionToMatrix(QuaternionInvert(player->rotation));
-	Vector3 pos = (Vector3){0.0, CAMERA_DIS/2, -CAMERA_DIS};
+	// Position.
+	camera->position = Vector3Add(player->position, Vector3Scale(direction, CAMERA_DIS));
 
-	camera->position = (Vector3){
-		m.m0 * pos.x + m.m1 * pos.y + m.m2 * pos.z,
-		m.m4 * pos.x + m.m5 * pos.y + m.m6 * pos.z,
-		m.m8 * pos.x + m.m9 * pos.y + m.m10 * pos.z
-	};
-
-	camera->position = Vector3Add(camera->position, player->position);
+	// Target.
+	camera->target = Vector3Add(camera->position, direction);
 
-	camera->up = (Vector3){
-		m.m1 + m.m2,
-		m.m5 + m.m6,
-		m.m9 + m.m10
-	};
+	// Up.
+	camera->up = Vector3RotateByQuaternion((Vector3){0.0, 1.0, 0.0}, player->rotation);
 
-	camera->position = (Vector3){20.0, 20.0, 20.0};
-	camera->up = (Vector3){0.0, 1.0, 0.0};
+	//camera->target = player->position;
+	//camera->position = (Vector3){10.0, 10.0, 10.0};
+	//camera->up = (Vector3){0.0, 1.0, 0.0};
 }
diff --git a/src/playerCamera.h b/src/playerCamera.h
index 960c30d..87663d4 100644
--- a/src/playerCamera.h
+++ b/src/playerCamera.h
@@ -3,7 +3,7 @@
 #ifndef PLAYER_CAMERA_H
 #define PLAYER_CAMERA_H
 
-#define CAMERA_DIS 10.0
+#define CAMERA_DIS 5.0
 
 void initPlayerCamera(Camera3D * camera);
 void updatePlayerCamera(Camera3D * camera, Game * game);
diff --git a/src/world.c b/src/world.c
index 3bc02cd..553f2ed 100644
--- a/src/world.c
+++ b/src/world.c
@@ -225,17 +225,69 @@ KfError removeEntityFromWorld(World * world, EntityId id) {
 	return KFSUCCESS;
 }
 
+void checkCollisionWithWorld(World * world, Entity * entity) {
+	int i, j;
+	Entity * entity2;
+	BoundingBox box1, box2;
+
+	Mesh mesh = entity->model->meshes[0];
+
+	Vector3 triangle[3];
+
+	for (i = 0; i < mesh.triangleCount; ++i) {
+
+		for (j = 0; j < 3; ++j)
+			triangle[j] = (Vector3){
+				mesh.vertices[(i * 9) + (j * 3)],
+				mesh.vertices[(i * 9) + (j * 3) + 1],
+				mesh.vertices[(i * 9) + (j * 3) + 2],
+			};
+
+		DrawLine3D(triangle[0], triangle[1], BLUE);
+		DrawLine3D(triangle[1], triangle[2], BLUE);
+		DrawLine3D(triangle[2], triangle[0], BLUE);
+	}
+
+	// Check for collision.
+	//for (i = 0; i < world->entitiesCount; ++i) {
+	//	entity2 = &world->entities[i];
+
+	//	if (entity->fingerprint == entity2->fingerprint)
+	//		continue;
+
+	//	// These fuckers collided.
+	//	if (CheckCollisionBoxes(box1, box2)) {
+	//		printf("hi %ld\n", clock());
+	//		break;
+	//	}
+	//}
+}
+
 void updateWorld(World * world, Game * game) {
 	int i;
 	Entity * entity;
 
+	// People are fucking dying.
+	EntityId kills[world->entitiesCount];
+	size_t killCount = 0;
+
 	for (i = 0; i < world->entitiesCount; ++i) {
 		entity = &world->entities[i];
 
 		// Call update callback.
 		if (entity->updateCb != NULL)
 			entity->updateCb(game, entity);
+
+		// It fucking died.
+		if (entity->health <= 0.0) {
+			kills[killCount] = entity->id;
+			++killCount;
+		}
 	}
+
+	// "bring out your dead!"
+	for (i = 0; i < killCount; ++i)
+		removeEntityFromWorld(world, kills[i]);
 }
 
 void drawWorld(World * world, Game * game) {
@@ -245,6 +297,8 @@ void drawWorld(World * world, Game * game) {
 	for (i = 0; i < world->entitiesCount; ++i) {
 		entity = &world->entities[i];
 
+		//checkCollisionWithWorld(world, entity);
+
 		// Call draw callback.
 		if (entity->drawCb != NULL)
 			entity->drawCb(game, entity);
-- 
cgit v1.2.3