Camera camera;
SDL_Renderer *renderer;
SDL_Texture *texture_cursor;
+ Console *console;
+ int console_enabled;
int cursor_x;
int cursor_y;
} Game;
SDL_BLENDOPERATION_ADD)) < 0) {
log_warn("SDL error: %s\n", SDL_GetError());
}
+
+ game->console = PUSH_LT(
+ lt,
+ create_console(game),
+ destroy_console);
+ if (game->console == NULL) {
+ RETURN_LT(lt, NULL);
+ }
+ game->console_enabled = 0;
+
game->cursor_x = 0;
game->cursor_y = 0;
case GAME_STATE_QUIT: break;
}
+ if (game->console_enabled) {
+ if (console_render(game->console, &game->camera) < 0) {
+ return -1;
+ }
+ }
+
if (game_render_cursor(game) < 0) {
return -1;
}
trace_assert(game);
trace_assert(delta_time > 0.0f);
+ if (game->console_enabled) {
+ if (console_update(game->console, delta_time) < 0) {
+ return -1;
+ }
+ }
+
switch (game->state) {
case GAME_STATE_LEVEL: {
if (level_update(game->level, delta_time) < 0) {
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));
- }
-
- if (game->level_editor == NULL) {
+ if (game_load_level(game, level_filename) < 0) {
return -1;
}
-
- if (game->level == NULL) {
- game->level = PUSH_LT(
- game->lt,
- create_level_from_level_editor(
- game->level_editor),
- destroy_level);
- } else {
- game->level = RESET_LT(
- game->lt,
- game->level,
- create_level_from_level_editor(
- game->level_editor));
- }
-
- if (game->level == NULL) {
- return -1;
- }
-
- game_switch_state(game, GAME_STATE_LEVEL);
}
-
} break;
case GAME_STATE_LEVEL_EDITOR: {
trace_assert(game);
trace_assert(event);
+ // Global event handling
switch (event->type) {
case SDL_QUIT: {
game_switch_state(game, GAME_STATE_QUIT);
} break;
}
+ // Console event handling
+ if (game->console_enabled) {
+ switch (event->type) {
+ case SDL_KEYDOWN:
+ switch (event->key.keysym.sym) {
+ case SDLK_ESCAPE:
+ SDL_StopTextInput();
+ game->console_enabled = 0;
+ return 0;
+ default: {}
+ }
+
+ default: {}
+ }
+
+ return console_handle_event(game->console, event);
+ } else {
+ switch (event->type) {
+ case SDL_KEYUP: {
+ switch (event->key.keysym.sym) {
+ case SDLK_BACKQUOTE:
+ case SDLK_c: {
+ SDL_StartTextInput();
+ game->console_enabled = 1;
+ console_slide_down(game->console);
+ } break;
+ }
+ } break;
+ }
+ }
+
+ // State event handling
switch (game->state) {
case GAME_STATE_LEVEL:
return game_event_running(game, event);
trace_assert(game);
trace_assert(keyboard_state);
+ if (game->console_enabled) {
+ return 0;
+ }
+
switch (game->state) {
case GAME_STATE_SETTINGS:
case GAME_STATE_QUIT:
return 0;
}
+
+int game_load_level(Game *game, const char *level_filename)
+{
+ trace_assert(game);
+ trace_assert(level_filename);
+
+ 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));
+ }
+
+ 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),
+ destroy_level);
+ } else {
+ game->level = RESET_LT(
+ game->lt,
+ game->level,
+ create_level_from_level_editor(
+ game->level_editor));
+ }
+
+ if (game->level == NULL) {
+ return -1;
+ }
+
+ game_switch_state(game, GAME_STATE_LEVEL);
+
+ return 0;
+}
int game_over_check(const Game *game);
+int game_load_level(Game *game, const char *filepath);
+
#endif // GAME_H_
Boxes *boxes;
Labels *labels;
Regions *regions;
- Console *console;
- int console_enabled;
};
Level *create_level_from_level_editor(const LevelEditor *level_editor)
RETURN_LT(lt, NULL);
}
- level->console = PUSH_LT(
- lt,
- create_console(),
- destroy_console);
- if (level->console == NULL) {
- RETURN_LT(lt, NULL);
- }
-
return level;
}
return -1;
}
- if (level->console_enabled) {
- if (console_render(level->console, camera) < 0) {
- return -1;
- }
- }
-
return 0;
}
trace_assert(level);
trace_assert(delta_time > 0);
- if (level->console_enabled) {
- if (console_update(level->console, delta_time) < 0) {
- return -1;
- }
- }
-
if (level->state == LEVEL_STATE_PAUSE) {
return 0;
}
return 0;
}
-static
-int level_event_console(Level *level, const SDL_Event *event)
-{
- trace_assert(level);
- trace_assert(event);
-
- if (level->console_enabled) {
- switch (event->type) {
- case SDL_KEYDOWN:
- switch (event->key.keysym.sym) {
- case SDLK_ESCAPE:
- SDL_StopTextInput();
- level->console_enabled = 0;
- return 0;
-
- default: {}
- }
-
- default: {}
- }
- } else {
- switch (event->type) {
- case SDL_KEYUP: {
- switch (event->key.keysym.sym) {
- case SDLK_BACKQUOTE:
- case SDLK_c: {
- SDL_StartTextInput();
- level->console_enabled = 1;
- console_slide_down(level->console);
- } break;
- }
- } break;
- }
- }
-
- return console_handle_event(level->console, event);
-}
-
int level_event(Level *level, const SDL_Event *event,
Camera *camera, Sound_samples *sound_samples)
{
trace_assert(level);
trace_assert(event);
- level_event_console(level, event);
-
- if (level->console_enabled) {
- return 0;
- }
-
switch (level->state) {
case LEVEL_STATE_IDLE: {
return level_event_idle(level, event, camera, sound_samples);
trace_assert(level);
trace_assert(keyboard_state);
- if (level->console_enabled) {
- return 0;
- }
-
if (level->state == LEVEL_STATE_PAUSE) {
return 0;
}
+#include <ctype.h>
+#include <math.h>
+
#include "system/stacktrace.h"
+#include "game.h"
#include "game/level.h"
#include "sdl/renderer.h"
#include "system/log.h"
#include "ui/console_log.h"
#include "ui/edit_field.h"
#include "ui/history.h"
+#include "math/extrema.h"
#define FONT_WIDTH_SCALE 3.0f
#define FONT_HEIGHT_SCALE 3.0f
#define CONSOLE_ALPHA (0.80f)
#define CONSOLE_BACKGROUND (rgba(0.20f, 0.20f, 0.20f, CONSOLE_ALPHA))
#define CONSOLE_FOREGROUND (rgba(0.80f, 0.80f, 0.80f, CONSOLE_ALPHA))
+#define CONSOLE_ERROR (rgba(0.80f, 0.50f, 0.50f, CONSOLE_ALPHA))
+
+typedef struct {
+ const char *begin;
+ const char *end;
+} Token;
+
+
+static inline
+Token token(const char *begin, const char *end)
+{
+ Token t = {begin, end};
+ return t;
+}
+
+static inline
+int token_equals_str(Token t, const char *s)
+{
+ trace_assert(t.begin <= t.end);
+ size_t n1 = (size_t) (t.end - t.begin);
+ size_t n2 = strlen(s);
+ if (n1 != n2) return 0;
+ return memcmp(t.begin, s, n1) == 0;
+}
+
+static inline
+Token token_nt(const char *s)
+{
+ return token(s, s + strlen(s));
+}
+
+static inline
+void ltrim(Token *t)
+{
+ while (t->begin < t->end && isspace(*t->begin)) {
+ t->begin++;
+ }
+}
+
+static inline
+Token chop_word(Token *t)
+{
+ ltrim(t);
+ const char *end = t->begin;
+ while (end < t->end && !isspace(*end)) {
+ end++;
+ }
+ Token result = token(t->begin, end);
+ t->begin = end;
+ return result;
+}
struct Console
{
Edit_field *edit_field;
Console_Log *console_log;
History *history;
+ Game *game;
float a;
};
/* TODO(#356): Console does not support autocompletion */
/* TODO(#358): Console does not support copy, cut, paste operations */
-Console *create_console(void)
+Console *create_console(Game *game)
{
Lt *lt = create_lt();
RETURN_LT(lt, NULL);
}
+ console->game = game;
+
return console;
}
return -1;
}
- if (console_log_push_line(console->console_log, source_code, CONSOLE_FOREGROUND) < 0) {
+ if (console_log_push_line(console->console_log, source_code, NULL, CONSOLE_FOREGROUND) < 0) {
return -1;
}
+ Token input = token_nt(source_code);
+
+ Token command = chop_word(&input);
+ if (token_equals_str(command, "load")) {
+ Token level = chop_word(&input);
+ console_log_push_line(console->console_log, "Loading level:", NULL, CONSOLE_FOREGROUND);
+ console_log_push_line(console->console_log, level.begin, level.end, CONSOLE_FOREGROUND);
+ char level_name[256];
+ memset(level_name, 0, 256);
+ memcpy(level_name, level.begin, min_size_t((size_t)(level.end - level.begin), 255));
+
+ if (game_load_level(console->game, level_name) < 0) {
+ console_log_push_line(console->console_log, "Could not load level", NULL, CONSOLE_ERROR);
+ }
+ } else {
+ console_log_push_line(console->console_log, "Unknown command", NULL, CONSOLE_ERROR);
+ }
+
edit_field_clean(console->edit_field);
return 0;
typedef struct Console Console;
typedef struct Sprite_font Sprite_font;
+typedef struct Game Game;
-Console *create_console(void);
+Console *create_console(Game *game);
void destroy_console(Console *console);
int console_handle_event(Console *console,
return 0;
}
-int console_log_push_line(Console_Log *console_log, const char *line, Color color)
+int console_log_push_line(Console_Log *console_log,
+ const char *line,
+ const char *line_end,
+ Color color)
{
trace_assert(console_log);
trace_assert(line);
free(console_log->buffer[console_log->cursor]);
}
- console_log->buffer[console_log->cursor] = string_duplicate(line, NULL);
+ console_log->buffer[console_log->cursor] = string_duplicate(line, line_end);
console_log->colors[console_log->cursor] = color;
if (console_log->buffer[console_log->cursor] == NULL) {
int console_log_push_line(Console_Log *console_log,
const char *line,
+ const char *line_end,
Color color);
#endif // CONSOLE_LOG_H_