I’m having an issue with Death Animation of EnemyA. It is a spritesheet with 8 frames and sometimes it completes one full cycle and sometimes it doesn’t. I also have a MAP CASE where press Space to continue to next level does not work. Any Advice? Game Project
#include <SDL.h>
#include <SDL_ttf.h>
#include <SDL_image.h>
#include <SDL_mixer.h>
#include <iostream>
#include <memory>
#include <vector>
#include "Game.h"
#include "Button.h"
#include "Story.h"
#include "StoryLines.h"
#include "Sprite.h"
#include "TextureManager.h"
#include "SoundManager.h"
#include "GameState.h"
#include "Combat.h"
// Constants
constexpr int FRAME_DELAY = 16; // Approximately 60 FPS
constexpr int FONT_SIZE = 30;
constexpr int TEXT_WRAP_WIDTH = 600;
// Volume bar constants
constexpr int VOLUME_BAR_WIDTH = 300;
constexpr int VOLUME_BAR_HEIGHT = 20;
constexpr SDL_Color VOLUME_BAR_COLOR = { 0, 255, 0, 255 };
constexpr SDL_Color VOLUME_BAR_BACKGROUND_COLOR = { 100, 100, 100, 255 };
// Declare global objects
TTF_Font* storylineFont = nullptr;
TTF_Font* defaultFont = nullptr;
SDL_Texture* menuBackdropTexture = nullptr;
SDL_Texture* speechBubbleTexture = nullptr;
SDL_Texture* storyBackdropTexture = nullptr;
SDL_Texture* mapBackdropTexture = nullptr;
Sprite* Knight_idle = nullptr;
SoundManager soundManager;
SDL_Renderer* renderer = nullptr;
struct KnightPosition {
int x;
int y;
int width;
int height;
};
//Other codes
// Load textures
menuBackdropTexture = TextureManager::LoadTexture("assets/Backdrops/menu_backdrop.png", renderer);
speechBubbleTexture = TextureManager::LoadTexture("assets/SpeechStuff/speech_bubble.png", renderer);
mapBackdropTexture = TextureManager::LoadTexture("assets/Backdrops/Map.png", renderer);
if (!mapBackdropTexture) {
SDL_Log("Failed to load map backdrop texture");
}
// Initialize Knight_idle as a Sprite
Knight_idle = new Sprite(renderer, "assets/Sprites/MC/idle.png");
if (!Knight_idle->loadTexture()) {
SDL_Log("Failed to load Knight idle sprite.");
return 1;
}
Knight_idle->setAnimationParameters(128, 126, 8, 0.1f);
if (!menuBackdropTexture || !speechBubbleTexture) {
SDL_Log("Failed to load textures.");
TTF_CloseFont(defaultFont);
TTF_CloseFont(storylineFont);
soundManager.shutdown();
TTF_Quit();
IMG_Quit();
SDL_Quit();
return 1;
}
// Load music
if (!soundManager.loadMusic("assets/Music/background_music.wav", "background")) {
SDL_Log("Failed to load background music.");
}
if (!soundManager.loadMusic("assets/Music/story_music.wav", "story")) {
SDL_Log("Failed to load story music.");
}
if (!soundManager.loadMusic("assets/Music/combat_music.wav", "combat")) {
SDL_Log("Failed to load combat music.");
}
if (!soundManager.loadMusic("assets/Music/Lvl1_Story.wav", "lvl1_story")) {
SDL_Log("Failed to load Level 1 Story music.");
}
if (!soundManager.loadMusic("assets/Music/Lvl2_Story.wav", "lvl2_story")) {
SDL_Log("Failed to load Level 2 Story music.");
}
// Initialize story instances
static Story storyInstance(renderer, storylineFont, storyLines, 50);
static Story level1StoryInstance(renderer, storylineFont, level1StoryLines, 50);
static Story level1WinInstance(renderer, storylineFont, level1Win, 50);
static Story level1LoseInstance(renderer, storylineFont, level1Lose, 50);
static Story level2StoryInstance(renderer, storylineFont, level2StoryLines, 50);
static Story level2WinInstance(renderer, storylineFont, level2Win, 50);
static Story level2LoseInstance(renderer, storylineFont, level2Lose, 50);
// Button setup
constexpr int BUTTON_WIDTH = 180;
constexpr int ABOUT_BUTTON_WIDTH = 250;
constexpr int BUTTON_HEIGHT = 70;
constexpr int BUTTON_SPACING = 50;
constexpr int NUM_BUTTONS = 4;
int windowWidth, windowHeight;
SDL_GetRendererOutputSize(renderer, &windowWidth, &windowHeight);
int totalButtonHeight = NUM_BUTTONS * BUTTON_HEIGHT + (NUM_BUTTONS - 1) * BUTTON_SPACING;
int startY = (windowHeight - totalButtonHeight) / 2 + 50;
Button buttons[NUM_BUTTONS] = {
Button((windowWidth - BUTTON_WIDTH) / 2, startY, BUTTON_WIDTH, BUTTON_HEIGHT, "assets/Buttons/start button.png", "assets/Buttons/clicked sta2.png", "assets/Buttons/clicked sta2.png", renderer),
Button((windowWidth - BUTTON_WIDTH) / 2, startY + (BUTTON_HEIGHT + BUTTON_SPACING), BUTTON_WIDTH, BUTTON_HEIGHT, "assets/Buttons/tutorial button.png", "assets/Buttons/clicked tutorial2.png", "assets/Buttons/clicked tutorial2.png", renderer),
Button((windowWidth - BUTTON_WIDTH) / 2, startY + 2 * (BUTTON_HEIGHT + BUTTON_SPACING), BUTTON_WIDTH, BUTTON_HEIGHT, "assets/Buttons/option button.png", "assets/Buttons/option_clicked.png", "assets/Buttons/option_clicked.png", renderer),
Button((windowWidth - ABOUT_BUTTON_WIDTH) / 2, startY + 3 * (BUTTON_HEIGHT + BUTTON_SPACING), ABOUT_BUTTON_WIDTH, BUTTON_HEIGHT, "assets/Buttons/about develper button.png", "assets/Buttons/clicked ab de 2.png", "assets/Buttons/clicked ab de 2.png", renderer)
};
buttons[0].setOnClick([&]() {
gameState = STORY;
storyInstance.reset();
storyBackdropTexture = TextureManager::LoadTexture("assets/Backdrops/castle/castle1.jpg", renderer);
soundManager.stopMusic();
soundManager.playMusic("story", -1);
});
buttons[1].setOnClick([&]() {
gameState = TUTORIAL;
});
buttons[2].setOnClick([&]() {
gameState = OPTIONS;
});
buttons[3].setOnClick([&]() {
gameState = ABOUT;
});
int musicVolume = MIX_MAX_VOLUME;
SDL_Texture* combatBackdropTexture = nullptr;
// Main Game Loop
while (gameState != EXIT) {
double deltaTime = getDeltaTime();
frameStart = SDL_GetTicks();
SDL_Event event;
// Check if the game state has changed
if (gameState != previousGameState) {
// Print the new game state name
switch (gameState) {
case MENU:
printf("Current game state: MENU\n");
break;
case STORY:
printf("Current game state: STORY\n");
break;
case TUTORIAL:
printf("Current game state: TUTORIAL\n");
break;
case OPTIONS:
printf("Current game state: OPTIONS\n");
break;
case ABOUT:
printf("Current game state: ABOUT\n");
break;
case PLAYING:
printf("Current game state: PLAYING\n");
break;
case LEVEL1_WIN:
printf("Current game state: LEVEL1_WIN\n");
break;
case LEVEL1_LOSE:
printf("Current game state: LEVEL1_LOSE\n");
break;
case LEVEL1_STORY:
printf("Current game state: LEVEL1_STORY\n");
break;
case LEVEL2_WIN:
printf("Current game state: LEVEL2_WIN\n");
break;
case LEVEL2_LOSE:
printf("Current game state: LEVEL2_LOSE\n");
break;
case LEVEL2_STORY:
printf("Current game state: LEVEL2_STORY\n");
break;
case MAP:
printf("Current game state: MAP\n");
break;
case EXIT:
printf("Current game state: EXIT\n");
break;
default:
printf("Current game state: UNKNOWN\n");
break;
}
// Update the previous game state
previousGameState = gameState;
}
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT || (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE)) {
gameState = EXIT;
}
// Handle returning to menu
if ((gameState == TUTORIAL || gameState == OPTIONS || gameState == ABOUT ||
gameState == LEVEL1_LOSE || gameState == LEVEL2_LOSE) && event.type == SDL_KEYDOWN) {
if (event.key.keysym.sym == SDLK_b) {
gameState = MENU;
for (int i = 0; i < NUM_BUTTONS; ++i) {
buttons[i].resetState();
}
}
}
// Handle story progression
if ((gameState == STORY || gameState == LEVEL1_STORY || gameState == LEVEL1_WIN ||
gameState == LEVEL1_LOSE || gameState == LEVEL2_WIN || gameState == LEVEL2_LOSE || gameState == MAP) &&
event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_SPACE) {
if (gameState == STORY && storyInstance.isComplete()) {
soundManager.stopMusic();
gameState = LEVEL1_STORY;
level1StoryInstance.reset();
SDL_DestroyTexture(storyBackdropTexture);
storyBackdropTexture = nullptr;
soundManager.playMusic("lvl1_story", -1);
}
else if (gameState == LEVEL1_STORY && level1StoryInstance.isComplete()) {
combatBackdropTexture = TextureManager::LoadTexture("assets/Backdrops/forest/forest2.jpg", renderer);
gameState = PLAYING;
initCombatWithRenderer(1, renderer);
soundManager.playMusic("combat", -1);
}
else if (gameState == LEVEL1_WIN && level1WinInstance.isComplete()) {
gameState = MAP;
currentLevel = 2; // Only increment level when going to map after win
soundManager.stopMusic();
soundManager.playMusic("story", -1);
}
else if (gameState == LEVEL2_WIN && level2WinInstance.isComplete()) {
gameState = MAP;
soundManager.stopMusic();
soundManager.playMusic("story", -1);
}
else if (gameState == STORY) {
storyInstance.advanceToNextLine();
}
else if (gameState == LEVEL1_STORY) {
level1StoryInstance.advanceToNextLine();
}
else if (gameState == LEVEL1_LOSE) {
level1LoseInstance.advanceToNextLine();
}
else if (gameState == LEVEL2_LOSE) {
level2LoseInstance.advanceToNextLine();
}
else if (gameState == MAP) {
renderText(renderer, defaultFont, "Press SPACE to continue", { 255, 255, 255, 255 },
(windowWidth - 300) / 2, windowHeight - 50);
if (currentLevel == 1) {
currentLevel = 2; // Only increment level when in MAP state and SPACE is pressed
combatBackdropTexture = TextureManager::LoadTexture("assets/Backdrops/snow land/snow land4.jpg", renderer);
gameState = PLAYING;
initCombatWithRenderer(2, renderer);
soundManager.playMusic("combat", -1);
}
else if (currentLevel == 2) {
currentLevel = 3; // Increment to next level
}
}
}
// Handle buttons
if (gameState == MENU) {
for (int i = 0; i < NUM_BUTTONS; ++i) {
buttons[i].handleEvent(&event);
}
}
if (gameState == OPTIONS) {
if (event.type == SDL_KEYDOWN) {
switch (event.key.keysym.sym) {
case SDLK_UP:
if (musicVolume < MIX_MAX_VOLUME) {
musicVolume += 8;
if (musicVolume > MIX_MAX_VOLUME) musicVolume = MIX_MAX_VOLUME;
Mix_VolumeMusic(musicVolume);
}
break;
case SDLK_DOWN:
if (musicVolume > 0) {
musicVolume -= 8;
if (musicVolume < 0) musicVolume = 0;
Mix_VolumeMusic(musicVolume);
}
break;
}
}
}
// Handle combat
if (gameState == PLAYING) {
CombatContext context = {
renderer,
defaultFont,
{255, 255, 255, 255},
{255, 0, 0, 255},
{0, 0, 255, 255},
{0, 0, 0, 255}
};
handleCombatEvent(&event, &context);
if (gameOver) {
printf("Game over detected\n");
SDL_DestroyTexture(combatBackdropTexture);
combatBackdropTexture = nullptr;
if (currentLevel == 1) {
gameState = LEVEL1_LOSE;
level1LoseInstance.reset();
}
else if (currentLevel == 2) {
gameState = LEVEL2_LOSE;
level2LoseInstance.reset();
}
soundManager.stopMusic();
soundManager.playMusic("story", -1);
}
else if (victory1) {
printf("Victory 1 detected\n");
SDL_DestroyTexture(combatBackdropTexture);
combatBackdropTexture = nullptr;
gameState = LEVEL1_WIN;
level1WinInstance.reset();
soundManager.stopMusic();
soundManager.playMusic("story", -1);
currentLevel = 1; // Make sure we don't increment level here
}
else if (victory2) {
printf("Victory 2 detected\n");
SDL_DestroyTexture(combatBackdropTexture);
combatBackdropTexture = nullptr;
gameState = LEVEL2_WIN;
level2WinInstance.reset();
soundManager.playMusic("lvl2_story", -1);
}
}
}
// Update knight animation with proper delta time
if (Knight_idle) {
Knight_idle->updateAnimation(static_cast<float>(deltaTime));
}
// Rendering
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
switch (gameState) {
case MENU:
if (!soundManager.isPlayingMusic()) {
soundManager.playMusic("background", -1);
}
SDL_RenderCopy(renderer, menuBackdropTexture, nullptr, nullptr);
for (int i = 0; i < NUM_BUTTONS; ++i) {
buttons[i].render(renderer);
}
break;
case STORY: {
if (storyBackdropTexture) {
SDL_RenderCopy(renderer, storyBackdropTexture, nullptr, nullptr);
}
SDL_Rect speechBubbleRect = {
(windowWidth - 800) / 2,
windowHeight - 400,
800,
300
};
SDL_RenderCopy(renderer, speechBubbleTexture, nullptr, &speechBubbleRect);
storyInstance.update(SDL_GetTicks());
storyInstance.render(renderer,
speechBubbleRect.x + 50,
speechBubbleRect.y + 90,
TEXT_WRAP_WIDTH);
if (storyInstance.isComplete()) {
renderText(renderer, defaultFont, "Press SPACE to continue", { 255, 255, 255, 255 },
(windowWidth - 300) / 2, windowHeight - 50);
}
break;
}
case LEVEL1_STORY: {
static SDL_Texture* level1StoryBackdrop = nullptr;
if (!level1StoryBackdrop) {
level1StoryBackdrop = TextureManager::LoadTexture("assets/SpeechStuff/Forestwithspeech.png", renderer);
}
if (level1StoryBackdrop) {
SDL_RenderCopy(renderer, level1StoryBackdrop, nullptr, nullptr);
}
if (Knight_idle) {
SDL_Rect knightRect = {
((windowWidth - 200) / 2) - 380,
windowHeight - 750,
200,
300
};
Knight_idle->render(knightRect.x, knightRect.y, knightRect.w, knightRect.h);
}
SDL_Rect speechBubbleRect = {
(windowWidth - 800) / 2,
windowHeight - 400,
800,
300
};
SDL_RenderCopy(renderer, speechBubbleTexture, nullptr, &speechBubbleRect);
level1StoryInstance.update(SDL_GetTicks());
level1StoryInstance.render(renderer,
speechBubbleRect.x + 50,
speechBubbleRect.y + 90,
TEXT_WRAP_WIDTH);
if (level1StoryInstance.isComplete()) {
renderText(renderer, defaultFont, "Press SPACE to continue", { 255, 255, 255, 255 },
(windowWidth - 300) / 2, windowHeight - 50);
}
break;
}
case PLAYING: {
if (combatBackdropTexture) {
SDL_RenderCopy(renderer, combatBackdropTexture, nullptr, nullptr);
}
// Render Knight_idle based on the current level
if (Knight_idle) {
int currentLevelIndex = currentLevel - 1;
SDL_Rect knightRect = {
knightPositions[currentLevelIndex].x,
knightPositions[currentLevelIndex].y,
knightPositions[currentLevelIndex].width,
knightPositions[currentLevelIndex].height
};
Knight_idle->updateAnimation(static_cast<float>(deltaTime));
Knight_idle->render(knightRect.x, knightRect.y, knightRect.w, knightRect.h);
}
// Update enemy animation
if (currentEnemy) {
currentEnemy->updateAnimation(static_cast<float>(deltaTime));
// Check if attack animation is complete
if (currentEnemy->getAnimationState() == EnemyState::ATTACK &&
currentEnemy->isAnimationComplete()) {
currentEnemy->setAnimationState(EnemyState::IDLE);
}
// Check if enemy is dead
if (currentEnemy->getHealth() <= 0) {
currentEnemy->setAnimationState(EnemyState::DEATH);
// Use a timer to manage the delay
static Uint32 deathTimer = SDL_GetTicks();
const Uint32 DEATH_DELAY = 3000; // 3 seconds delay
if (SDL_GetTicks() - deathTimer >= DEATH_DELAY) {
// Move to the next level or end the game
if (currentLevel == 1) {
gameState = LEVEL1_WIN;
level1WinInstance.reset();
}
else if (currentLevel == 2) {
gameState = LEVEL2_WIN;
level2WinInstance.reset();
}
else if (currentLevel == 3) {
// Handle level 3 win
}
// Cleanup combat resources
cleanupCombat();
}
}
}
// Render combat UI elements
CombatContext context = {
renderer,
defaultFont,
{255, 255, 255, 255},
{255, 0, 0, 255},
{0, 0, 255, 255},
{0, 0, 0, 255}
};
renderCombat(&context);
break;
}
case LEVEL1_WIN: {
static SDL_Texture* level1StoryBackdrop = nullptr;
if (!level1StoryBackdrop) {
level1StoryBackdrop = TextureManager::LoadTexture("assets/Backdrops/castle/castle1.jpg", renderer);
}
if (level1StoryBackdrop) {
SDL_RenderCopy(renderer, level1StoryBackdrop, nullptr, nullptr);
}
static bool messageDisplayed = false;
if (!messageDisplayed) {
renderText(renderer, defaultFont, "Press SPACE to continue", { 255, 255, 255, 255 },
(windowWidth - 300) / 2, windowHeight - 50);
messageDisplayed = true;
}
while (SDL_PollEvent(&event)) {
if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_SPACE) {
messageDisplayed = false;
gameState = MAP;
}
}
break;
}
case LEVEL1_LOSE: {
static SDL_Texture* level1StoryBackdrop = nullptr;
if (!level1StoryBackdrop) {
level1StoryBackdrop = TextureManager::LoadTexture("assets/Backdrops/castle/castle1.jpg", renderer);
}
if (level1StoryBackdrop) {
SDL_RenderCopy(renderer, level1StoryBackdrop, nullptr, nullptr);
}
SDL_Rect speechBubbleRect = {
(windowWidth - 800) / 2,
windowHeight - 400,
800,
300
};
SDL_RenderCopy(renderer, speechBubbleTexture, nullptr, &speechBubbleRect);
level1LoseInstance.update(SDL_GetTicks());
level1LoseInstance.render(renderer,
speechBubbleRect.x + 50,
speechBubbleRect.y + 90,
TEXT_WRAP_WIDTH);
if (level1LoseInstance.isComplete()) {
renderText(renderer, defaultFont, "Press SPACE to return to menu", { 255, 255, 255, 255 },
(windowWidth - 300) / 2, windowHeight - 50);
}
break;
}
case LEVEL2_WIN: {
static SDL_Texture* level2WinBackdrop = nullptr;
if (!level2WinBackdrop) {
level2WinBackdrop = TextureManager::LoadTexture("assets/Backdrops/snow land/snow land4.jpg", renderer);
}
if (level2WinBackdrop) {
SDL_RenderCopy(renderer, level2WinBackdrop, nullptr, nullptr);
}
SDL_Rect speechBubbleRect = {
(windowWidth - 800) / 2,
windowHeight - 400,
800,
300
};
SDL_RenderCopy(renderer, speechBubbleTexture, nullptr, &speechBubbleRect);
level2WinInstance.update(SDL_GetTicks());
level2WinInstance.render(renderer,
speechBubbleRect.x + 50,
speechBubbleRect.y + 90,
TEXT_WRAP_WIDTH);
if (level2WinInstance.isComplete()) {
renderText(renderer, defaultFont, "Press SPACE to continue", { 255, 255, 255, 255 },
(windowWidth - 300) / 2, windowHeight - 50);
}
break;
}
case LEVEL2_LOSE: {
static SDL_Texture* level2LoseBackdrop = nullptr;
if (!level2LoseBackdrop) {
level2LoseBackdrop = TextureManager::LoadTexture("assets/Backdrops/snow land/snow land4.jpg", renderer);
}
if (level2LoseBackdrop) {
SDL_RenderCopy(renderer, level2LoseBackdrop, nullptr, nullptr);
}
SDL_Rect speechBubbleRect = {
(windowWidth - 800) / 2,
windowHeight - 400,
800,
300
};
SDL_RenderCopy(renderer, speechBubbleTexture, nullptr, &speechBubbleRect);
level2LoseInstance.update(SDL_GetTicks());
level2LoseInstance.render(renderer,
speechBubbleRect.x + 50,
speechBubbleRect.y + 90,
TEXT_WRAP_WIDTH);
if (level2LoseInstance.isComplete()) {
renderText(renderer, defaultFont, "Press SPACE to return to menu", { 255, 255, 255, 255 },
(windowWidth - 300) / 2, windowHeight - 50);
}
break;
}
case TUTORIAL: {
SDL_Rect speechBubbleRect = {
(windowWidth - 800) / 2,
windowHeight - 400,
800,
300
};
SDL_RenderCopy(renderer, speechBubbleTexture, nullptr, &speechBubbleRect);
break;
}
case OPTIONS: {
const std::string optionsMessage =
"Options Menu:\n"
"Here you can configure game settings such as audio volume.\n"
"Use the Up/Down arrow keys to adjust music volume.";
const std::string returnMessage = "Press B to return to menu";
renderText(renderer, defaultFont, optionsMessage, { 255, 255, 255, 255 },
(windowWidth - TEXT_WRAP_WIDTH) / 2, 100, TEXT_WRAP_WIDTH);
renderText(renderer, defaultFont, returnMessage, { 255, 255, 255, 255 },
(windowWidth - 300) / 2, windowHeight - 50);
std::string musicVolumeText = "Music Volume: " + std::to_string(musicVolume);
renderText(renderer, defaultFont, musicVolumeText, { 255, 255, 255, 255 },
(windowWidth - 300) / 2, windowHeight - 150);
int volumeBarX = (windowWidth - VOLUME_BAR_WIDTH) / 2;
int volumeBarY = windowHeight - 100;
SDL_Rect volumeBarBackground = { volumeBarX, volumeBarY, VOLUME_BAR_WIDTH, VOLUME_BAR_HEIGHT };
SDL_SetRenderDrawColor(renderer, VOLUME_BAR_BACKGROUND_COLOR.r, VOLUME_BAR_BACKGROUND_COLOR.g,
VOLUME_BAR_BACKGROUND_COLOR.b, VOLUME_BAR_BACKGROUND_COLOR.a);
SDL_RenderFillRect(renderer, &volumeBarBackground);
int filledWidth = (musicVolume * VOLUME_BAR_WIDTH) / MIX_MAX_VOLUME;
SDL_Rect volumeBarFilled = { volumeBarX, volumeBarY, filledWidth, VOLUME_BAR_HEIGHT };
SDL_SetRenderDrawColor(renderer, VOLUME_BAR_COLOR.r, VOLUME_BAR_COLOR.g,
VOLUME_BAR_COLOR.b, VOLUME_BAR_COLOR.a);
SDL_RenderFillRect(renderer, &volumeBarFilled);
break;
}
case ABOUT: {
const std::string aboutMessage =
"Knight Revenger is a story-driven RPG built using SDL in C++, where you play as a wrongfully exiled Knight on a quest to reclaim your honor and uncover the truth behind your expulsion. Featuring challenging gameplay, memorable characters, and immersive visuals and music, the game explores themes of redemption, identity, and justice in a richly crafted world.\n"
"This project is brought to you by a diverse team of students, blending creativity and collaboration to deliver an unforgettable gaming experience.\n"
"Thank you for supporting our journey!";
const std::string returnMessage = "Press B to return to menu";
renderText(renderer, defaultFont, aboutMessage, { 255, 255, 255, 255 },
(windowWidth - TEXT_WRAP_WIDTH) / 2, 100, TEXT_WRAP_WIDTH);
renderText(renderer, defaultFont, returnMessage, { 255, 255, 255, 255 },
(windowWidth - 300) / 2, windowHeight - 50);
break;
}
case MAP: {
SDL_RenderCopy(renderer, mapBackdropTexture, nullptr, nullptr);
// Handle key press events
while (SDL_PollEvent(&event)) {
if (event.type == SDL_KEYDOWN) {
printf("Key pressed: %d\n", event.key.keysym.sym);
if (event.key.keysym.sym == SDLK_SPACE) {
printf("Space bar pressed. Current level: %d\n", currentLevel);
// Initialize the next level
if (currentLevel == 1) {
printf("Transitioning to Level 2.\n");
currentLevel = 2;
initCombatWithRenderer(currentLevel, renderer);
// Set up EnemyB for Level 2
currentEnemy = new EnemyB(renderer);
currentEnemy->initSprite(renderer);
}
else if (currentLevel == 2) {
printf("Transitioning to Level 3.\n");
currentLevel = 3;
initCombatWithRenderer(currentLevel, renderer);
// Set up EnemyC for Level 3
currentEnemy = new EnemyC(renderer);
currentEnemy->initSprite(renderer);
}
// Transition to the PLAYING state
gameState = PLAYING;
printf("Transitioned to PLAYING state.\n");
}
}
}
break;
}
}
SDL_RenderPresent(renderer);
frameTime = SDL_GetTicks() - frameStart;
if (FRAME_DELAY > frameTime) {
SDL_Delay(FRAME_DELAY - frameTime);
}
}
// Cleanup
if (Knight_idle) {
delete Knight_idle;
Knight_idle = nullptr;
}
cleanupResources();
return 0;
}