X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fgame.c;h=7c3786c8ab4247491c0d80a8b3386407ddd9357b;hb=9127e1899cdbf7cd0a261a93722e1b1d691f5a37;hp=8f2361afc93829a2a7bdf1fb9838ca5c815a5c93;hpb=70b065ae72a4bbd1c465a6bcd65504bccf60d587;p=nothing.git diff --git a/src/game.c b/src/game.c index 8f2361af..7c3786c8 100644 --- a/src/game.c +++ b/src/game.c @@ -1,5 +1,4 @@ -#include -#include +#include #include "system/stacktrace.h" #include @@ -15,12 +14,17 @@ #include "system/str.h" #include "ebisp/builtins.h" #include "broadcast.h" +#include "sdl/texture.h" +#include "game/level/level_editor.h" + +static int game_render_cursor(const Game *game); typedef enum Game_state { GAME_STATE_RUNNING = 0, GAME_STATE_PAUSE, GAME_STATE_CONSOLE, GAME_STATE_LEVEL_PICKER, + GAME_STATE_LEVEL_EDITOR, GAME_STATE_QUIT } Game_state; @@ -31,27 +35,27 @@ typedef struct Game { Broadcast *broadcast; Sprite_font *font; LevelPicker *level_picker; + LevelEditor *level_editor; Level *level; - char *level_file_path; Sound_samples *sound_samples; Camera *camera; Console *console; SDL_Renderer *renderer; + SDL_Texture *texture_cursor; + int cursor_x; + int cursor_y; } Game; -Game *create_game(const char *level_file_path, +Game *create_game(const char *level_folder, const char *sound_sample_files[], size_t sound_sample_files_count, SDL_Renderer *renderer) { - trace_assert(level_file_path); + trace_assert(level_folder); - Lt *const lt = create_lt(); - if (lt == NULL) { - return NULL; - } + Lt *lt = create_lt(); - Game *game = PUSH_LT(lt, nth_alloc(sizeof(Game)), free); + Game *game = PUSH_LT(lt, nth_calloc(1, sizeof(Game)), free); if (game == NULL) { RETURN_LT(lt, NULL); } @@ -70,7 +74,7 @@ Game *create_game(const char *level_file_path, game->font = PUSH_LT( lt, create_sprite_font_from_file( - "fonts/charmap-oldschool.bmp", + "images/charmap-oldschool.bmp", renderer), destroy_sprite_font); if (game->font == NULL) { @@ -81,22 +85,12 @@ Game *create_game(const char *level_file_path, lt, create_level_picker( game->font, - level_file_path), + level_folder), destroy_level_picker); if (game->level_picker == NULL) { RETURN_LT(lt, NULL); } - game->level = NULL; - - game->level_file_path = PUSH_LT( - lt, - string_duplicate(level_file_path, NULL), - free); - if (game->level_file_path == NULL) { - RETURN_LT(lt, NULL); - } - game->sound_samples = PUSH_LT( lt, create_sound_samples( @@ -124,6 +118,23 @@ Game *create_game(const char *level_file_path, } game->renderer = renderer; + game->texture_cursor = PUSH_LT( + lt, + texture_from_bmp("images/cursor.bmp", renderer), + SDL_DestroyTexture); + if (SDL_SetTextureBlendMode( + game->texture_cursor, + SDL_ComposeCustomBlendMode( + SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR, + SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR, + SDL_BLENDOPERATION_ADD, + SDL_BLENDFACTOR_ONE, + SDL_BLENDFACTOR_ZERO, + SDL_BLENDOPERATION_ADD)) < 0) { + log_warn("SDL error: %s\n", SDL_GetError()); + } + game->cursor_x = 0; + game->cursor_y = 0; return game; } @@ -151,7 +162,7 @@ int game_render(const Game *game) return -1; } - if (console_render(game->console, game->renderer) < 0) { + if (console_render(game->console, game->camera, game->renderer) < 0) { return -1; } } break; @@ -160,6 +171,20 @@ int game_render(const Game *game) if (level_picker_render(game->level_picker, game->camera, game->renderer) < 0) { return -1; } + + if (game_render_cursor(game) < 0) { + return -1; + } + } break; + + case GAME_STATE_LEVEL_EDITOR: { + if (level_editor_render(game->level_editor, game->camera) < 0) { + return -1; + } + + if (game_render_cursor(game) < 0) { + return -1; + } } break; case GAME_STATE_QUIT: break; @@ -176,6 +201,7 @@ int game_sound(Game *game) case GAME_STATE_CONSOLE: return level_sound(game->level, game->sound_samples); case GAME_STATE_LEVEL_PICKER: + case GAME_STATE_LEVEL_EDITOR: case GAME_STATE_QUIT: return 0; } @@ -223,22 +249,56 @@ int game_update(Game *game, float delta_time) return -1; } - // TODO: There is no way to go back to LevelPicker when the level is loaded - const char *level_file_path = level_picker_selected_level(game->level_picker); + const char *level_filename = level_picker_selected_level(game->level_picker); + + if (level_filename != NULL) { + if (game->level_editor == NULL) { + game->level_editor = PUSH_LT( + game->lt, + create_level_editor_from_file(level_filename), + destroy_level_editor); + } else { + game->level_editor = RESET_LT( + game->lt, + game->level_editor, + create_level_editor_from_file(level_filename)); + } - trace_assert(game->level == NULL); + if (game->level_editor == NULL) { + return -1; + } + + if (game->level == NULL) { + game->level = PUSH_LT( + game->lt, + create_level_from_level_editor( + game->level_editor, + game->broadcast), + destroy_level); + } else { + game->level = RESET_LT( + game->lt, + game->level, + create_level_from_level_editor( + game->level_editor, + game->broadcast)); + } - if (level_file_path != NULL) { - game->level = PUSH_LT( - game->lt, - create_level_from_file(level_file_path, game->broadcast), - destroy_level); if (game->level == NULL) { return -1; } game->state = GAME_STATE_RUNNING; } + + } break; + + case GAME_STATE_LEVEL_EDITOR: { + if (level_editor_focus_camera( + game->level_editor, + game->camera) < 0) { + return -1; + } } break; case GAME_STATE_PAUSE: @@ -256,10 +316,6 @@ static int game_event_pause(Game *game, const SDL_Event *event) trace_assert(event); switch (event->type) { - case SDL_QUIT: - game->state = GAME_STATE_QUIT; - break; - case SDL_KEYDOWN: switch (event->key.keysym.sym) { case SDLK_p: @@ -284,63 +340,66 @@ static int game_event_running(Game *game, const SDL_Event *event) trace_assert(event); switch (event->type) { - case SDL_QUIT: - game->state = GAME_STATE_QUIT; - break; - - case SDL_KEYDOWN: + case SDL_KEYDOWN: { switch (event->key.keysym.sym) { - case SDLK_r: - log_info("Reloading the level from '%s'...\n", game->level_file_path); + case SDLK_r: { + const char *level_filename = level_picker_selected_level(game->level_picker); + + log_info("Reloading the level from '%s'...\n", level_filename); + + game->level_editor = RESET_LT( + game->lt, + game->level_editor, + create_level_editor_from_file(level_filename)); + if (game->level_editor == NULL) { + log_fail("Could not reload level %s\n", level_filename); + game->state = GAME_STATE_QUIT; + return -1; + } game->level = RESET_LT( game->lt, game->level, - create_level_from_file( - game->level_file_path, game->broadcast)); - + create_level_from_level_editor( + game->level_editor, + game->broadcast)); if (game->level == NULL) { - log_fail("Could not reload level %s\n", game->level_file_path); + log_fail("Could not reload level %s\n", level_filename); game->state = GAME_STATE_QUIT; return -1; } camera_disable_debug_mode(game->camera); + } break; - break; - - case SDLK_q: - log_info("Reloading the level's platforms from '%s'...\n", game->level_file_path); - if (level_reload_preserve_player(game->level, game->level_file_path, game->broadcast) < 0) { - log_fail("Could not reload level %s\n", game->level_file_path); - game->state = GAME_STATE_QUIT; - return -1; - } - break; - - case SDLK_p: + case SDLK_p: { game->state = GAME_STATE_PAUSE; camera_toggle_blackwhite_mode(game->camera); sound_samples_toggle_pause(game->sound_samples); - break; + } break; - case SDLK_l: + case SDLK_l: { camera_toggle_debug_mode(game->camera); level_toggle_debug_mode(game->level); - break; + } break; + + case SDLK_TAB: { + game->state = GAME_STATE_LEVEL_EDITOR; + SDL_SetRelativeMouseMode(true); + } break; } - break; - case SDL_KEYUP: + } break; + + case SDL_KEYUP: { switch (event->key.keysym.sym) { case SDLK_BACKQUOTE: - case SDLK_c: + case SDLK_c: { SDL_StartTextInput(); game->state = GAME_STATE_CONSOLE; console_slide_down(game->console); - break; + } break; } - break; - + } break; } return level_event(game->level, event); @@ -349,10 +408,6 @@ static int game_event_running(Game *game, const SDL_Event *event) static int game_event_console(Game *game, const SDL_Event *event) { switch (event->type) { - case SDL_QUIT: - game->state = GAME_STATE_QUIT; - return 0; - case SDL_KEYDOWN: switch (event->key.keysym.sym) { case SDLK_ESCAPE: @@ -375,13 +430,80 @@ static int game_event_level_picker(Game *game, const SDL_Event *event) trace_assert(event); switch (event->type) { - case SDL_QUIT: - game->state = GAME_STATE_QUIT; - return 0; + case SDL_KEYDOWN: { + switch(event->key.keysym.sym) { + case SDLK_n: { + if (game->level_editor == NULL) { + game->level_editor = PUSH_LT( + game->lt, + create_level_editor(), + destroy_level_editor); + } else { + game->level_editor = RESET_LT( + game->lt, + game->level_editor, + create_level_editor()); + } + + if (game->level_editor == NULL) { + return -1; + } + + if (game->level == NULL) { + game->level = PUSH_LT( + game->lt, + create_level_from_level_editor( + game->level_editor, + game->broadcast), + destroy_level); + } else { + game->level = RESET_LT( + game->lt, + game->level, + create_level_from_level_editor( + game->level_editor, + game->broadcast)); + } - default: - return level_picker_event(game->level_picker, event); + if (game->level == NULL) { + return -1; + } + + game->state = GAME_STATE_RUNNING; + } break; + } + } break; + } + + return level_picker_event(game->level_picker, event); +} + +static int game_event_level_editor(Game *game, const SDL_Event *event) +{ + trace_assert(game); + trace_assert(event); + + switch (event->type) { + case SDL_KEYDOWN: { + switch (event->key.keysym.sym) { + case SDLK_TAB: { + game->level = RESET_LT( + game->lt, + game->level, + create_level_from_level_editor( + game->level_editor, + game->broadcast)); + if (game->level == NULL) { + return -1; + } + game->state = GAME_STATE_RUNNING; + SDL_SetRelativeMouseMode(false); + } break; + } + } break; } + + return level_editor_event(game->level_editor, event, game->camera); } int game_event(Game *game, const SDL_Event *event) @@ -389,6 +511,18 @@ int game_event(Game *game, const SDL_Event *event) trace_assert(game); trace_assert(event); + switch (event->type) { + case SDL_QUIT: { + game->state = GAME_STATE_QUIT; + return 0; + } break; + + case SDL_MOUSEMOTION: { + game->cursor_x = event->motion.x; + game->cursor_y = event->motion.y; + } break; + } + switch (game->state) { case GAME_STATE_RUNNING: return game_event_running(game, event); @@ -402,10 +536,14 @@ int game_event(Game *game, const SDL_Event *event) case GAME_STATE_LEVEL_PICKER: return game_event_level_picker(game, event); - default: {} + case GAME_STATE_LEVEL_EDITOR: + return game_event_level_editor(game, event); + + case GAME_STATE_QUIT: + return 0; } - return 0; + return -1; } @@ -420,6 +558,7 @@ int game_input(Game *game, case GAME_STATE_QUIT: case GAME_STATE_PAUSE: case GAME_STATE_CONSOLE: + case GAME_STATE_LEVEL_EDITOR: return 0; case GAME_STATE_RUNNING: @@ -454,7 +593,26 @@ game_send(Game *game, Gc *gc, struct Scope *scope, if (strcmp(target, "level") == 0) { return level_send(game->level, gc, scope, rest); + } else if (strcmp(target, "menu") == 0) { + level_picker_clean_selection(game->level_picker); + game->state = GAME_STATE_LEVEL_PICKER; + return eval_success(NIL(gc)); } return unknown_target(gc, "game", target); } + +// Private Functions + +static int game_render_cursor(const Game *game) +{ + trace_assert(game); + + SDL_Rect src = {0, 0, 32, 32}; + SDL_Rect dest = {game->cursor_x, game->cursor_y, 32, 32}; + if (SDL_RenderCopy(game->renderer, game->texture_cursor, &src, &dest) < 0) { + return -1; + } + + return 0; +}