Animation code
This commit is contained in:
		
							
								
								
									
										78
									
								
								animation_player.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								animation_player.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | |||||||
|  | #include "animation_player.h" | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <SDL2/SDL_rect.h> | ||||||
|  | #include <SDL2/SDL_timer.h> | ||||||
|  | #include <SDL2/SDL_render.h> | ||||||
|  | #include <SDL2/SDL_image.h> | ||||||
|  |  | ||||||
|  | AnimPlayer ap_init(SDL_Renderer *renderer, const char *filepath, uint32_t ms_speed, uint32_t sprite_width, uint32_t sprite_height, bool loop) { | ||||||
|  | 	SDL_Texture *image = IMG_LoadTexture(renderer, filepath); | ||||||
|  | 	if (!image) { | ||||||
|  | 		return (AnimPlayer){0}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	int w; | ||||||
|  | 	if (SDL_QueryTexture(image, NULL, NULL, &w, NULL) < 0) { | ||||||
|  | 		return (AnimPlayer){0}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	AnimPlayer ap = { | ||||||
|  | 		.image         = image, | ||||||
|  | 		.last_time     = SDL_GetTicks(), | ||||||
|  | 		.ms_speed      = ms_speed, | ||||||
|  | 		.sprite_width  = sprite_width, | ||||||
|  | 		.sprite_height = sprite_height, | ||||||
|  | 		.count         = w / sprite_width, | ||||||
|  | 		.current       = 0, | ||||||
|  | 		.loop          = loop, | ||||||
|  | 		.finished      = false, | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	ap.ms_duration = ap.ms_speed * ap.count; | ||||||
|  |  | ||||||
|  | 	return ap; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ap_update(AnimPlayer *ap, uint32_t ticks) { | ||||||
|  | 	if (!ap) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (ap->current + 1 == ap->count && !(ap->loop)) { | ||||||
|  | 		ap->finished = true; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (ticks - ap->last_time >= ap->ms_speed) { | ||||||
|  | 		ap->last_time = ticks; | ||||||
|  | 		ap->current   = ++ap->current % ap->count; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ap_draw(SDL_Renderer *renderer, const AnimPlayer *ap, const SDL_Rect *dst, bool x_flip) { | ||||||
|  | 	if (!renderer || !ap || !(ap->image)) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	SDL_Rect src = { | ||||||
|  | 		.x = ap->current * ap->sprite_width, | ||||||
|  | 		.y = 0, | ||||||
|  | 		.w = ap->sprite_width, | ||||||
|  | 		.h = ap->sprite_height, | ||||||
|  | 	}; | ||||||
|  | 	SDL_RenderCopyEx(renderer, ap->image, &src, dst, 0, NULL, x_flip ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ap_reset(AnimPlayer *ap) { | ||||||
|  | 	ap->current  = 0; | ||||||
|  | 	ap->finished = false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ap_destroy(AnimPlayer *ap) { | ||||||
|  | 	if (!ap || !(ap->image)) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	SDL_DestroyTexture(ap->image); | ||||||
|  | 	ap->image = NULL; | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								animation_player.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								animation_player.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <SDL2/SDL_render.h> | ||||||
|  |  | ||||||
|  | typedef struct anim_player AnimPlayer; | ||||||
|  |  | ||||||
|  | struct anim_player { | ||||||
|  | 	SDL_Texture *image; | ||||||
|  | 	uint32_t    last_time; | ||||||
|  | 	uint32_t    ms_speed; | ||||||
|  | 	uint32_t    ms_duration; | ||||||
|  | 	uint32_t    sprite_width; | ||||||
|  | 	uint32_t    sprite_height; | ||||||
|  | 	uint16_t    count; | ||||||
|  | 	uint16_t    current; | ||||||
|  | 	bool        loop; | ||||||
|  | 	bool        finished; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | AnimPlayer ap_init   (SDL_Renderer *renderer, const char *filepath, uint32_t ms_speed, uint32_t sprite_width, uint32_t sprite_height, bool loop); | ||||||
|  | void       ap_update (AnimPlayer *ap, uint32_t ticks); | ||||||
|  | void       ap_draw   (SDL_Renderer *renderer, const AnimPlayer *ap, const SDL_Rect *dst, bool x_flip); | ||||||
|  | void       ap_reset  (AnimPlayer *ap); | ||||||
|  | void       ap_destroy(AnimPlayer *ap); | ||||||
							
								
								
									
										64
									
								
								main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								main.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | |||||||
|  | #include "player.h" | ||||||
|  | #include <SDL2/SDL.h> | ||||||
|  | #include <SDL2/SDL_timer.h> | ||||||
|  | #include <SDL2/SDL_rect.h> | ||||||
|  | #include <SDL2/SDL_events.h> | ||||||
|  | #include <SDL2/SDL_render.h> | ||||||
|  | #include <SDL2/SDL_video.h> | ||||||
|  | #include <SDL2/SDL_image.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | #define WINDOW_WIDTH 1280 | ||||||
|  | #define WINDOW_HEIGHT 720 | ||||||
|  |  | ||||||
|  | int main() { | ||||||
|  | 	SDL_Init(SDL_INIT_EVERYTHING); | ||||||
|  | 	IMG_Init(IMG_INIT_PNG); | ||||||
|  |  | ||||||
|  | 	SDL_Window *window = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, | ||||||
|  | 																				WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN); | ||||||
|  |  | ||||||
|  | 	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 }); | ||||||
|  |  | ||||||
|  | 	bool running = true; | ||||||
|  |  | ||||||
|  | 	SDL_Event event = {0}; | ||||||
|  | 	uint32_t ticks; | ||||||
|  |  | ||||||
|  | 	while (running) { | ||||||
|  | 		while (SDL_PollEvent(&event)) { | ||||||
|  | 			player_events(&player, &event); | ||||||
|  |  | ||||||
|  | 			switch (event.type) { | ||||||
|  | 			case SDL_QUIT: | ||||||
|  | 				running = false; | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		ticks = SDL_GetTicks(); | ||||||
|  |  | ||||||
|  | 		player_update(&player, ticks); | ||||||
|  |  | ||||||
|  | 		SDL_SetRenderDrawColor(renderer, 0, 94, 124, 255); | ||||||
|  |  | ||||||
|  | 		SDL_RenderClear(renderer); | ||||||
|  |  | ||||||
|  | 		player_draw(&player, renderer); | ||||||
|  |  | ||||||
|  | 		SDL_RenderPresent(renderer); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	SDL_DestroyRenderer(renderer); | ||||||
|  |  | ||||||
|  | 	SDL_DestroyWindow(window); | ||||||
|  |  | ||||||
|  | 	IMG_Quit(); | ||||||
|  | 	SDL_Quit(); | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
							
								
								
									
										200
									
								
								player.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								player.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,200 @@ | |||||||
|  | #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 <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 *jump_state(StateMachine *sm, Player *player); | ||||||
|  | State *fall_state(StateMachine *sm, Player *player); | ||||||
|  | State *dash_state(StateMachine *sm, Player *player); | ||||||
|  |  | ||||||
|  | void player_init(Player *player, SDL_Renderer *renderer, SDL_Rect position) { | ||||||
|  | 	player->position    = position; | ||||||
|  | 	player->movement    = (Movement){0}; | ||||||
|  | 	player->x_direction = PLAYER_DIRECTION_RIGHT; | ||||||
|  | 	player->velocity    = 4; | ||||||
|  |  | ||||||
|  | 	player->animations[PLAYER_STATE_IDLE] =  | ||||||
|  | 			ap_init(renderer, "knight_player/Idle_KG_2.png",    125, SPRITE_WIDTH, SPRITE_HEIGHT, true); | ||||||
|  | 	player->animations[PLAYER_STATE_WALK] =  | ||||||
|  | 			ap_init(renderer, "knight_player/Walking_KG_2.png", 125, SPRITE_WIDTH, SPRITE_HEIGHT, true); | ||||||
|  | 	player->animations[PLAYER_STATE_JUMP] =  | ||||||
|  | 			ap_init(renderer, "knight_player/Jump_KG_2.png",    125, SPRITE_WIDTH, SPRITE_HEIGHT, false); | ||||||
|  | 	player->animations[PLAYER_STATE_FALL] =  | ||||||
|  | 			ap_init(renderer, "knight_player/Fall_KG_2.png",    125, SPRITE_WIDTH, SPRITE_HEIGHT, false); | ||||||
|  | 	player->animations[PLAYER_STATE_DASH] =  | ||||||
|  | 			ap_init(renderer, "knight_player/Dashing_KG_1.png", 125, 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_JUMP] = (State){ .state_func = (StateFunc *)jump_state }; | ||||||
|  | 	player->states[PLAYER_STATE_FALL] = (State){ .state_func = (StateFunc *)fall_state }; | ||||||
|  | 	player->states[PLAYER_STATE_DASH] = (State){ .state_func = (StateFunc *)dash_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; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	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; | ||||||
|  | 					player->event_data.key = PLAYER_CONTROL_LEFT_DOWN; | ||||||
|  | 					break; | ||||||
|  | 				case SDLK_RIGHT: | ||||||
|  | 					player->movement.x     = PLAYER_DIRECTION_RIGHT * player->velocity; | ||||||
|  | 					player->x_direction    = PLAYER_DIRECTION_RIGHT; | ||||||
|  | 					player->event_data.key = PLAYER_CONTROL_RIGHT_DOWN; | ||||||
|  | 					break; | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		case SDL_KEYUP: | ||||||
|  | 			switch (event->key.keysym.sym) { | ||||||
|  | 				case SDLK_LEFT: | ||||||
|  | 					player->movement.x     = 0; | ||||||
|  | 					player->event_data.key = PLAYER_CONTROL_LEFT_UP; | ||||||
|  | 					break; | ||||||
|  | 				case SDLK_RIGHT: | ||||||
|  | 					player->movement.x     = 0; | ||||||
|  | 					player->event_data.key = PLAYER_CONTROL_RIGHT_UP; | ||||||
|  | 					break; | ||||||
|  | 				case SDLK_SPACE: | ||||||
|  | 					player->event_data.key = PLAYER_CONTROL_SPACE; | ||||||
|  | 					break; | ||||||
|  | 				case SDLK_LCTRL: | ||||||
|  | 					player->movement.x     = player->x_direction * player->velocity * 3; | ||||||
|  | 					player->event_data.key = PLAYER_CONTROL_LCTRL; | ||||||
|  |  | ||||||
|  | 					if (player->current_state == PLAYER_STATE_JUMP) { | ||||||
|  | 						player->event_data.dash_in_air = true; | ||||||
|  | 					} else { | ||||||
|  | 						player->event_data.dash_in_air = false; | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					break; | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void player_update(Player *player, uint32_t ticks) { | ||||||
|  | 	player->position.x += player->movement.x; | ||||||
|  | 	sm_run(&(player->state_machine), (void *)player); | ||||||
|  | 	ap_update(&(player->animations[player->current_state]), ticks); | ||||||
|  | 	player->event_data.key = PLAYER_CONTROL_NONE; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | 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); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | State *update_state(Player *player, uint32_t state) { | ||||||
|  | 	if (state >= COUNT_PLAYER_STATES) { | ||||||
|  | 		return &(player->states[player->current_state]); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	player->current_state = state; | ||||||
|  | 	return &(player->states[state]); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | State *idle_state(StateMachine *sm, Player *player) { | ||||||
|  | 	switch (player->event_data.key) { | ||||||
|  | 		case PLAYER_CONTROL_LEFT_DOWN: | ||||||
|  | 		case PLAYER_CONTROL_RIGHT_DOWN: | ||||||
|  | 			return update_state(player, PLAYER_STATE_WALK); | ||||||
|  | 		case PLAYER_CONTROL_SPACE: | ||||||
|  | 			return update_state(player, PLAYER_STATE_JUMP); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return update_state(player, PLAYER_STATE_IDLE); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | State *walk_state(StateMachine *sm, Player *player) { | ||||||
|  | 	switch (player->event_data.key) { | ||||||
|  | 		case PLAYER_CONTROL_LEFT_UP: | ||||||
|  | 		case PLAYER_CONTROL_RIGHT_UP: | ||||||
|  | 			return update_state(player, PLAYER_STATE_IDLE); | ||||||
|  | 		case PLAYER_CONTROL_SPACE: | ||||||
|  | 			return update_state(player, PLAYER_STATE_JUMP); | ||||||
|  | 		case PLAYER_CONTROL_LCTRL: | ||||||
|  | 			return update_state(player, PLAYER_STATE_DASH); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return update_state(player, PLAYER_STATE_WALK); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | State *jump_state(StateMachine *sm, Player *player) { | ||||||
|  | 	bool reset     = false; | ||||||
|  | 	uint32_t state = PLAYER_STATE_JUMP; | ||||||
|  |  | ||||||
|  | 	if (player->animations[PLAYER_STATE_JUMP].finished) { | ||||||
|  | 		reset = true; | ||||||
|  | 		state = PLAYER_STATE_FALL; | ||||||
|  | 	} else if (player->event_data.key == PLAYER_CONTROL_LCTRL) { | ||||||
|  | 		reset = true; | ||||||
|  | 		state = PLAYER_STATE_DASH; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (reset) { | ||||||
|  | 		ap_reset(&(player->animations[PLAYER_STATE_JUMP])); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	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) { | ||||||
|  | 		reset = true; | ||||||
|  | 		state = PLAYER_STATE_IDLE; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (reset) { | ||||||
|  | 		ap_reset(&(player->animations[PLAYER_STATE_FALL])); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return update_state(player, state); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | State *dash_state(StateMachine *sm, Player *player) { | ||||||
|  | 	bool reset     = false; | ||||||
|  | 	uint32_t state = PLAYER_STATE_DASH; | ||||||
|  |  | ||||||
|  | 	player->movement.x += player->x_direction * 10; | ||||||
|  |  | ||||||
|  | 	if (player->animations[PLAYER_STATE_DASH].finished) { | ||||||
|  | 		reset = true; | ||||||
|  | 		player->movement.x = 0; | ||||||
|  |  | ||||||
|  | 		if (player->event_data.dash_in_air) { | ||||||
|  | 			state = PLAYER_STATE_FALL; | ||||||
|  | 		} else { | ||||||
|  | 			state = PLAYER_STATE_IDLE; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (reset) { | ||||||
|  | 		ap_reset(&(player->animations[PLAYER_STATE_DASH])); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return update_state(player, state); | ||||||
|  | } | ||||||
							
								
								
									
										68
									
								
								player.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								player.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "animation_player.h" | ||||||
|  | #include "state_machine.h" | ||||||
|  | #include <SDL2/SDL_rect.h> | ||||||
|  | #include <SDL2/SDL_events.h> | ||||||
|  | #include <SDL2/SDL_render.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  |  | ||||||
|  | enum player_states { | ||||||
|  | 	PLAYER_STATE_IDLE, | ||||||
|  | 	PLAYER_STATE_WALK, | ||||||
|  | 	PLAYER_STATE_JUMP, | ||||||
|  | 	PLAYER_STATE_FALL, | ||||||
|  | 	PLAYER_STATE_DASH, | ||||||
|  |  | ||||||
|  | 	COUNT_PLAYER_STATES, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum player_controls { | ||||||
|  | 	PLAYER_CONTROL_NONE, | ||||||
|  | 	PLAYER_CONTROL_LEFT_DOWN, | ||||||
|  | 	PLAYER_CONTROL_RIGHT_DOWN, | ||||||
|  | 	PLAYER_CONTROL_LEFT_UP, | ||||||
|  | 	PLAYER_CONTROL_RIGHT_UP, | ||||||
|  | 	PLAYER_CONTROL_SPACE, | ||||||
|  | 	PLAYER_CONTROL_LCTRL, | ||||||
|  |  | ||||||
|  | 	COUNT_PLAYER_CONTROLS, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum player_direction { | ||||||
|  | 	PLAYER_DIRECTION_LEFT  = -1, | ||||||
|  | 	PLAYER_DIRECTION_RIGHT =  1, | ||||||
|  | 	PLAYER_DIRECTION_UP    = -1, | ||||||
|  | 	PLAYER_DIRECTION_DOWN  =  1, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | typedef struct player_event_data PlayerEventData; | ||||||
|  | struct player_event_data { | ||||||
|  | 	uint32_t key; | ||||||
|  | 	bool     dash_in_air; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | typedef struct movement Movement; | ||||||
|  | struct movement { | ||||||
|  | 	int32_t x; | ||||||
|  | 	int32_t y; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | typedef struct player Player; | ||||||
|  | struct player { | ||||||
|  | 	uint32_t        current_state;  | ||||||
|  | 	uint32_t        velocity;  | ||||||
|  | 	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]; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | void player_init  (Player *player, SDL_Renderer *renderer, SDL_Rect position); | ||||||
|  | void player_events(Player *player, const SDL_Event *event); | ||||||
|  | void player_update(Player *player, uint32_t ticks); | ||||||
|  | void player_draw  (const Player *player, SDL_Renderer *renderer); | ||||||
							
								
								
									
										9
									
								
								state_machine.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								state_machine.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | #include "state_machine.h" | ||||||
|  |  | ||||||
|  | void sm_run(StateMachine *sm, void *event_data) { | ||||||
|  | 	if (!sm || !(sm->current_state)) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	sm->current_state = sm->current_state->state_func(sm, event_data); | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								state_machine.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								state_machine.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | typedef struct state State; | ||||||
|  | typedef struct state_machine StateMachine; | ||||||
|  | typedef State *(StateFunc)(StateMachine *sm, void *event_data); | ||||||
|  | typedef void NoEventData; | ||||||
|  |  | ||||||
|  | struct state { | ||||||
|  | 	StateFunc *state_func; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct state_machine { | ||||||
|  | 	State *current_state; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | void sm_run(StateMachine *sm, void *event_data); | ||||||
		Reference in New Issue
	
	Block a user