diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..f0ea327 Binary files /dev/null and b/.DS_Store differ diff --git a/README.md b/README.md index 0a4cf5d..3287a4c 100644 --- a/README.md +++ b/README.md @@ -63,4 +63,10 @@ The project includes a `Makefile` to automate the compilation process. - [ ] Implement transition from Intro Sequence to Active Gameplay. - [ ] Integrate sprite rendering for the player character. - [ ] Expand game world with interactive objects. -- [ ] Add background music and sound effects using `SDL2_mixer`. \ No newline at end of file +- [ ] Add background music and sound effects using `SDL2_mixer`. + +## 🔊 Audio Credits +- dialog-beep.wav: Sound effect from [freesound.org](https://freesound.org/people/nugsano/sounds/842200/) by nugsano + +## 🔤 Font Credits +- font.ttf: Determination Mono Web Font from [FontSpace](https://www.fontspace.com/determination-mono-web-font-f23209) \ No newline at end of file diff --git a/assets/.DS_Store b/assets/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/assets/.DS_Store differ diff --git a/assets/dialog-beep.wav b/assets/dialog-beep.wav new file mode 100644 index 0000000..b018739 Binary files /dev/null and b/assets/dialog-beep.wav differ diff --git a/assets/font.ttf b/assets/font.ttf index ab68fb1..28274a9 100644 Binary files a/assets/font.ttf and b/assets/font.ttf differ diff --git a/game b/game new file mode 100755 index 0000000..d8910ce Binary files /dev/null and b/game differ diff --git a/src/main.c b/src/main.c index 7438d94..5085294 100644 --- a/src/main.c +++ b/src/main.c @@ -3,6 +3,8 @@ #include #include #include +#include +#include /* * Global Constants @@ -22,7 +24,7 @@ typedef struct { SDL_Color color; } Player; -/* +/* * Game State Structure * This is the 'Brain' of the game, containing everything needed to track the current session. */ @@ -33,6 +35,11 @@ typedef struct { 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 + Mix_Chunk* beep_chunk; // Sound effect for each typed character + // Screen shake effect + float shake_timer; // Time remaining for shake effect (ms) + float shake_duration; // Total duration of shake effect when triggered (ms) + float shake_intensity; // Current intensity of shake (pixels) Player player; // The player object } Game; @@ -53,6 +60,12 @@ bool init_game(Game *game) { return false; } + // Initialize SDL_mixer for audio with lower frequency (22050 Hz) to lower pitch of beep + if (Mix_OpenAudio(22050, MIX_DEFAULT_FORMAT, 2, 2048) < 0) { + printf("SDL_mixer could not open audio! Mix_Error: %s\n", Mix_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) { @@ -61,14 +74,27 @@ bool init_game(Game *game) { printf("SUCCESS: Font loaded successfully!\n"); } + // Load the beep sound effect + game->beep_chunk = Mix_LoadWAV("assets/dialog-beep.wav"); + if (!game->beep_chunk) { + printf("WARNING: Failed to load beep sound! Mix_Error: %s\n", Mix_GetError()); + // Not critical, continue without sound + } + // 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."; + // Initialize shake effect + game->shake_timer = 0.0f; + game->shake_duration = 300.0f; // 300ms shake duration + game->shake_intensity = 0.0f; + // Seed random number generator for shake effect + srand((unsigned int)SDL_GetTicks()); game->player = (Player){ .x = 100, .y = 100, .speed = 0.5f, .size = 32, .color = {255, 0, 0, 255} }; - + return true; } @@ -110,12 +136,32 @@ void handle_input(Game *game, float delta_time) { * Handles the typewriter timing. */ void update(Game *game) { + // UPDATE SHAKE EFFECT: + // Decrease shake timer and calculate current intensity + if (game->shake_timer > 0.0f) { + game->shake_timer -= 16.67f; // Approximate 60 FPS frame time + if (game->shake_timer < 0.0f) game->shake_timer = 0.0f; + // Calculate intensity based on remaining timer (linear fade out) + game->shake_intensity = (game->shake_timer / game->shake_duration) * 4.0f; // Max 4px shake + } else { + game->shake_intensity = 0.0f; + } + // 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 (current_time - game->last_char_time >= 333) { // Adjusted timing if (game->visible_chars < (int)strlen(game->message)) { + // Check if the character to be revealed is a space + char current_char = game->message[game->visible_chars]; game->visible_chars++; + + // Play beep for each character except spaces (already lower pitch due to mixer frequency) + if (game->beep_chunk && current_char != ' ') { + Mix_PlayChannel(-1, game->beep_chunk, 0); + // Trigger shake effect for non-space characters + game->shake_timer = game->shake_duration; + } game->last_char_time = current_time; } } @@ -150,13 +196,16 @@ void render(SDL_Renderer *renderer, Game *game) { if (surface) { SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface); - // CENTER THE TEXT: + // CENTER THE TEXT WITH SHAKE: // 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 + // Add shake offset for text jitter effect + int shake_offset_x = (rand() % (int)(game->shake_intensity * 2 + 1)) - game->shake_intensity; + int shake_offset_y = (rand() % (int)(game->shake_intensity * 2 + 1)) - game->shake_intensity; + SDL_Rect text_rect = { + (SCREEN_WIDTH - surface->w) / 2 + shake_offset_x, + (SCREEN_HEIGHT - surface->h) / 2 + shake_offset_y, + surface->w, + surface->h }; SDL_RenderCopy(renderer, texture, NULL, &text_rect); @@ -202,6 +251,9 @@ int main(int argc, char* args[]) { // Cleanup memory if (game.font) TTF_CloseFont(game.font); + if (game.beep_chunk) Mix_FreeChunk(game.beep_chunk); + Mix_CloseAudio(); + Mix_Quit(); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); TTF_Quit();