diff options
author | nathansmithsmith <thenathansmithsmith@gmail.com> | 2023-07-18 05:54:30 -0600 |
---|---|---|
committer | nathansmithsmith <thenathansmithsmith@gmail.com> | 2023-07-18 05:54:30 -0600 |
commit | f3f5fedbf591c10fa675a32103bab9480b42abe8 (patch) | |
tree | 54b46a23279cc45091393762c0d01b9c3637b729 /src | |
parent | 77a06748f9f394486cad833e2ca351e8dbcc7361 (diff) |
Bullet system added
Diffstat (limited to 'src')
-rw-r--r-- | src/bullets.c | 165 | ||||
-rw-r--r-- | src/bullets.h | 34 | ||||
-rw-r--r-- | src/entities/antifaShip.c | 20 | ||||
-rw-r--r-- | src/entities/soldato.c | 23 | ||||
-rw-r--r-- | src/entities/soldato.h | 2 | ||||
-rw-r--r-- | src/entity.c | 40 | ||||
-rw-r--r-- | src/entity.h | 26 | ||||
-rw-r--r-- | src/game.c | 4 | ||||
-rw-r--r-- | src/game.h | 2 | ||||
-rw-r--r-- | src/gameCommon.h | 3 | ||||
-rw-r--r-- | src/gameScreen.c | 7 |
11 files changed, 302 insertions, 24 deletions
diff --git a/src/bullets.c b/src/bullets.c new file mode 100644 index 0000000..10116c2 --- /dev/null +++ b/src/bullets.c @@ -0,0 +1,165 @@ +#include "bullets.h" +#include "game.h" + +Bullet createBullet(Entity entity, Vector3 direction, Vector3 offset, float damage) { + Bullet bullet = (Bullet){ + .hit = false, + .ray = (Ray){ + .position = Vector3Add(entity.position, offset), + .direction = direction, + }, + .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]; + + if (last->hit) + popBackBullets(bullets); + else if (Vector3Length(last->ray.position) >= GAME_BOUNDS) + popBackBullets(bullets); +} + +void updateBullet(Game * game, Bullet * bullet) { + int i, j; + RayCollision collision; + Ray ray; + Entity * currentEntity; + + // Already hit. + if (bullet->hit) + return; + + // Set direction. + ray.direction = bullet->ray.direction; + + // Check collision. + for (i = 0; i < game->world.entitiesCount; ++i) { + currentEntity = &game->world.entities[i]; + + // This was the entity that shot it. + 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); + + // Loop through meshes. + for (j = 0; j < currentEntity->model->meshCount; ++j) { + collision = GetRayCollisionMesh( + ray, + currentEntity->model->meshes[j], + currentEntity->model->transform + ); + + // Did hit. + if (!collision.hit) + continue; + + currentEntity->health -= bullet->damage; + bullet->hit = true; + goto afterCollisionCheck; + } + } + +afterCollisionCheck: + + // Update position. + bullet->ray.position = Vector3Add( + bullet->ray.position, + bullet->ray.direction + ); + + // Debug ray (: + //DrawRay(bullet->ray, BLUE); +} diff --git a/src/bullets.h b/src/bullets.h new file mode 100644 index 0000000..a01a967 --- /dev/null +++ b/src/bullets.h @@ -0,0 +1,34 @@ +#include "gameCommon.h" +#include "entity.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. + 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); + +KfError addBullet(Bullets * bullets, Bullet bullet); +KfError popBackBullets(Bullets * bullets); + +void updateBullets(Game * game, Bullets * bullets); +void updateBullet(Game * game, Bullet * bullet); + +#endif diff --git a/src/entities/antifaShip.c b/src/entities/antifaShip.c index c2e292a..2d58510 100644 --- a/src/entities/antifaShip.c +++ b/src/entities/antifaShip.c @@ -1,8 +1,7 @@ #include "antifaShip.h" #include "game.h" #include "settings.h" - -// TODO: Get rid of some magic numbers. +#include "bullets.h" void initAntifaShip(Entity * entity, Game * game) { entity->model = &game->assets.models[ANTIFA_SHIP_ASSET]; @@ -43,6 +42,23 @@ void controlAntifaShipJoystick(Game * game, Entity * entity) { float rollStick = GetGamepadAxisMovement(gamePadNum, settings.rollStick); float speedStick = GetGamepadAxisMovement(gamePadNum, settings.speedStick); + // 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); + } + Vector3 stick = (Vector3){ pitchStick, -yawStick, diff --git a/src/entities/soldato.c b/src/entities/soldato.c index 30dfa6b..beec40a 100644 --- a/src/entities/soldato.c +++ b/src/entities/soldato.c @@ -7,19 +7,19 @@ void initSoldato(Entity * entity, Game * game) { // Acceleration. entity->useAcceleration = true; entity->acceleration = (EntityAcceleration){ - .speedUp = 5.0, - .speedDown = 0.00001 + .speedUp = 20.0, + .speedDown = 15.0 }; // PID configs. PIDConfig speedPIDConfig = { - .kP = -0.5, + .kP = 1, .kI = 0.0, .kD = 0.0, .angleMode = false, .doClamp = true, .min = 0.0, - .max = 30.0 + .max = 100.0 }; // Allocate data. @@ -31,7 +31,15 @@ void initSoldato(Entity * entity, Game * game) { } Soldato * data = (Soldato*)entity->data; - data->speedPID = createPID(speedPIDConfig); + + // Create fly to point. + data->flyToPoint = (EntityFlyToPointInfo){ + //.controller.speedPID = createPID(speedPIDConfig), + .controller.bangbang.speed = 20.0, + .controller.bangbang.stopAt = 0.0, + .controlType = ENTITY_FLY_TO_POINT_BANG_BANG, + .rotationSpeed = 0.0 + }; } void closeSoldato(Entity * entity) { @@ -43,11 +51,10 @@ void updateSoldato(Game * game, Entity * entity) { Entity * player = getEntityFromWorld(game->world, 0); Soldato * data = (Soldato*)entity->data; - entityFlightToPoint( + entityFlyToPoint( entity, player->position, - &data->speedPID, - 5.0 + &data->flyToPoint ); } diff --git a/src/entities/soldato.h b/src/entities/soldato.h index 5123aee..f93206d 100644 --- a/src/entities/soldato.h +++ b/src/entities/soldato.h @@ -6,7 +6,7 @@ #define SOLDATO_H typedef struct Soldato { - PID speedPID; + EntityFlyToPointInfo flyToPoint; } Soldato; void initSoldato(Entity * entity, Game * game); diff --git a/src/entity.c b/src/entity.c index e918617..285744d 100644 --- a/src/entity.c +++ b/src/entity.c @@ -52,6 +52,7 @@ Entity createEntity(EntityType type, Game * game) { // Set defaults. Entity entity = (Entity){ .type = type, + .model = NULL, .position = Vector3Zero(), .rotation = QuaternionIdentity(), .velocity = entityVelocityIdentity(), @@ -59,6 +60,7 @@ Entity createEntity(EntityType type, Game * game) { .useAcceleration = false, .updateCb = info.updateCb, .drawCb = info.drawCb, + .health = 1.0, .data = NULL }; @@ -152,7 +154,7 @@ void entityJoystickControl(Entity * entity, Vector3 stick, float speed) { entityUpdatePosition(entity); } -void entityFlightToPoint(Entity * entity, Vector3 point, PID * speedPID, float rotationSpeed) { +void entityFlyToPoint(Entity * entity, Vector3 point, EntityFlyToPointInfo * info) { float t = GetFrameTime(); // Get distance and direction. @@ -164,19 +166,37 @@ void entityFlightToPoint(Entity * entity, Vector3 point, PID * speedPID, float r Quaternion rotation = QuaternionInvert(QuaternionFromMatrix(matrix)); // Rotate this fucker. - if (rotationSpeed == 0.0) + if (info->rotationSpeed == 0.0) entity->rotation = rotation; else - entity->rotation = QuaternionSlerp(entity->rotation, rotation, t * rotationSpeed); + entity->rotation = QuaternionSlerp(entity->rotation, rotation, t * info->rotationSpeed); // Velocity control. - float s = runPID(0.0, Vector3Length(dis), speedPID); + float speed = 0.0; + + float distance = Vector3Length(dis); + + switch (info->controlType) { + case ENTITY_FLY_TO_POINT_PID: + speed = runPID(0.0, -distance, &info->controller.speedPID); + break; + case ENTITY_FLY_TO_POINT_BANG_BANG: + speed = info->controller.bangbang.speed; + + if (distance <= info->controller.bangbang.stopAt) + speed = 0.0; + + break; + default: // Something is fucked up. + break; + } + Matrix m = QuaternionToMatrix(QuaternionInvert(entity->rotation)); // Accelerate. if (entity->useAcceleration) - s = accelerateValue( - s, + speed = accelerateValue( + speed, entity->lastVelocity.speed, entity->acceleration.speedUp * t, entity->acceleration.speedDown * t @@ -184,13 +204,13 @@ void entityFlightToPoint(Entity * entity, Vector3 point, PID * speedPID, float r // Velocity. entity->velocity.velocity = (Vector3){ - m.m2 * s, - m.m6 * s, - m.m10 * s + m.m2 * speed, + m.m6 * speed, + m.m10 * speed }; entityUpdatePosition(entity); - entity->velocity.speed = s; + entity->velocity.speed = speed; entity->lastVelocity = entity->velocity; } diff --git a/src/entity.h b/src/entity.h index c6fa6c6..dc6be72 100644 --- a/src/entity.h +++ b/src/entity.h @@ -64,6 +64,9 @@ typedef struct Entity { EntityUpdateCb updateCb; EntityDrawCb drawCb; + // Health is a percent from 1.0 to 0.0. + float health; + // Used for whatever. void * data; } Entity; @@ -92,7 +95,26 @@ void entityUpdateRotation(Entity * entity); void entityJoystickControl(Entity * entity, Vector3 stick, float speed); -// 0.0 rotationSpeed for directly setting the rotation. -void entityFlightToPoint(Entity * entity, Vector3 point, PID * speedPID, float rotationSpeed); +enum { + ENTITY_FLY_TO_POINT_PID, + ENTITY_FLY_TO_POINT_BANG_BANG +}; + +// Shit for fly to point. +typedef struct EntityFlyToPointInfo { + union { + PID speedPID; + + struct { + float speed; + float stopAt; + } bangbang; + } controller; + + uint8_t controlType; + float rotationSpeed; // 0.0 to not use. +} EntityFlyToPointInfo; + +void entityFlyToPoint(Entity * entity, Vector3 point, EntityFlyToPointInfo * info); #endif @@ -19,6 +19,9 @@ void initGame(Game * game) { // Camera. initPlayerCamera(&game->playerCamera); + + // Bullets. + initBullets(&game->bullets); // World. initWorld(&game->world); @@ -39,6 +42,7 @@ void initGame(Game * game) { void closeGame(Game * game) { unloadAssets(&game->assets); + freeBullets(&game->bullets); freeWorld(&game->world); // Close window last. @@ -6,6 +6,7 @@ #include "assets.h" #include "world.h" #include "settings.h" +#include "bullets.h" #ifndef GAME_H #define GAME_H @@ -23,6 +24,7 @@ typedef struct Game { Assets assets; World world; Settings settings; + Bullets bullets; } Game; void initGame(Game * game); diff --git a/src/gameCommon.h b/src/gameCommon.h index 08ce5fe..4c22664 100644 --- a/src/gameCommon.h +++ b/src/gameCommon.h @@ -19,6 +19,9 @@ typedef struct Game Game; typedef struct Entity Entity; +// How far from center you can go. +#define GAME_BOUNDS 1000.0 + #define WINDOW_WIDTH 960 #define WINDOW_HEIGHT 540 diff --git a/src/gameScreen.c b/src/gameScreen.c index 3282a8f..286a026 100644 --- a/src/gameScreen.c +++ b/src/gameScreen.c @@ -1,6 +1,7 @@ #include "gameScreen.h" #include "game.h" #include "world.h" +#include "bullets.h" void updateGameScreen(Game * game) { @@ -14,11 +15,15 @@ void updateGameScreen(Game * game) { BeginMode3D(game->playerCamera); - DrawGrid(500, 25.0); + DrawGrid(50, 25.0); + + //DrawSphereWires(Vector3Zero(), GAME_BOUNDS, 32, 32, WHITE); // Draw world. drawWorld(&game->world, game); + updateBullets(game, &game->bullets); + EndMode3D(); } |