Add FSM to player movement

master
En Yi 2019-11-25 22:20:06 +08:00
parent 0a3fefb194
commit 6540e27b0e
6 changed files with 211 additions and 33 deletions

8
.gitignore vendored
View File

@ -1,4 +1,4 @@
*
!*.c
!*.h
!.gitignore
Make*
main.code-workspace
main
.vscode

View File

@ -2,12 +2,37 @@
#include <stdio.h>
#define BEZIER_POINTS 10
#define LEFT KEY_LEFT
#define RIGHT KEY_RIGHT
#define JUMP KEY_SPACE
#define DASH KEY_Z
struct kinematic_obj
{
Rectangle rect;
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
@ -51,7 +76,15 @@ Vector2 dir(Vector2 vec);
// Linked list, linked_list.c
// Squishy Square functions, squishy.c
struct squishy_square init_squishy_square(Rectangle *rect, Color color);
void update_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);

46
main.c
View File

@ -23,13 +23,16 @@
struct obj_node *HEAD;
int PLAYER_ACCEL = 1500;
int JUMP_ACCEL = 15000;
int GRAV = 750;
int JUMP_SPD = 350;
int GRAV = 1000;
int main()
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
char current_state[20];
char current_spd[50];
InitWindow(screenWidth, screenHeight, "raylib");
@ -38,16 +41,19 @@ int main()
camera.rotation = 0.0f;
camera.zoom = 1.0f;
struct kinematic_obj player = init_kinematic_obj(40, 40);
player.color = BLUE;
struct player_obj player = {
.kinematic = init_kinematic_obj(40, 40),
.state = IDLE
};
struct kinematic_obj tile = init_kinematic_obj(900, 100);
set_position(&player, 400, 300);
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
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;
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
@ -58,26 +64,10 @@ int main()
{
// Update
//----------------------------------------------------------------------------------
//UpdateCamera(&camera);
Vector2 accel = (Vector2){
.x = PLAYER_ACCEL*(IsKeyDown(KEY_RIGHT)-IsKeyDown(KEY_LEFT)),
.y = 0
};
if (!place_meeting(&player, (Vector2){0,1})){
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);
player_input_check(&player);
update_squishy(&sqr);
Vector2 center = (Vector2){
.x = (sqr.topleft.x + sqr.topright.x)/2,
.y = (sqr.topleft.y + sqr.bottomleft.y)/2
};
update_squishy(&sqr);
//----------------------------------------------------------------------------------
// Draw
@ -85,15 +75,19 @@ int main()
BeginDrawing();
ClearBackground(RAYWHITE);
draw_squishy(&sqr);
BeginMode2D(camera);
current = HEAD;
while(current){
DrawRectangleRec(current->obj->rect, current->obj->color);
DrawRectangleLinesEx(current->obj->rect, 1, BLACK);
current = current->next;
}
DrawFPS(100,100);
draw_squishy(&sqr);
DrawFPS(0,0);
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();
EndDrawing();

View File

@ -3,8 +3,7 @@
struct kinematic_obj init_kinematic_obj(int width, int height){
struct kinematic_obj obj = {
.velocity = {0.0f,0.0f},
.rect = {0,0,width,height},
.color = BLACK
.rect = {0,0,width,height}
};
return obj;

134
obj/player.c 100644
View File

@ -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);
}

18
utilities/debug.c 100644
View File

@ -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;
}
}