spherecast

wip first person shooter engine
Download | Log | Files | Refs

player.c (3955B)


      1 #include <float.h>
      2 #include <raylib.h>
      3 #include <raymath.h>
      4 #include <stdint.h>
      5 #include <stdio.h>
      6 
      7 #include "config.h"
      8 #include "player.h"
      9 
     10 static PlayerIntent GetIntent(enum Input i) {
     11   return (PlayerIntent){
     12       .move = i & (INPUT_FORWARD | INPUT_BACKWARD | INPUT_LEFT | INPUT_RIGHT),
     13       .sprint = i & INPUT_SPRINT,
     14       .crouch = i & INPUT_CROUCH,
     15       .jump = i & INPUT_JUMP};
     16 }
     17 
     18 void PlayerApplyAcceleration(Player *p, enum Input i, float dt) {
     19   Vector3 forward = {sinf(p->rot.z), 0.0f, cosf(p->rot.z)};
     20 
     21   Vector3 right = {sinf(p->rot.z - PI / 2.0f), 0.0f,
     22                    cosf(p->rot.z - PI / 2.0f)};
     23 
     24   Vector3 input = Vector3Zero();
     25   if (i & INPUT_FORWARD)
     26     input.z += 1;
     27   if (i & INPUT_BACKWARD)
     28     input.z -= 1;
     29   if (i & INPUT_LEFT)
     30     input.x -= 1;
     31   if (i & INPUT_RIGHT)
     32     input.x += 1;
     33 
     34   if (Vector3Length(input) == 0.0f)
     35     return;
     36 
     37   Vector3 wishDir =
     38       Vector3Add(Vector3Scale(forward, input.z), Vector3Scale(right, input.x));
     39 
     40   wishDir = Vector3Normalize(wishDir);
     41 
     42   float currentSpeed = Vector3DotProduct(p->vel, wishDir);
     43 
     44   float addSpeed = p->maxSpeed - currentSpeed;
     45   if (addSpeed <= 0.0f)
     46     return;
     47 
     48   float accelSpeed = p->accel * p->maxSpeed * dt;
     49   if (accelSpeed > addSpeed)
     50     accelSpeed = addSpeed;
     51 
     52   p->vel = Vector3Add(p->vel, Vector3Scale(wishDir, accelSpeed));
     53 }
     54 
     55 /*
     56  * This function does nothing but set/unset player states
     57  */
     58 void PlayerUpdateMode(Player *p, PlayerIntent in) {
     59   switch (p->mode) {
     60 
     61   case MOVE_WALK:
     62     if (in.sprint) {
     63       p->mode = MOVE_SPRINT;
     64       break;
     65     }
     66 
     67     if (in.crouch) {
     68       p->mode = MOVE_CROUCH;
     69       break;
     70     }
     71 
     72     if (in.jump && p->grounded) {
     73       p->vel.y += JUMP_FORCE;
     74       break;
     75     }
     76     break;
     77 
     78   case MOVE_SPRINT:
     79     if (in.move && in.crouch && Vector3Length(p->vel) > 4.0f) {
     80       p->mode = MOVE_SLIDE;
     81       break;
     82     }
     83 
     84     if (!in.sprint) {
     85       p->mode = MOVE_WALK;
     86       break;
     87     }
     88 
     89     if (in.jump && p->grounded) {
     90       p->vel.y += JUMP_FORCE;
     91       break;
     92     }
     93 
     94     break;
     95 
     96   case MOVE_CROUCH:
     97     if (!in.crouch) {
     98       p->mode = MOVE_WALK;
     99       break;
    100     }
    101     break;
    102 
    103   case MOVE_SLIDE:
    104     if (!in.crouch || Vector3Length(p->vel) < 1.0f) {
    105       p->mode = MOVE_WALK;
    106       break;
    107     }
    108     break;
    109   }
    110 }
    111 
    112 void PlayerHandleMovement(Player *p, PlayerIntent in) {
    113   p->rot.x = 0;
    114   p->height = PLAYER_HEIGHT;
    115 
    116   switch (p->mode) {
    117 
    118   case MOVE_WALK:
    119     printf("STATE WALK\n");
    120     p->maxSpeed = WALK_SPEED;
    121     p->accel = WALK_ACCEL;
    122     break;
    123 
    124   case MOVE_SPRINT:
    125     printf("STATE SPRINT\n");
    126     p->maxSpeed = SPRINT_SPEED;
    127     p->accel = SPRINT_ACCEL;
    128     break;
    129 
    130   case MOVE_CROUCH:
    131     printf("STATE CROUCH\n");
    132     p->maxSpeed = CROUCH_SPEED;
    133     p->accel = CROUCH_ACCEL;
    134     p->height = PLAYER_HEIGHT / 2;
    135     break;
    136 
    137   case MOVE_SLIDE:
    138     printf("STATE SLIDE\n");
    139     p->maxSpeed = SLIDE_SPEED;
    140     p->accel = SLIDE_ACCEL;
    141     p->height = PLAYER_HEIGHT / 2;
    142     p->rot.x = PI / 24;
    143     break;
    144 
    145     if (!p->grounded) {
    146       p->maxSpeed = AIR_SPEED;
    147       p->accel = AIR_ACCEL;
    148     }
    149   }
    150 }
    151 
    152 void PlayerUpdate(Player *p, enum Input i, float dt) {
    153 
    154   p->groundedTimer = Clamp(p->groundedTimer - dt, 0, COYOTE_TIME);
    155   p->grounded = (p->groundedTimer > 0);
    156 
    157   PlayerIntent intent = GetIntent(i);
    158 
    159   PlayerUpdateMode(p, intent);
    160   PlayerHandleMovement(p, intent);
    161 }
    162 
    163 void PlayerApplyFriction(Player *p, float dt) {
    164   float friction = AIR_FRICTION;
    165   if (p->mode == MOVE_WALK || p->mode == MOVE_SPRINT || p->mode == MOVE_CROUCH)
    166     friction = GROUND_FRICTION;
    167 
    168   Vector3 horiz = {p->vel.x, 0, p->vel.z};
    169   float speed = Vector3Length(horiz);
    170 
    171   if (speed < STOP_SPEED) {
    172     p->vel = (Vector3){0, p->vel.y, 0};
    173     return;
    174   }
    175 
    176   float control = speed < STOP_SPEED ? STOP_SPEED : speed;
    177   float drop = control * friction * dt;
    178 
    179   float newSpeed = speed - drop;
    180   if (newSpeed < 0)
    181     newSpeed = 0;
    182 
    183   horiz = Vector3Scale(horiz, newSpeed / speed);
    184 
    185   p->vel.x = horiz.x;
    186   p->vel.z = horiz.z;
    187 }