Compare commits

..

6 Commits

3 changed files with 182 additions and 63 deletions

4
main.c
View File

@@ -22,7 +22,7 @@ int main() {
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
Player player = {0};
player_init(&player, renderer, (SDL_Rect){ .x = 50, .y = 100, .w = 100, .h = 64 });
player_init(&player, renderer, (SDL_Rect){ .x = 50, .y = 600, .w = 100, .h = 64 });
bool running = true;
@@ -31,8 +31,6 @@ int main() {
while (running) {
while (SDL_PollEvent(&event)) {
player_events(&player, &event);
switch (event.type) {
case SDL_QUIT:
running = false;

222
player.c
View File

@@ -1,21 +1,33 @@
#include "player.h"
#include "SDL_keycode.h"
#include "SDL_render.h"
#include "animation_player.h"
#include "state_machine.h"
#include <SDL2/SDL_events.h>
#include <SDL2/SDL_keyboard.h>
#include <SDL2/SDL_scancode.h>
#include <SDL2/SDL_render.h>
#include <stdbool.h>
#include <stdint.h>
#define SPRITE_WIDTH 100
#define SPRITE_HEIGHT 64
State *update_state(Player *player, uint32_t state);
State *idle_state(StateMachine *sm, Player *player);
State *walk_state(StateMachine *sm, Player *player);
State *dash_state(StateMachine *sm, Player *player);
void get_player_controls(Player *player);
void set_x_movement (Player *player);
void player_move (Player *player);
void player_dash (Player *player);
void player_jump (Player *player);
void player_fall (Player *player);
bool player_on_ground (Player *player);
int32_t player_gravity (Player *player);
State *update_state (Player *player, uint32_t state);
State *idle_state (StateMachine *sm, Player *player);
State *walk_state (StateMachine *sm, Player *player);
State *dash_state (StateMachine *sm, Player *player);
State *jump_state (StateMachine *sm, Player *player);
State *fall_state (StateMachine *sm, Player *player);
void player_init(Player *player, SDL_Renderer *renderer, SDL_Rect position) {
player->base_y = position.y;
player->position = position;
player->movement = (Movement){0};
player->x_direction = PLAYER_DIRECTION_RIGHT;
@@ -27,27 +39,26 @@ void player_init(Player *player, SDL_Renderer *renderer, SDL_Rect position) {
ap_init(renderer, "knight_player/Walking_KG_2.png", 125, SPRITE_WIDTH, SPRITE_HEIGHT, true);
player->animations[PLAYER_STATE_DASH] =
ap_init(renderer, "knight_player/Dashing_KG_1.png", 125, SPRITE_WIDTH, SPRITE_HEIGHT, false);
player->animations[PLAYER_STATE_JUMP] =
ap_init(renderer, "knight_player/Jump_KG_2.png", 100, SPRITE_WIDTH, SPRITE_HEIGHT, false);
player->animations[PLAYER_STATE_FALL] =
ap_init(renderer, "knight_player/Fall_KG_2.png", 50, SPRITE_WIDTH, SPRITE_HEIGHT, false);
player->states[PLAYER_STATE_IDLE] = (State){ .state_func = (StateFunc *)idle_state };
player->states[PLAYER_STATE_WALK] = (State){ .state_func = (StateFunc *)walk_state };
player->states[PLAYER_STATE_DASH] = (State){ .state_func = (StateFunc *)dash_state };
player->states[PLAYER_STATE_JUMP] = (State){ .state_func = (StateFunc *)jump_state };
player->states[PLAYER_STATE_FALL] = (State){ .state_func = (StateFunc *)fall_state };
player->event_data = (PlayerEventData){0};
player->state_machine = (StateMachine){ .current_state = &(player->states[PLAYER_STATE_IDLE]) };
player->current_state = PLAYER_STATE_IDLE;
}
void player_events(Player *player, const SDL_Event *event) {
if (!player || !event) {
return;
}
player->event_data.event = event;
sm_run(&(player->state_machine), (void *)player);
player->controls = (PlayerControl){0};
}
void player_update(Player *player, uint32_t ticks) {
player->position.x += player->movement.x;
get_player_controls(player);
sm_run(&(player->state_machine), (void *)player);
player_move(player);
ap_update(&(player->animations[player->current_state]), ticks);
}
@@ -55,6 +66,65 @@ void player_draw(const Player *player, SDL_Renderer *renderer) {
ap_draw(renderer, &(player->animations[player->current_state]), &(player->position), player->x_direction == PLAYER_DIRECTION_LEFT);
}
void get_player_controls(Player *player) {
const uint8_t *keys = SDL_GetKeyboardState(NULL);
player->controls.walk_left = keys[SDL_SCANCODE_LEFT] == SDL_PRESSED;
player->controls.walk_right = keys[SDL_SCANCODE_RIGHT] == SDL_PRESSED;
player->controls.space_last = player->controls.space_pressed;
player->controls.space_pressed = keys[SDL_SCANCODE_SPACE] == SDL_PRESSED;
player->controls.jump = player->controls.space_last && !(player->controls.space_pressed);
player->controls.lctrl_last = player->controls.lctrl_pressed;
player->controls.lctrl_pressed = keys[SDL_SCANCODE_LCTRL] == SDL_PRESSED;
player->controls.dash = player->controls.lctrl_last && !(player->controls.lctrl_pressed);
}
void set_x_movement(Player *player) {
if (player->controls.walk_left) {
player->movement.x = PLAYER_DIRECTION_LEFT * player->velocity;
player->x_direction = PLAYER_DIRECTION_LEFT;
} else if (player->controls.walk_right) {
player->movement.x = PLAYER_DIRECTION_RIGHT * player->velocity;
player->x_direction = PLAYER_DIRECTION_RIGHT;
} else if (!(player->controls.walk_left) && !(player->controls.walk_right)) {
player->movement.x = 0;
}
}
void player_move(Player *player) {
player->position.x += player->movement.x;
player->position.y += player->movement.y;
if (player->position.y > player->base_y) {
player->position.y = player->base_y;
}
}
void player_dash(Player *player) {
player->movement.x = player->x_direction * player->velocity * 2;
}
void player_jump(Player *player) {
player->movement.y = player->velocity * 7 * -1;
}
void player_fall(Player *player) {
player->movement.y = player->velocity * 6;
}
bool player_on_ground(Player *player) {
return player->position.y == player->base_y;
}
int32_t player_gravity(Player *player) {
return player->velocity * 0.5;
}
bool player_falling(Player *player) {
return player->movement.y > 0;
}
State *update_state(Player *player, uint32_t state) {
if (state >= COUNT_PLAYER_STATES) {
return &(player->states[player->current_state]);
@@ -65,52 +135,40 @@ State *update_state(Player *player, uint32_t state) {
}
State *idle_state(StateMachine *sm, Player *player) {
const SDL_Event *event = player->event_data.event;
uint32_t state = PLAYER_STATE_IDLE;
uint32_t state = PLAYER_STATE_IDLE;
switch (event->type) {
case SDL_KEYDOWN:
switch (event->key.keysym.sym) {
case SDLK_LEFT:
player->movement.x = PLAYER_DIRECTION_LEFT * player->velocity;
player->x_direction = PLAYER_DIRECTION_LEFT;
state = PLAYER_STATE_WALK;
break;
case SDLK_RIGHT:
player->movement.x = PLAYER_DIRECTION_RIGHT * player->velocity;
player->x_direction = PLAYER_DIRECTION_RIGHT;
state = PLAYER_STATE_WALK;
break;
}
break;
if (player->controls.jump) {
player_jump(player);
state = PLAYER_STATE_JUMP;
} else if (player->controls.walk_left) {
state = PLAYER_STATE_WALK;
} else if (player->controls.walk_right) {
state = PLAYER_STATE_WALK;
}
set_x_movement(player);
return update_state(player, state);
}
State *walk_state(StateMachine *sm, Player *player) {
const SDL_Event *event = player->event_data.event;
uint32_t state = PLAYER_STATE_WALK;
switch (event->type) {
case SDL_KEYUP:
switch (event->key.keysym.sym) {
case SDLK_LCTRL:
player->movement.x = player->x_direction * player->velocity * 3;
state = PLAYER_STATE_DASH;
break;
case SDLK_LEFT:
player->movement.x = 0;
state = PLAYER_STATE_IDLE;
break;
case SDLK_RIGHT:
player->movement.x = 0;
state = PLAYER_STATE_IDLE;
break;
}
break;
if (player->controls.jump) {
player_jump(player);
state = PLAYER_STATE_JUMP;
} else if (player->controls.dash) {
player_dash(player);
player->controls.jump_dash = false;
state = PLAYER_STATE_DASH;
}
if (!(player->controls.walk_left) && !(player->controls.walk_right)) {
state = PLAYER_STATE_IDLE;
}
set_x_movement(player);
return update_state(player, state);
}
@@ -118,12 +176,18 @@ State *dash_state(StateMachine *sm, Player *player) {
bool reset = false;
uint32_t state = PLAYER_STATE_DASH;
player->movement.x += player->x_direction * 3;
player->movement.x += player->x_direction * (int32_t)player->velocity * 0.5;
if (player->animations[PLAYER_STATE_DASH].finished) {
player->movement.x = 0;
reset = true;
state = PLAYER_STATE_IDLE;
if (player->controls.jump_dash) {
player_fall(player);
state = PLAYER_STATE_FALL;
} else {
player->movement.x = 0;
state = PLAYER_STATE_IDLE;
}
reset = true;
}
if (reset) {
@@ -132,3 +196,49 @@ State *dash_state(StateMachine *sm, Player *player) {
return update_state(player, state);
}
State *jump_state(StateMachine *sm, Player *player) {
bool reset = false;
uint32_t state = PLAYER_STATE_JUMP;
player->movement.y += player_gravity(player);
if (player->controls.dash) {
player_dash(player);
player->controls.jump_dash = true;
player->movement.y = player_gravity(player);
reset = true;
state = PLAYER_STATE_DASH;
} else if (player->animations[PLAYER_STATE_JUMP].finished) {
player_fall(player);
reset = true;
state = PLAYER_STATE_FALL;
}
if (reset) {
ap_reset(&(player->animations[PLAYER_STATE_JUMP]));
}
set_x_movement(player);
return update_state(player, state);
}
State *fall_state(StateMachine *sm, Player *player) {
bool reset = false;
uint32_t state = PLAYER_STATE_FALL;
if (player->animations[PLAYER_STATE_FALL].finished && player_on_ground(player)) {
player->movement.y = 0;
reset = true;
state = PLAYER_STATE_IDLE;
}
if (reset) {
ap_reset(&(player->animations[PLAYER_STATE_FALL]));
}
set_x_movement(player);
return update_state(player, state);
}

View File

@@ -12,6 +12,8 @@ enum player_states {
PLAYER_STATE_IDLE,
PLAYER_STATE_WALK,
PLAYER_STATE_DASH,
PLAYER_STATE_JUMP,
PLAYER_STATE_FALL,
COUNT_PLAYER_STATES,
};
@@ -23,9 +25,17 @@ enum player_direction {
PLAYER_DIRECTION_DOWN = 1,
};
typedef struct player_event_data PlayerEventData;
struct player_event_data {
const SDL_Event *event;
typedef struct player_control PlayerControl;
struct player_control {
bool walk_left;
bool walk_right;
bool space_last;
bool space_pressed;
bool jump;
bool lctrl_last;
bool lctrl_pressed;
bool dash;
bool jump_dash;
};
typedef struct movement Movement;
@@ -38,13 +48,14 @@ typedef struct player Player;
struct player {
uint32_t current_state;
uint32_t velocity;
int32_t base_y;
int32_t x_direction;
Movement movement;
SDL_Rect position;
PlayerEventData event_data;
StateMachine state_machine;
State states[COUNT_PLAYER_STATES];
AnimPlayer animations[COUNT_PLAYER_STATES];
PlayerControl controls;
};
void player_init (Player *player, SDL_Renderer *renderer, SDL_Rect position);