Add FSM to player movement
parent
0a3fefb194
commit
6540e27b0e
|
@ -1,4 +1,4 @@
|
||||||
*
|
Make*
|
||||||
!*.c
|
main.code-workspace
|
||||||
!*.h
|
main
|
||||||
!.gitignore
|
.vscode
|
||||||
|
|
|
@ -2,12 +2,37 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define BEZIER_POINTS 10
|
#define BEZIER_POINTS 10
|
||||||
|
#define LEFT KEY_LEFT
|
||||||
|
#define RIGHT KEY_RIGHT
|
||||||
|
#define JUMP KEY_SPACE
|
||||||
|
#define DASH KEY_Z
|
||||||
|
|
||||||
struct kinematic_obj
|
struct kinematic_obj
|
||||||
{
|
{
|
||||||
Rectangle rect;
|
Rectangle rect;
|
||||||
Vector2 velocity;
|
Vector2 velocity;
|
||||||
Color color;
|
};
|
||||||
|
|
||||||
|
enum PLAYER_STATE
|
||||||
|
{
|
||||||
|
IDLE = 0,
|
||||||
|
JUMP_SQUAT,
|
||||||
|
JUMPING,
|
||||||
|
FALLING,
|
||||||
|
LANDING,
|
||||||
|
DASH_START,
|
||||||
|
DASHING,
|
||||||
|
DASH_END,
|
||||||
|
RUN_START,
|
||||||
|
RUNNING,
|
||||||
|
RUN_END,
|
||||||
|
TURN_AROUND
|
||||||
|
};
|
||||||
|
|
||||||
|
struct player_obj
|
||||||
|
{
|
||||||
|
struct kinematic_obj kinematic;
|
||||||
|
enum PLAYER_STATE state;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct squishy_square
|
struct squishy_square
|
||||||
|
@ -51,7 +76,15 @@ Vector2 dir(Vector2 vec);
|
||||||
|
|
||||||
// Linked list, linked_list.c
|
// Linked list, linked_list.c
|
||||||
|
|
||||||
|
|
||||||
// Squishy Square functions, squishy.c
|
// Squishy Square functions, squishy.c
|
||||||
struct squishy_square init_squishy_square(Rectangle *rect, Color color);
|
struct squishy_square init_squishy_square(Rectangle *rect, Color color);
|
||||||
void update_squishy(struct squishy_square *square);
|
void update_squishy(struct squishy_square *square);
|
||||||
void draw_squishy(struct squishy_square *square);
|
void draw_squishy(struct squishy_square *square);
|
||||||
|
|
||||||
|
//Player stuff, player.c
|
||||||
|
struct player_obj init_player_obj();
|
||||||
|
void player_input_check(struct player_obj *player);
|
||||||
|
|
||||||
|
//Debug stuff, debug.c
|
||||||
|
void state_string(char *str, enum PLAYER_STATE state);
|
44
main.c
44
main.c
|
@ -23,13 +23,16 @@
|
||||||
struct obj_node *HEAD;
|
struct obj_node *HEAD;
|
||||||
int PLAYER_ACCEL = 1500;
|
int PLAYER_ACCEL = 1500;
|
||||||
int JUMP_ACCEL = 15000;
|
int JUMP_ACCEL = 15000;
|
||||||
int GRAV = 750;
|
int JUMP_SPD = 350;
|
||||||
|
int GRAV = 1000;
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
// Initialization
|
// Initialization
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
const int screenWidth = 800;
|
const int screenWidth = 800;
|
||||||
const int screenHeight = 450;
|
const int screenHeight = 450;
|
||||||
|
char current_state[20];
|
||||||
|
char current_spd[50];
|
||||||
|
|
||||||
InitWindow(screenWidth, screenHeight, "raylib");
|
InitWindow(screenWidth, screenHeight, "raylib");
|
||||||
|
|
||||||
|
@ -38,16 +41,19 @@ int main()
|
||||||
camera.rotation = 0.0f;
|
camera.rotation = 0.0f;
|
||||||
camera.zoom = 1.0f;
|
camera.zoom = 1.0f;
|
||||||
|
|
||||||
struct kinematic_obj player = init_kinematic_obj(40, 40);
|
struct player_obj player = {
|
||||||
player.color = BLUE;
|
.kinematic = init_kinematic_obj(40, 40),
|
||||||
|
.state = IDLE
|
||||||
|
};
|
||||||
|
|
||||||
struct kinematic_obj tile = init_kinematic_obj(900, 100);
|
struct kinematic_obj tile = init_kinematic_obj(900, 100);
|
||||||
set_position(&player, 400, 300);
|
set_position(&player, 400, 300);
|
||||||
set_position(&tile, -50, 380);
|
set_position(&tile, -50, 380);
|
||||||
struct squishy_square sqr = init_squishy_square(&player.rect, RED);
|
struct squishy_square sqr = init_squishy_square(&player.kinematic.rect, RED);
|
||||||
|
|
||||||
// TODO: get a linked list implementation
|
// TODO: get a linked list implementation
|
||||||
struct obj_node tile_node = {.obj=&tile, .next=NULL};
|
struct obj_node tile_node = {.obj=&tile, .next=NULL};
|
||||||
struct obj_node player_node = {.obj=&player, .next=&tile_node};
|
struct obj_node player_node = {.obj=&player.kinematic, .next=&tile_node};
|
||||||
HEAD = &player_node;
|
HEAD = &player_node;
|
||||||
|
|
||||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
|
@ -58,26 +64,10 @@ int main()
|
||||||
{
|
{
|
||||||
// Update
|
// Update
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
//UpdateCamera(&camera);
|
|
||||||
Vector2 accel = (Vector2){
|
|
||||||
.x = PLAYER_ACCEL*(IsKeyDown(KEY_RIGHT)-IsKeyDown(KEY_LEFT)),
|
|
||||||
.y = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!place_meeting(&player, (Vector2){0,1})){
|
player_input_check(&player);
|
||||||
accel.y = GRAV;
|
|
||||||
}
|
|
||||||
accel.x -= player.velocity.x * 6.5;
|
|
||||||
|
|
||||||
if (IsKeyDown(KEY_SPACE) && place_meeting(&player, (Vector2){0,1}))
|
|
||||||
accel.y -= JUMP_ACCEL;
|
|
||||||
move(&player, accel);
|
|
||||||
|
|
||||||
update_squishy(&sqr);
|
update_squishy(&sqr);
|
||||||
Vector2 center = (Vector2){
|
|
||||||
.x = (sqr.topleft.x + sqr.topright.x)/2,
|
|
||||||
.y = (sqr.topleft.y + sqr.bottomleft.y)/2
|
|
||||||
};
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
|
@ -85,15 +75,19 @@ int main()
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
|
|
||||||
ClearBackground(RAYWHITE);
|
ClearBackground(RAYWHITE);
|
||||||
|
draw_squishy(&sqr);
|
||||||
|
|
||||||
BeginMode2D(camera);
|
BeginMode2D(camera);
|
||||||
current = HEAD;
|
current = HEAD;
|
||||||
while(current){
|
while(current){
|
||||||
DrawRectangleRec(current->obj->rect, current->obj->color);
|
DrawRectangleLinesEx(current->obj->rect, 1, BLACK);
|
||||||
current = current->next;
|
current = current->next;
|
||||||
}
|
}
|
||||||
DrawFPS(100,100);
|
DrawFPS(0,0);
|
||||||
draw_squishy(&sqr);
|
state_string(current_state, player.state);
|
||||||
|
DrawText(current_state, 250, 0, 12, BLACK);
|
||||||
|
sprintf(current_spd, "Velocity: {%.2f,%.2f}", player.kinematic.velocity.x,player.kinematic.velocity.y);
|
||||||
|
DrawText(current_spd, 350, 0, 12, BLACK);
|
||||||
EndMode2D();
|
EndMode2D();
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
struct kinematic_obj init_kinematic_obj(int width, int height){
|
struct kinematic_obj init_kinematic_obj(int width, int height){
|
||||||
struct kinematic_obj obj = {
|
struct kinematic_obj obj = {
|
||||||
.velocity = {0.0f,0.0f},
|
.velocity = {0.0f,0.0f},
|
||||||
.rect = {0,0,width,height},
|
.rect = {0,0,width,height}
|
||||||
.color = BLACK
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
#include "header.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define PLAYER_ACCEL 1500
|
||||||
|
#define RUN_INIT_SPD 200
|
||||||
|
#define JUMP_SPD 500
|
||||||
|
#define GRAV 1000
|
||||||
|
|
||||||
|
static bool allow_move = true;
|
||||||
|
static int jumps = 1;
|
||||||
|
static frame_counter = 0;
|
||||||
|
static int run_dir = 1;
|
||||||
|
static bool allow_friction = true;
|
||||||
|
const unsigned int run_start_frames = 8;
|
||||||
|
const unsigned int jump_squat_frames = 6;
|
||||||
|
const unsigned int land_lag_frames = 5;
|
||||||
|
|
||||||
|
// The player FSM
|
||||||
|
void player_input_check(struct player_obj *player){
|
||||||
|
Vector2 accel = (Vector2){
|
||||||
|
.x = 0,
|
||||||
|
.y = 0
|
||||||
|
};
|
||||||
|
switch(player->state){
|
||||||
|
case IDLE:
|
||||||
|
if (IsKeyDown(LEFT) || IsKeyDown(RIGHT)){
|
||||||
|
player->state = RUN_START;
|
||||||
|
allow_friction = false;
|
||||||
|
player->kinematic.velocity.x = (IsKeyDown(KEY_RIGHT)-IsKeyDown(KEY_LEFT)) * RUN_INIT_SPD;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RUN_START:
|
||||||
|
run_dir = sign(player->kinematic.velocity.x);
|
||||||
|
// Run Opposite Direction
|
||||||
|
if ((IsKeyPressed(LEFT) && run_dir == 1) || (IsKeyPressed(RIGHT) && run_dir == -1)){
|
||||||
|
frame_counter = 0;
|
||||||
|
player->kinematic.velocity.x *= -1;
|
||||||
|
}else{
|
||||||
|
// Complete the run startup
|
||||||
|
if(frame_counter<run_start_frames)
|
||||||
|
++frame_counter;
|
||||||
|
else{
|
||||||
|
frame_counter = 0;
|
||||||
|
allow_friction = true;
|
||||||
|
player->state = RUNNING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RUNNING:
|
||||||
|
run_dir = sign(player->kinematic.velocity.x);
|
||||||
|
if ((IsKeyPressed(LEFT) && run_dir == 1) || (IsKeyPressed(RIGHT) && run_dir == -1)){
|
||||||
|
player->state = RUN_END;
|
||||||
|
}else{
|
||||||
|
if (!IsKeyDown(LEFT) && !IsKeyDown(RIGHT)){
|
||||||
|
player->state = RUN_END;
|
||||||
|
}else{
|
||||||
|
accel.x = PLAYER_ACCEL*(IsKeyDown(KEY_RIGHT)-IsKeyDown(KEY_LEFT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RUN_END:
|
||||||
|
if(player->kinematic.velocity.x < 10 && player->kinematic.velocity.x > -10){
|
||||||
|
if(IsKeyDown(LEFT) || IsKeyDown(RIGHT)){
|
||||||
|
player->state = RUNNING;
|
||||||
|
}else{
|
||||||
|
player->state = IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TURN_AROUND:
|
||||||
|
|
||||||
|
break;
|
||||||
|
case JUMP_SQUAT:
|
||||||
|
if(frame_counter<jump_squat_frames)
|
||||||
|
++frame_counter;
|
||||||
|
else{
|
||||||
|
frame_counter = 0;
|
||||||
|
if (IsKeyDown(JUMP))
|
||||||
|
player->kinematic.velocity.y = -JUMP_SPD;
|
||||||
|
else
|
||||||
|
player->kinematic.velocity.y = -JUMP_SPD/2;
|
||||||
|
player->state = JUMPING;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JUMPING:
|
||||||
|
accel.x = PLAYER_ACCEL*(IsKeyDown(KEY_RIGHT)-IsKeyDown(KEY_LEFT));
|
||||||
|
if (player->kinematic.velocity.y > 0)
|
||||||
|
player->state = FALLING;
|
||||||
|
break;
|
||||||
|
case FALLING:
|
||||||
|
accel.x = PLAYER_ACCEL*(IsKeyDown(KEY_RIGHT)-IsKeyDown(KEY_LEFT));
|
||||||
|
if (place_meeting(&player->kinematic, (Vector2){0,1})){
|
||||||
|
player->state = LANDING;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LANDING:
|
||||||
|
if(frame_counter<land_lag_frames)
|
||||||
|
++frame_counter;
|
||||||
|
else{
|
||||||
|
jumps = 1;
|
||||||
|
frame_counter = 0;
|
||||||
|
if (IsKeyDown(LEFT) || IsKeyDown(RIGHT)){
|
||||||
|
player->state = RUNNING;
|
||||||
|
}else{
|
||||||
|
player->state = IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DASH_START:
|
||||||
|
|
||||||
|
break;
|
||||||
|
case DASHING:
|
||||||
|
|
||||||
|
break;
|
||||||
|
case DASH_END:
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsKeyPressed(JUMP) && jumps > 0){
|
||||||
|
player->state = JUMP_SQUAT;
|
||||||
|
allow_friction = true;
|
||||||
|
--jumps;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allow_friction == true)
|
||||||
|
accel.x -= player->kinematic.velocity.x * 8;
|
||||||
|
|
||||||
|
if (!place_meeting(&player, (Vector2){0,1})){
|
||||||
|
accel.y = GRAV;
|
||||||
|
}
|
||||||
|
|
||||||
|
move(&player->kinematic, accel);
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include "header.h"
|
||||||
|
|
||||||
|
void state_string(char *str, enum PLAYER_STATE state){
|
||||||
|
switch(state){
|
||||||
|
case IDLE: sprintf(str, "%s", "IDLE");break;
|
||||||
|
case JUMP_SQUAT: sprintf(str, "%s", "JUMP_SQUAT");break;
|
||||||
|
case JUMPING: sprintf(str, "%s", "JUMPING");break;
|
||||||
|
case FALLING: sprintf(str, "%s", "FALLING");break;
|
||||||
|
case LANDING: sprintf(str, "%s", "LANDING");break;
|
||||||
|
case DASH_START: sprintf(str, "%s", "DASH_START");break;
|
||||||
|
case DASHING: sprintf(str, "%s", "DASHING");break;
|
||||||
|
case DASH_END: sprintf(str, "%s", "DASH_END");break;
|
||||||
|
case RUN_START: sprintf(str, "%s", "RUN_START");break;
|
||||||
|
case RUNNING: sprintf(str, "%s", "RUNNING");break;
|
||||||
|
case RUN_END: sprintf(str, "%s", "RUN_END");break;
|
||||||
|
case TURN_AROUND: sprintf(str, "%s", "TURN_AROUND");break;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue