Created
July 18, 2025 19:37
-
-
Save erikyuzwa/ba8c6abd5c92d6c5ba5df4ef71219f18 to your computer and use it in GitHub Desktop.
hello world using libtcod 2.1.1 and C
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define SDL_MAIN_USE_CALLBACKS | |
#include <SDL3/SDL.h> | |
#include <SDL3/SDL_main.h> | |
#include "libtcod.h" // Include the main libtcod header | |
#include <stdio.h> | |
#include <stdlib.h> | |
// Define console dimensions | |
#define SCREEN_WIDTH 80 | |
#define SCREEN_HEIGHT 50 | |
const TCOD_ColorRGB BLACK = { 0, 0, 0 }; | |
const TCOD_ColorRGB WHITE = { 255, 255, 255 }; | |
const TCOD_ColorRGB YELLOW = { 255, 255, 0 }; | |
typedef struct { | |
int x, y; | |
} Player; | |
typedef struct { | |
TCOD_Context* context; | |
TCOD_Tileset* tileset; | |
TCOD_Console* main_console; | |
TCOD_ContextParams params; | |
Player player; | |
bool is_running; | |
} AppState; | |
// Print libtcod log messages using SDL_Log | |
void print_log(const TCOD_LogMessage* message, void* userdata) { | |
SDL_Log("%s:%d:%d:%s\n", message->source, message->lineno, message->level, message->message); | |
} | |
SDL_AppResult SDL_AppInit(void** appstate, int argc, char** argv) { | |
SDL_Log("App Init"); | |
SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE); | |
TCOD_set_log_callback(print_log, NULL); | |
TCOD_set_log_level(TCOD_LOG_DEBUG); | |
AppState* state = (AppState*)SDL_calloc(1, sizeof(AppState)); | |
if (!state) return SDL_APP_FAILURE; | |
const char* FONT = "assets/dejavu12x12_gs_tc.png"; | |
state->tileset = TCOD_tileset_load(FONT, 32, 8, 256, TCOD_CHARMAP_TCOD); | |
// The main console to be presented. | |
state->main_console = TCOD_console_new(SCREEN_WIDTH, SCREEN_HEIGHT); | |
state->params = (TCOD_ContextParams) { | |
.console = state->main_console, | |
.window_title = "libtcod C sample", | |
.sdl_window_flags = SDL_WINDOW_RESIZABLE, | |
.renderer_type = TCOD_RENDERER_SDL2, //aka. SDL3 | |
.tileset = state->tileset, | |
.vsync = false, | |
.argc = argc, | |
.argv = (const char* const*)argv, | |
}; | |
TCOD_context_new(&state->params, &state->context); | |
state->player = (Player){ SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 }; | |
state->is_running = true; | |
*appstate = state; | |
return SDL_APP_CONTINUE; | |
} | |
SDL_AppResult SDL_AppIterate(void* appstate) { | |
AppState* state = (AppState*)appstate; | |
// clear the console | |
TCOD_console_clear(state->main_console); | |
// render our player | |
TCOD_console_put_rgb(state->main_console, state->player.x, state->player.y, '@', &YELLOW, &BLACK, 0); | |
// update the game screen | |
TCOD_context_present(state->context, state->main_console, NULL); | |
// return SDL_APP_SUCCESS to quit | |
return state->is_running ? SDL_APP_CONTINUE : SDL_APP_SUCCESS; | |
} | |
SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) { | |
AppState* state = (AppState*)appstate; | |
TCOD_context_convert_event_coordinates(state->context, event); | |
switch (event->type) { | |
case SDL_EVENT_WINDOW_CLOSE_REQUESTED: | |
SDL_Log("Window close requested"); | |
state->is_running = false; | |
break; | |
case SDL_EVENT_KEY_DOWN: | |
switch (event->key.key) { | |
case SDLK_ESCAPE: | |
state->is_running = false; | |
break; | |
case SDLK_UP: | |
state->player.y -= 1; | |
break; | |
case SDLK_DOWN: | |
state->player.y += 1; | |
break; | |
case SDLK_LEFT: | |
state->player.x -= 1; | |
break; | |
case SDLK_RIGHT: | |
state->player.x += 1; | |
break; | |
} | |
break; | |
case SDL_EVENT_QUIT: | |
state->is_running = false; | |
break; | |
} | |
return SDL_APP_CONTINUE; | |
} | |
void SDL_AppQuit(void* appstate, SDL_AppResult result) { | |
SDL_Log("App Quit"); | |
if (appstate != NULL) { | |
AppState* state = (AppState*)appstate; | |
// TODO: free up anything else | |
SDL_free(state); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment