diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/app.h | 4 | ||||
| -rw-r--r-- | src/font.c | 178 | ||||
| -rw-r--r-- | src/font.h | 26 | ||||
| -rw-r--r-- | src/game.c | 68 | ||||
| -rw-r--r-- | src/main.c | 5 |
5 files changed, 268 insertions, 13 deletions
@@ -12,9 +12,9 @@ typedef enum { void init_app(SDL_Renderer* renderer, MIX_Mixer* mixer); void free_app(); -void init_game(SDL_Renderer* renderer, MIX_Mixer* mixer); +void init_timed_game(SDL_Renderer* renderer, MIX_Mixer* mixer, float time_remaining); void free_game(); -void update_game(float dt, MIX_Mixer* mixer); +void update_game(float dt); void draw_game(SDL_Renderer* renderer); void game_event(SDL_Event* e); diff --git a/src/font.c b/src/font.c new file mode 100644 index 0000000..999c3da --- /dev/null +++ b/src/font.c @@ -0,0 +1,178 @@ +#include "font.h" +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> + +#define FILE_NAME_SIZE 300 + +void free_sprite_font(sprite_font* font) { + free(font->characters); + SDL_DestroyTexture(font->spritesheet); + + memset(font, 0, sizeof(sprite_font)); +} + +int get_string_parameter(const char* line, const char* parameter, const char** start) { + *start = strstr(line, parameter); + if ((*start) == NULL) + return -1; + + *start += strlen(parameter); + if ((*start)[0] != '\"') { + return -1; + } + + int length = 0; + while ((*start)[length+1] != '\0' && (*start)[length+1] != '\"') length++; + + (*start)++; + return length; +} + +char parse_character_tag(const char* character_tag) { + if (strncmp(character_tag, "space", 5) == 0) + return ' '; + + return character_tag[0]; +} + +bool get_int_parameter(const char* line, const char* parameter, int* value) { + const char* start = strstr(line, parameter); + if (start == NULL) { + return false; + } + start += strlen(parameter); + + int c = 0; + bool negative = false; + + if (start[0] == '-') { + negative = true; + start++; + } + + for(int i = 0; start[i] >= '0' && start[i] <= '9'; i++) { + c *= 10; c += start[i] - '0'; + } + + *value = negative ? -c : c; + return true; +} + +bool load_sprite_font(const char* filename, sprite_font* font) { + if (font->characters || font->spritesheet) { + SDL_Log("Trying to reallocate font causing memory leak, exitting!"); + exit(EXIT_FAILURE); + } + + FILE* f = fopen(filename, "r"); + if (f == NULL) { + SDL_Log("Failed to open sprite font file %s, error: %s, exitting!", + filename, + strerror(errno) + ); + exit(EXIT_FAILURE); + } + + char line[PARSER_LINE_SIZE]; + if (fgets(line, sizeof(line), f) == NULL || + strncmp(line, "info", 4) != 0) { + SDL_Log("File %s is not a valid font file, exitting!", + filename); + fclose(f); + exit(EXIT_FAILURE); + } + + char font_name[FONT_NAME_SIZE]; + const char* font_name_start; + int font_name_length = + SDL_min(get_string_parameter(line, "face=", &font_name_start), + FONT_NAME_SIZE-1 + ); + + strncpy(font_name, font_name_start, font_name_length); + font_name[font_name_length] = '\0'; + + int char_size = 0, char_count = 0; + font_char* characters_unarranged = NULL; + + while (fgets(line, PARSER_LINE_SIZE, f) != NULL) { + + if (strncmp(line, "chars", 5) == 0) { + int total_char_count; + + if(!get_int_parameter(line, "count=", &total_char_count)) + continue; + + char_size = total_char_count; + characters_unarranged = + realloc(characters_unarranged, char_size * sizeof(font_char)); + + if (characters_unarranged == NULL) { + SDL_Log("Failed to allocate space while loading font %s, error %s, exitting!", + filename, + strerror(errno)); + exit(EXIT_FAILURE); + } + } + + else if (strncmp(line, "char", 4) == 0) { + font_char new_font_char; + + int val; + + if (!get_int_parameter(line, "x=", &val)) + continue; + new_font_char.x = val; + + if (!get_int_parameter(line, "y=", &val)) + continue; + new_font_char.y = val; + + if (!get_int_parameter(line, "width=", &val)) + continue; + new_font_char.width = val; + + if (!get_int_parameter(line, "height=", &val)) + continue; + new_font_char.height = val; + + if (!get_int_parameter(line, "xoffset=", &val)) + continue; + new_font_char.x_offset = val; + + if (!get_int_parameter(line, "yoffset=", &val)) + continue; + new_font_char.y_offset = val; + + if (!get_int_parameter(line, "xadvance=", &val)) + continue; + new_font_char.x_advance = val; + + const char* character_tag; + if (get_string_parameter(line, "letter=", &character_tag) <= 0) + continue; + new_font_char.character = parse_character_tag(character_tag); + + if (char_count >= char_size) { + char_size = char_count+1; + characters_unarranged = + realloc(characters_unarranged, char_size * sizeof(font_char)); + } + + if (characters_unarranged == NULL) { + SDL_Log("Failed to allocate space while loading font %s, error %s, exitting!", + filename, + strerror(errno)); + exit(EXIT_FAILURE); + } + + characters_unarranged[char_count] = new_font_char; + char_count++; + } + } + + fclose(f); + return true; +} diff --git a/src/font.h b/src/font.h new file mode 100644 index 0000000..a26c332 --- /dev/null +++ b/src/font.h @@ -0,0 +1,26 @@ +#ifndef FONT_H_ +#define FONT_H_ + +#include <SDL3/SDL.h> +#define FONT_NAME_SIZE 40 +#define PARSER_LINE_SIZE 4096 + +typedef struct { + float x, y; + float width, height; + float x_offset, y_offset; + float x_advance; + char character; +} font_char; + +typedef struct { + char name[FONT_NAME_SIZE]; + SDL_Texture* spritesheet; + char smallest_character, largest_character; + font_char* characters; +} sprite_font; + +bool load_sprite_font(const char* filename, sprite_font* font); +void free_sprite_font(sprite_font* font); + +#endif // FONT_H_ @@ -33,6 +33,7 @@ #define BOARD_PADDING 4 #define BACKGROUND_SCROLL_SPEED 40 +#define MAX_CLEARED_TILES_STORED 50 typedef enum { linear_move_state, @@ -79,10 +80,20 @@ typedef enum { swap_animation_state } game_scene_state; +typedef enum { + timed_mode, + combo_mode +} game_mode; + +typedef struct { + float time_remaining; +} timed_mode_data; + typedef struct { bool inited; SDL_Texture* spritesheet; game_scene_state state; + game_mode mode; piece pieces[MAX_PIECES]; int num_pieces; @@ -104,6 +115,8 @@ typedef struct { MIX_Track* background_music_track; MIX_Track* effect_track; MIX_Audio* pop_audio; + + timed_mode_data timed_mode_data; } s_game; extern SDL_Window* window; @@ -265,6 +278,15 @@ void init_game(SDL_Renderer* renderer, MIX_Mixer* mixer) { fill_board(); } +void init_timed_game(SDL_Renderer* renderer, MIX_Mixer* mixer, float time_remaining) { + init_game(renderer, mixer); + + game.mode = timed_mode; + game.timed_mode_data = (timed_mode_data) { + .time_remaining = time_remaining + }; +} + void free_game() { SDL_DestroyTexture(game.spritesheet); SDL_DestroyTexture(game.background_texture); @@ -351,6 +373,9 @@ int mouse_on_piece() { } void update_intro_state() { + if (game.state != intro_state) + return; + for (int i = 0; i < game.num_pieces; i++) { if (game.pieces[i].state != static_state && game.pieces[i].state != fall_state) { return; @@ -463,6 +488,9 @@ static inline void play_sound_effect(MIX_Audio* audio) { } void update_piece_swap_animation_state() { + if (game.state != swap_animation_state) + return; + for (int i = 0; i < game.num_pieces; i++) { if (game.pieces[i].state != static_state && game.pieces[i].state != fall_state) return; @@ -521,27 +549,32 @@ void scroll_background(float dt) { } } -void update_game(float dt, MIX_Mixer* mixer) { + +void delete_out_of_screen_pieces() { int window_width, window_height; SDL_GetWindowSizeInPixels(window, &window_width, &window_height); for (int i = 0; i < game.num_pieces; i++) { - update_piece(&game.pieces[i], dt); - if (game.pieces[i].position.y > window_height + DELETE_PIECE_OFFSET) { delete_piece(game.pieces[i].piece_id); } } +} - handle_piece_rotation(dt); +void update_timed_mode(float dt); +void update_game(float dt) { + for (int i = 0; i < game.num_pieces; i++) { + update_piece(&game.pieces[i], dt); + } + delete_out_of_screen_pieces(); + handle_piece_rotation(dt); scroll_background(dt); - if (game.state == intro_state) { - update_intro_state(); - } else if (game.state == swap_animation_state) { - update_piece_swap_animation_state(); - } + update_intro_state(); + update_piece_swap_animation_state(); + + update_timed_mode(dt); } void draw_piece(SDL_Renderer* renderer, const piece* piece) { @@ -659,6 +692,8 @@ void piece_held_event(SDL_Event* e) { } } + //If pieces are more that one tile apart or + //they are of the same color do nothing if (SDL_abs(selected_x-swap_x) + SDL_abs(selected_y-swap_y) != 1 || retreive_piece(selected_piece_id)->piece_color == retreive_piece(swap_piece_id)->piece_color) { game.state = neutral_state; @@ -683,3 +718,18 @@ void game_event(SDL_Event* e) { piece_held_event(e); } } + + +//********************************************** +//*****************TIMED MODE******************* +//*********************************************/ +void update_timed_mode(float dt) { + timed_mode_data* timed_mode_data = &game.timed_mode_data; + + timed_mode_data->time_remaining = + SDL_max(timed_mode_data->time_remaining - dt, 0); + + if (timed_mode_data->time_remaining <= 0) { + SDL_Log("Time over"); + } +} @@ -7,6 +7,7 @@ #include <SDL3_mixer/SDL_mixer.h> #include "app.h" +#include "font.h" #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 @@ -66,7 +67,7 @@ SDL_AppResult SDL_AppIterate(void* userdata) { switch (app_state) { case game_state: - update_game(SDL_min(dt, MAX_DELTATIME), mixer); + update_game(SDL_min(dt, MAX_DELTATIME)); draw_game(renderer); break; @@ -88,7 +89,7 @@ void SDL_AppQuit(void* userdata, SDL_AppResult result) { } void init_app(SDL_Renderer* renderer, MIX_Mixer* mixer) { - init_game(renderer, mixer); + init_timed_game(renderer, mixer, 5); app_state = game_state; } |
