Initial commit basically lol

This commit is contained in:
Martin Dvořák 2026-08-28 20:51:26 +02:00
commit 6d77491228
5 changed files with 316 additions and 2 deletions

211
src/main.c Normal file
View file

@ -0,0 +1,211 @@
#include <SDL.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <SDL_ttf.h>
/*
* Global Constants
* These define the window dimensions and are used for centering graphics.
*/
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 600;
/*
* Player Structure
* Even if invisible, we keep the player state to allow for future gameplay logic.
*/
typedef struct {
float x, y;
float speed;
int size;
SDL_Color color;
} Player;
/*
* Game State Structure
* This is the 'Brain' of the game, containing everything needed to track the current session.
*/
typedef struct {
bool is_running; // Controls the main game loop
float escape_timer; // Tracks how long the Escape key has been held (in ms)
int visible_chars; // Number of characters currently revealed in the typewriter text
uint32_t last_char_time; // Timestamp of the last character revealed
const char* message; // The string to be displayed
TTF_Font* font; // Pointer to the loaded TrueType font
Player player; // The player object
} Game;
/**
* Initializes SDL, TTF, and the game state.
* Returns true if everything started correctly, false otherwise.
*/
bool init_game(Game *game) {
// Initialize SDL Video subsystem
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
return false;
}
// Initialize SDL_ttf for text rendering
if (TTF_Init() == -1) {
printf("SDL_ttf could not initialize! TTF_Error: %s\n", TTF_GetError());
return false;
}
// Load the font file from assets. Size is 48 for a cinematic look.
game->font = TTF_OpenFont("assets/font.ttf", 48);
if (!game->font) {
printf("CRITICAL: Failed to load font! TTF_Error: %s\n", TTF_GetError());
} else {
printf("SUCCESS: Font loaded successfully!\n");
}
// Setup initial state
game->is_running = true;
game->escape_timer = 0.0f;
game->visible_chars = 0;
game->last_char_time = SDL_GetTicks();
game->message = "Hello, human.";
game->player = (Player){ .x = 100, .y = 100, .speed = 0.5f, .size = 32, .color = {255, 0, 0, 255} };
return true;
}
/**
* Processes keyboard and window events.
* Handles the 'hold to quit' logic for the Escape key.
*/
void handle_input(Game *game, float delta_time) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
game->is_running = false;
}
}
const uint8_t *state = SDL_GetKeyboardState(NULL);
// ESCAPE KEY LOGIC:
// If Escape is held, we add the actual time passed (delta_time) to the timer.
if (state[SDL_SCANCODE_ESCAPE]) {
game->escape_timer += delta_time;
if (game->escape_timer >= 1000.0f) { // Exactly 1000ms = 1 second
game->is_running = false;
}
} else {
// Reset timer immediately if key is released
game->escape_timer = 0.0f;
}
// Player Movement (Invisible for now)
if (state[SDL_SCANCODE_UP]) game->player.y -= game->player.speed;
if (state[SDL_SCANCODE_DOWN]) game->player.y += game->player.speed;
if (state[SDL_SCANCODE_LEFT]) game->player.x -= game->player.speed;
if (state[SDL_SCANCODE_RIGHT]) game->player.x += game->player.speed;
}
/**
* Updates game logic independent of rendering.
* Handles the typewriter timing.
*/
void update(Game *game) {
// TYPEWRITER LOGIC:
// Check if enough time has passed since the last letter appeared.
uint32_t current_time = SDL_GetTicks();
if (current_time - game->last_char_time >= 150) {
if (game->visible_chars < (int)strlen(game->message)) {
game->visible_chars++;
game->last_char_time = current_time;
}
}
// Keep player within screen bounds
if (game->player.x < 0) game->player.x = 0;
if (game->player.x > SCREEN_WIDTH - game->player.size) game->player.x = SCREEN_WIDTH - game->player.size;
if (game->player.y < 0) game->player.y = 0;
if (game->player.y > SCREEN_HEIGHT - game->player.size) game->player.y = SCREEN_HEIGHT - game->player.size;
}
/**
* Handles all drawing operations.
* Clears screen and renders centered text.
*/
void render(SDL_Renderer *renderer, Game *game) {
// 1. Clear the screen to black
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
// 2. Render the revealed portion of the text
if (game->font) {
char buffer[64] = {0};
if (game->visible_chars > 0) {
// Copy only the number of characters currently 'revealed'
strncpy(buffer, game->message, game->visible_chars);
buffer[game->visible_chars] = '\0';
SDL_Color white = {255, 255, 255, 255};
SDL_Surface* surface = TTF_RenderText_Blended(game->font, buffer, white);
if (surface) {
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
// CENTER THE TEXT:
// Subtract half the text width/height from center screen coordinates.
SDL_Rect text_rect = {
(SCREEN_WIDTH - surface->w) / 2,
(SCREEN_HEIGHT - surface->h) / 2,
surface->w,
surface->h
};
SDL_RenderCopy(renderer, texture, NULL, &text_rect);
SDL_FreeSurface(surface);
SDL_DestroyTexture(texture);
}
}
}
// 3. Swap the backbuffer to the screen
SDL_RenderPresent(renderer);
}
int main(int argc, char* args[]) {
Game game;
if (!init_game(&game)) return 1;
SDL_Window *window = SDL_CreateWindow("C Game Template", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
// FPS Locking variables
const int TARGET_FPS = 60;
const uint32_t FRAME_DELAY = 1000 / TARGET_FPS;
while (game.is_running) {
uint32_t frame_start = SDL_GetTicks();
// Calculate Delta Time (time since last frame) in milliseconds
// Since we lock to 60FPS, this is usually around 16.6ms.
float delta_time = 1000.0f / TARGET_FPS;
handle_input(&game, delta_time);
update(&game);
render(renderer, &game);
// FRAME CAPPER:
// Calculate how long the frame took and sleep the remaining time.
uint32_t frame_time = SDL_GetTicks() - frame_start;
if (FRAME_DELAY > frame_time) {
SDL_Delay(FRAME_DELAY - frame_time);
}
}
// Cleanup memory
if (game.font) TTF_CloseFont(game.font);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
TTF_Quit();
SDL_Quit();
return 0;
}