-#include <SDL2/SDL.h>
-#include <SDL2/SDL_mixer.h>
+#include <SDL.h>
#include "system/stacktrace.h"
#include <stdio.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;
Broadcast *broadcast;
Sprite_font *font;
LevelPicker *level_picker;
+ LevelEditor *level_editor;
Level *level;
Sound_samples *sound_samples;
Camera *camera;
{
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);
}
RETURN_LT(lt, NULL);
}
- game->level = NULL;
-
game->sound_samples = PUSH_LT(
lt,
create_sound_samples(
lt,
texture_from_bmp("images/cursor.bmp", renderer),
SDL_DestroyTexture);
- /* TODO(#773): If a specific blending is not supported that should not crash the entire game */
if (SDL_SetTextureBlendMode(
game->texture_cursor,
SDL_ComposeCustomBlendMode(
SDL_BLENDFACTOR_ONE,
SDL_BLENDFACTOR_ZERO,
SDL_BLENDOPERATION_ADD)) < 0) {
- log_fail("SDL error: %s\n", SDL_GetError());
- RETURN_LT(lt, NULL);
+ log_warn("SDL error: %s\n", SDL_GetError());
}
game->cursor_x = 0;
game->cursor_y = 0;
if (level_render(game->level, game->camera) < 0) {
return -1;
}
-
- 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;
- }
} break;
case GAME_STATE_CONSOLE: {
return -1;
}
- if (console_render(game->console, game->renderer) < 0) {
+ if (console_render(game->console, game->camera, game->renderer) < 0) {
return -1;
}
} break;
return -1;
}
- 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) {
+ 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_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;
}
return -1;
}
- const char *level_folder = 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));
+ }
+
+ if (game->level_editor == NULL) {
+ return -1;
+ }
- if (level_folder != NULL) {
if (game->level == NULL) {
game->level = PUSH_LT(
game->lt,
- create_level_from_file(level_folder, game->broadcast),
+ create_level_from_level_editor(
+ game->level_editor,
+ game->broadcast),
destroy_level);
} else {
game->level = RESET_LT(
game->lt,
game->level,
- create_level_from_file(level_folder, game->broadcast));
+ create_level_from_level_editor(
+ game->level_editor,
+ game->broadcast));
}
if (game->level == NULL) {
} break;
+ case GAME_STATE_LEVEL_EDITOR: {
+ if (level_editor_focus_camera(
+ game->level_editor,
+ game->camera) < 0) {
+ return -1;
+ }
+ } break;
+
case GAME_STATE_PAUSE:
case GAME_STATE_QUIT:
break;
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:
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: {
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(
- level_filename,
+ create_level_from_level_editor(
+ game->level_editor,
game->broadcast));
-
if (game->level == NULL) {
log_fail("Could not reload level %s\n", level_filename);
game->state = GAME_STATE_QUIT;
camera_disable_debug_mode(game->camera);
} break;
- case SDLK_q:
- if (level_reload_preserve_player(game->level, game->broadcast) < 0) {
- log_fail("Could not reload level\n");
- 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;
- case SDL_MOUSEMOTION:
- game->cursor_x = event->motion.x;
- game->cursor_y = event->motion.y;
- break;
+ } break;
}
return level_event(game->level, 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:
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());
+ }
- case SDL_MOUSEMOTION:
- game->cursor_x = event->motion.x;
- game->cursor_y = event->motion.y;
- break;
+ if (game->level_editor == NULL) {
+ return -1;
+ }
- default: {}
+ 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 (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)
{
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);
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;
}
case GAME_STATE_QUIT:
case GAME_STATE_PAUSE:
case GAME_STATE_CONSOLE:
+ case GAME_STATE_LEVEL_EDITOR:
return 0;
case GAME_STATE_RUNNING:
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;
+}