diff --git a/assets/textures/ball/banana_ball.png b/assets/textures/ball/banana_ball.png new file mode 100644 index 0000000..0247eaf Binary files /dev/null and b/assets/textures/ball/banana_ball.png differ diff --git a/assets/textures/ball/beach_ball.png b/assets/textures/ball/beach_ball.png new file mode 100644 index 0000000..4cd3721 Binary files /dev/null and b/assets/textures/ball/beach_ball.png differ diff --git a/assets/textures/ball/cloudy__ball.png b/assets/textures/ball/cloudy__ball.png new file mode 100644 index 0000000..7d96ead Binary files /dev/null and b/assets/textures/ball/cloudy__ball.png differ diff --git a/assets/textures/ball/basic_ball_5.png b/assets/textures/ball/default_ball.png similarity index 100% rename from assets/textures/ball/basic_ball_5.png rename to assets/textures/ball/default_ball.png diff --git a/assets/textures/ball/simple_ball.png b/assets/textures/ball/simple_ball.png new file mode 100644 index 0000000..157995c Binary files /dev/null and b/assets/textures/ball/simple_ball.png differ diff --git a/assets/textures/paddles/cloudy_paddle.png b/assets/textures/paddles/cloudy_paddle.png new file mode 100644 index 0000000..6bd1c62 Binary files /dev/null and b/assets/textures/paddles/cloudy_paddle.png differ diff --git a/assets/textures/paddles/basic_paddle_2.png b/assets/textures/paddles/cpu_paddle.png similarity index 100% rename from assets/textures/paddles/basic_paddle_2.png rename to assets/textures/paddles/cpu_paddle.png diff --git a/assets/textures/paddles/basic_paddle.png b/assets/textures/paddles/default_paddle.png similarity index 100% rename from assets/textures/paddles/basic_paddle.png rename to assets/textures/paddles/default_paddle.png diff --git a/assets/textures/paddles/human_paddle.png b/assets/textures/paddles/human_paddle.png new file mode 100644 index 0000000..231b66b Binary files /dev/null and b/assets/textures/paddles/human_paddle.png differ diff --git a/assets/textures/spaces/basic_space.png b/assets/textures/spaces/default_space.png similarity index 100% rename from assets/textures/spaces/basic_space.png rename to assets/textures/spaces/default_space.png diff --git a/assets/textures/spaces/galaxy_space.png b/assets/textures/spaces/galaxy_space.png new file mode 100644 index 0000000..6bec620 Binary files /dev/null and b/assets/textures/spaces/galaxy_space.png differ diff --git a/assets/textures/spaces/trap_space.png b/assets/textures/spaces/trap_space.png new file mode 100644 index 0000000..7842c0c Binary files /dev/null and b/assets/textures/spaces/trap_space.png differ diff --git a/include/game.h b/include/game.h index b2b7404..b6b90a2 100644 --- a/include/game.h +++ b/include/game.h @@ -42,7 +42,10 @@ struct GameConfig { int maxScoreOption = 0; // 0 = 5, 1 = 11, 2 = 15, 3 = 21 int maxScore = 5; bool sfxEnabled = true; - int selectedSettingLine = 0; // 0 = Resolution, 1 = Framerate, 2 = Screen Mode, 3 = Score Limit, 4 = Sound, 5 = Back + int spaceThemeOption = 0; // 0 = Default, 1 = Galaxy, 2 = Trap + int ballThemeOption = 0; // 0 = Default, 1 = Banana, 2 = Beach, 3 = Cloudy, 4 = Simple + int paddleThemeOption = 0; // 0 = Default, 1 = Cloudy, 2 = CPU, 3 = Human + int selectedSettingLine = 0; // 0 = Resolution, 1 = Framerate, 2 = Screen Mode, 3 = Score Limit, 4 = Sound, 5 = Space, 6 = Ball, 7 = Paddle, 8 = Back }; struct GameContext { @@ -69,12 +72,13 @@ struct GameContext { Texture2D LoadTextureFromResource(int id); Sound LoadSoundFromResource(int id); void SetWindowIconFromResource(int id); - // Forward declarations class Ball; class Paddle; class CpuPaddle; +void ApplyPaddleTextures(const GameContext& ctx, Paddle& player, CpuPaddle& cpu); + // Game state update and draw routines void ResetBall(Ball& ball); void DrawCourt(const GameContext& ctx, int screenWidth, int screenHeight); @@ -121,6 +125,7 @@ public: bool Update() override; void Draw() override; + void ReloadTexture(int resourceId); }; class Ball : public GameObject { @@ -147,6 +152,7 @@ public: bool Update() override; void Draw() override; + void ReloadTexture(int resourceId); }; class CpuPaddle : public Paddle { diff --git a/include/main.h b/include/main.h index 765eed4..e8b18f3 100644 --- a/include/main.h +++ b/include/main.h @@ -1,4 +1,5 @@ #pragma once + #include #include #include diff --git a/include/menu.h b/include/menu.h index 6582ea4..3827e98 100644 --- a/include/menu.h +++ b/include/menu.h @@ -1,4 +1,5 @@ #pragma once + #include "game.h" #include #include @@ -22,7 +23,7 @@ public: // Settings and lobby routines void ApplyResolution(int width, int height); void ApplyFramerate(int option); -void UpdateSettingsState(GameContext& ctx); +void UpdateSettingsState(GameContext& ctx, Ball& ball, Paddle& player, CpuPaddle& cpu); void DrawSettingsState(const GameContext& ctx, int screenWidth, int screenHeight); void UpdateLobbyState(GameContext& ctx); void DrawLobbyState(const GameContext& ctx, int screenWidth, int screenHeight); diff --git a/include/resource.h b/include/resource.h index 2acf0be..52a3a08 100644 --- a/include/resource.h +++ b/include/resource.h @@ -1,15 +1,30 @@ #pragma once -#define IDI_ICON1 100 +#define IDI_ICON1 100 -#define IDR_TEX_BASIC_SPACE 101 -#define IDR_TEX_WALLS 102 -#define IDR_TEX_LINE 103 -#define IDR_TEX_BALL 104 -#define IDR_TEX_PADDLE 105 -#define IDR_TEX_PADDLE2 106 +// Backgrounds +#define IDR_TEX_SPACE_DEFAULT 101 +#define IDR_TEX_SPACE_GALAXY 107 +#define IDR_TEX_SPACE_TRAP 108 +#define IDR_TEX_WALLS 102 +#define IDR_TEX_LINE 103 + +// Balls +#define IDR_TEX_BALL_DEFAULT 104 +#define IDR_TEX_BALL_BANANA 109 +#define IDR_TEX_BALL_BEACH 110 +#define IDR_TEX_BALL_CLOUDY 111 +#define IDR_TEX_BALL_SIMPLE 112 + +// Paddles +#define IDR_TEX_PADDLE_DEFAULT 105 +#define IDR_TEX_PADDLE_CLOUDY 106 +#define IDR_TEX_PADDLE_CPU 113 +#define IDR_TEX_PADDLE_HUMAN 114 + +// Audio +#define IDR_SND_PADDLE_HIT 201 +#define IDR_SND_WALL_HIT 202 +#define IDR_SND_SCORE 203 +#define IDR_SND_BANANA 204 -#define IDR_SND_PADDLE_HIT 201 -#define IDR_SND_WALL_HIT 202 -#define IDR_SND_SCORE 203 -#define IDR_SND_BANANA 204 diff --git a/pong-reloaded.vcxproj b/pong-reloaded.vcxproj index 654348a..9b670b0 100644 --- a/pong-reloaded.vcxproj +++ b/pong-reloaded.vcxproj @@ -153,11 +153,19 @@ - + + + + + - - - + + + + + + + diff --git a/pong-reloaded.vcxproj.filters b/pong-reloaded.vcxproj.filters index 1c928b6..ff0d468 100644 --- a/pong-reloaded.vcxproj.filters +++ b/pong-reloaded.vcxproj.filters @@ -22,6 +22,18 @@ {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + {89cd7d41-de3f-4bd4-a3b4-c7aab8c5ffe9} + + + {3a7b2941-0560-4ab7-b8eb-255ef37bd3a4} + + + {03e96034-55b9-4397-9f56-467d7c351e20} + + + {5b322e46-cf19-4411-bcdd-5c3ca59fc236} + @@ -61,27 +73,51 @@ - - Resource Files\textures - - - Resource Files\textures - - - Resource Files\textures - - - Resource Files\textures - - - Resource Files\textures - - - Resource Files\textures - Resource Files + + Resource Files\textures\ball + + + Resource Files\textures\ball + + + Resource Files\textures\ball + + + Resource Files\textures\ball + + + Resource Files\textures\ball + + + Resource Files\textures\hud + + + Resource Files\textures\paddles + + + Resource Files\textures\paddles + + + Resource Files\textures\paddles + + + Resource Files\textures\paddles + + + Resource Files\textures\spaces + + + Resource Files\textures\spaces + + + Resource Files\textures\spaces + + + Resource Files\textures\spaces + diff --git a/resources.rc b/resources.rc index 8d0b9cc..ff8c94e 100644 --- a/resources.rc +++ b/resources.rc @@ -1,15 +1,30 @@ #include "include/resource.h" -IDI_ICON1 ICON "assets/icon.ico" +IDI_ICON1 ICON "assets/icon.ico" -IDR_TEX_BASIC_SPACE RCDATA "assets/textures/spaces/basic_space.png" -IDR_TEX_WALLS RCDATA "assets/textures/spaces/walls.png" -IDR_TEX_LINE RCDATA "assets/textures/hud/line.png" -IDR_TEX_BALL RCDATA "assets/textures/ball/basic_ball_5.png" -IDR_TEX_PADDLE RCDATA "assets/textures/paddles/basic_paddle.png" -IDR_TEX_PADDLE2 RCDATA "assets/textures/paddles/basic_paddle_2.png" +// Backgrounds +IDR_TEX_SPACE_DEFAULT RCDATA "assets/textures/spaces/default_space.png" +IDR_TEX_SPACE_GALAXY RCDATA "assets/textures/spaces/galaxy_space.png" +IDR_TEX_SPACE_TRAP RCDATA "assets/textures/spaces/trap_space.png" +IDR_TEX_WALLS RCDATA "assets/textures/spaces/walls.png" +IDR_TEX_LINE RCDATA "assets/textures/hud/line.png" + +// Balls +IDR_TEX_BALL_DEFAULT RCDATA "assets/textures/ball/default_ball.png" +IDR_TEX_BALL_BANANA RCDATA "assets/textures/ball/banana_ball.png" +IDR_TEX_BALL_BEACH RCDATA "assets/textures/ball/beach_ball.png" +IDR_TEX_BALL_CLOUDY RCDATA "assets/textures/ball/cloudy__ball.png" +IDR_TEX_BALL_SIMPLE RCDATA "assets/textures/ball/simple_ball.png" + +// Paddles +IDR_TEX_PADDLE_DEFAULT RCDATA "assets/textures/paddles/default_paddle.png" +IDR_TEX_PADDLE_CLOUDY RCDATA "assets/textures/paddles/cloudy_paddle.png" +IDR_TEX_PADDLE_CPU RCDATA "assets/textures/paddles/cpu_paddle.png" +IDR_TEX_PADDLE_HUMAN RCDATA "assets/textures/paddles/human_paddle.png" + +// Audio +IDR_SND_PADDLE_HIT RCDATA "assets/audio/paddle_hit.ogg" +IDR_SND_WALL_HIT RCDATA "assets/audio/wall_hit.ogg" +IDR_SND_SCORE RCDATA "assets/audio/score.ogg" +IDR_SND_BANANA RCDATA "assets/audio/banana_wall_hit.ogg" -IDR_SND_PADDLE_HIT RCDATA "assets/audio/paddle_hit.ogg" -IDR_SND_WALL_HIT RCDATA "assets/audio/wall_hit.ogg" -IDR_SND_SCORE RCDATA "assets/audio/score.ogg" -IDR_SND_BANANA RCDATA "assets/audio/banana_wall_hit.ogg" diff --git a/src/game.cpp b/src/game.cpp index 3fab1fb..7b94608 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1,5 +1,6 @@ #include "game.h" #include "main.h" +#include "resource.h" // Paddle implementation bool Paddle::Update() { @@ -41,6 +42,17 @@ void Paddle::Draw() { } } +void Paddle::ReloadTexture(int resourceId) { + if (texture.id > 0) { + UnloadTexture(texture); + } + if (resourceId > 0) { + texture = LoadTextureFromResource(resourceId); + } else { + texture = { 0 }; + } +} + // Ball implementation bool Ball::Update() { @@ -70,6 +82,17 @@ void Ball::Draw() { } } +void Ball::ReloadTexture(int resourceId) { + if (texture.id > 0) { + UnloadTexture(texture); + } + if (resourceId > 0) { + texture = LoadTextureFromResource(resourceId); + } else { + texture = { 0 }; + } +} + // Game state routines and helpers void ResetBall(Ball& ball) { @@ -361,3 +384,18 @@ void DrawGameOverState(const GameContext& ctx, int screenWidth, int screenHeight int instWidth = MeasureText("Press SPACEBAR to return to Main Menu", 20); DrawText("Press SPACEBAR to return to Main Menu", screenWidth / 2 - instWidth / 2, panelY + 340, 20, YELLOW); } + +void ApplyPaddleTextures(const GameContext& ctx, Paddle& player, CpuPaddle& cpu) { + int playerResId = IDR_TEX_PADDLE_DEFAULT; + if (ctx.config.paddleThemeOption == 1) playerResId = IDR_TEX_PADDLE_CLOUDY; + else if (ctx.config.paddleThemeOption == 2) playerResId = IDR_TEX_PADDLE_CPU; + else if (ctx.config.paddleThemeOption == 3) playerResId = IDR_TEX_PADDLE_HUMAN; + + player.ReloadTexture(playerResId); + + if (ctx.isMultiplayer) { + cpu.ReloadTexture(playerResId); + } else { + cpu.ReloadTexture(IDR_TEX_PADDLE_CPU); + } +} diff --git a/src/main.cpp b/src/main.cpp index 63ecadb..9e9397c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,7 +36,7 @@ int main() { GameContext ctx; // Asset textures loading - ctx.courtBackground = LoadTextureFromResource(IDR_TEX_BASIC_SPACE); + ctx.courtBackground = LoadTextureFromResource(IDR_TEX_SPACE_DEFAULT); ctx.wallsTexture = LoadTextureFromResource(IDR_TEX_WALLS); ctx.lineTexture = LoadTextureFromResource(IDR_TEX_LINE); @@ -49,21 +49,21 @@ int main() { Ball ball( Vector2{ screen_width / 2.0f, screen_height / 2.0f }, Yellow, 20.0f, - IDR_TEX_BALL + IDR_TEX_BALL_DEFAULT ); ResetBall(ball); Paddle player( Vector2{ screen_width - 20.0f - 10.0f - 25.0f, screen_height / 2.0f - 60.0f }, WHITE, 25.0f, 120.0f, - IDR_TEX_PADDLE + IDR_TEX_PADDLE_DEFAULT ); CpuPaddle cpu( Vector2{ 20.0f + 10.0f, screen_height / 2.0f - 60.0f }, WHITE, 25.0f, 120.0f, Difficulty::Normal, - IDR_TEX_PADDLE2 + IDR_TEX_PADDLE_DEFAULT ); // Menu instantiation @@ -142,6 +142,7 @@ int main() { ctx.isPaused = false; ResetBall(ball); ctx.currentState = GameState::Playing; + ApplyPaddleTextures(ctx, player, cpu); } else if (selected == 3) { ctx.currentState = GameState::MainMenu; @@ -149,13 +150,19 @@ int main() { break; } case GameState::MultiplayerLobby: + { + GameState oldState = ctx.currentState; UpdateLobbyState(ctx); + if (ctx.currentState == GameState::Multiplayer && oldState != GameState::Multiplayer) { + ApplyPaddleTextures(ctx, player, cpu); + } break; + } case GameState::Multiplayer: UpdateMultiplayerState(ctx, ball, player, cpu); break; case GameState::Settings: - UpdateSettingsState(ctx); + UpdateSettingsState(ctx, ball, player, cpu); break; case GameState::Playing: UpdatePlayingState(ctx, ball, player, cpu); diff --git a/src/menu.cpp b/src/menu.cpp index 4d30512..4d0df02 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -1,5 +1,6 @@ #include "menu.h" #include "main.h" +#include "resource.h" int Menu::Update() { // Menu navigation @@ -64,15 +65,15 @@ void ApplyFramerate(int option) { } } -void UpdateSettingsState(GameContext& ctx) { +void UpdateSettingsState(GameContext& ctx, Ball& ball, Paddle& player, CpuPaddle& cpu) { // Menu navigation if (IsKeyPressed(KEY_UP)) { ctx.config.selectedSettingLine--; - if (ctx.config.selectedSettingLine < 0) ctx.config.selectedSettingLine = 5; + if (ctx.config.selectedSettingLine < 0) ctx.config.selectedSettingLine = 8; } if (IsKeyPressed(KEY_DOWN)) { ctx.config.selectedSettingLine++; - if (ctx.config.selectedSettingLine > 5) ctx.config.selectedSettingLine = 0; + if (ctx.config.selectedSettingLine > 8) ctx.config.selectedSettingLine = 0; } // Settings adjustments (LEFT/RIGHT or ENTER) @@ -125,6 +126,67 @@ void UpdateSettingsState(GameContext& ctx) { } } else if (ctx.config.selectedSettingLine == 5) { + bool changed = false; + if (IsKeyPressed(KEY_RIGHT) || IsKeyPressed(KEY_ENTER)) { + ctx.config.spaceThemeOption = (ctx.config.spaceThemeOption + 1) % 3; + changed = true; + } + else if (IsKeyPressed(KEY_LEFT)) { + ctx.config.spaceThemeOption = (ctx.config.spaceThemeOption - 1 + 3) % 3; + changed = true; + } + if (changed) { + int resId = IDR_TEX_SPACE_DEFAULT; + if (ctx.config.spaceThemeOption == 1) resId = IDR_TEX_SPACE_GALAXY; + else if (ctx.config.spaceThemeOption == 2) resId = IDR_TEX_SPACE_TRAP; + + if (ctx.courtBackground.id > 0) { + UnloadTexture(ctx.courtBackground); + } + ctx.courtBackground = LoadTextureFromResource(resId); + } + } + else if (ctx.config.selectedSettingLine == 6) { + bool changed = false; + if (IsKeyPressed(KEY_RIGHT) || IsKeyPressed(KEY_ENTER)) { + ctx.config.ballThemeOption = (ctx.config.ballThemeOption + 1) % 5; + changed = true; + } + else if (IsKeyPressed(KEY_LEFT)) { + ctx.config.ballThemeOption = (ctx.config.ballThemeOption - 1 + 5) % 5; + changed = true; + } + if (changed) { + int resId = IDR_TEX_BALL_DEFAULT; + if (ctx.config.ballThemeOption == 1) resId = IDR_TEX_BALL_BANANA; + else if (ctx.config.ballThemeOption == 2) resId = IDR_TEX_BALL_BEACH; + else if (ctx.config.ballThemeOption == 3) resId = IDR_TEX_BALL_CLOUDY; + else if (ctx.config.ballThemeOption == 4) resId = IDR_TEX_BALL_SIMPLE; + + ball.ReloadTexture(resId); + } + } + else if (ctx.config.selectedSettingLine == 7) { + bool changed = false; + if (IsKeyPressed(KEY_RIGHT) || IsKeyPressed(KEY_ENTER)) { + ctx.config.paddleThemeOption = (ctx.config.paddleThemeOption + 1) % 4; + changed = true; + } + else if (IsKeyPressed(KEY_LEFT)) { + ctx.config.paddleThemeOption = (ctx.config.paddleThemeOption - 1 + 4) % 4; + changed = true; + } + if (changed) { + int resId = IDR_TEX_PADDLE_DEFAULT; + if (ctx.config.paddleThemeOption == 1) resId = IDR_TEX_PADDLE_CLOUDY; + else if (ctx.config.paddleThemeOption == 2) resId = IDR_TEX_PADDLE_CPU; + else if (ctx.config.paddleThemeOption == 3) resId = IDR_TEX_PADDLE_HUMAN; + + player.ReloadTexture(resId); + cpu.ReloadTexture(resId); + } + } + else if (ctx.config.selectedSettingLine == 8) { if (IsKeyPressed(KEY_ENTER)) { ctx.currentState = GameState::MainMenu; } @@ -156,21 +218,45 @@ void DrawSettingsState(const GameContext& ctx, int screenWidth, int screenHeight if (ctx.config.sfxEnabled) sfxStr += "ON"; else sfxStr += "OFF"; + std::string spaceThemeStr = "Space Theme: "; + if (ctx.config.spaceThemeOption == 0) spaceThemeStr += "Default"; + else if (ctx.config.spaceThemeOption == 1) spaceThemeStr += "Galaxy"; + else if (ctx.config.spaceThemeOption == 2) spaceThemeStr += "Trap"; + + std::string ballThemeStr = "Ball Theme: "; + if (ctx.config.ballThemeOption == 0) ballThemeStr += "Default"; + else if (ctx.config.ballThemeOption == 1) ballThemeStr += "Banana"; + else if (ctx.config.ballThemeOption == 2) ballThemeStr += "Beach"; + else if (ctx.config.ballThemeOption == 3) ballThemeStr += "Cloudy"; + else if (ctx.config.ballThemeOption == 4) ballThemeStr += "Simple"; + + std::string paddleThemeStr = "Paddle Theme: "; + if (ctx.config.paddleThemeOption == 0) paddleThemeStr += "Default"; + else if (ctx.config.paddleThemeOption == 1) paddleThemeStr += "Cloudy"; + else if (ctx.config.paddleThemeOption == 2) paddleThemeStr += "CPU Style"; + else if (ctx.config.paddleThemeOption == 3) paddleThemeStr += "Human Style"; + // Menu options highlighting and drawing Color resColor = (ctx.config.selectedSettingLine == 0) ? YELLOW : WHITE; Color fpsColor = (ctx.config.selectedSettingLine == 1) ? YELLOW : WHITE; Color modeColor = (ctx.config.selectedSettingLine == 2) ? YELLOW : WHITE; Color scoreColor = (ctx.config.selectedSettingLine == 3) ? YELLOW : WHITE; Color sfxColor = (ctx.config.selectedSettingLine == 4) ? YELLOW : WHITE; - Color backColor = (ctx.config.selectedSettingLine == 5) ? YELLOW : WHITE; + Color spaceColor = (ctx.config.selectedSettingLine == 5) ? YELLOW : WHITE; + Color ballColor = (ctx.config.selectedSettingLine == 6) ? YELLOW : WHITE; + Color paddleColor = (ctx.config.selectedSettingLine == 7) ? YELLOW : WHITE; + Color backColor = (ctx.config.selectedSettingLine == 8) ? YELLOW : WHITE; - int startY = screenHeight / 2 - 90; + int startY = screenHeight / 2 - 80; DrawText(resStr.c_str(), screenWidth / 2 - MeasureText(resStr.c_str(), 30) / 2, startY, 30, resColor); - DrawText(fpsStr.c_str(), screenWidth / 2 - MeasureText(fpsStr.c_str(), 30) / 2, startY + 45, 30, fpsColor); - DrawText(modeStr.c_str(), screenWidth / 2 - MeasureText(modeStr.c_str(), 30) / 2, startY + 90, 30, modeColor); - DrawText(scoreLimitStr.c_str(), screenWidth / 2 - MeasureText(scoreLimitStr.c_str(), 30) / 2, startY + 135, 30, scoreColor); - DrawText(sfxStr.c_str(), screenWidth / 2 - MeasureText(sfxStr.c_str(), 30) / 2, startY + 180, 30, sfxColor); - DrawText("Back", screenWidth / 2 - MeasureText("Back", 30) / 2, startY + 225, 30, backColor); + DrawText(fpsStr.c_str(), screenWidth / 2 - MeasureText(fpsStr.c_str(), 30) / 2, startY + 40, 30, fpsColor); + DrawText(modeStr.c_str(), screenWidth / 2 - MeasureText(modeStr.c_str(), 30) / 2, startY + 80, 30, modeColor); + DrawText(scoreLimitStr.c_str(), screenWidth / 2 - MeasureText(scoreLimitStr.c_str(), 30) / 2, startY + 120, 30, scoreColor); + DrawText(sfxStr.c_str(), screenWidth / 2 - MeasureText(sfxStr.c_str(), 30) / 2, startY + 160, 30, sfxColor); + DrawText(spaceThemeStr.c_str(), screenWidth / 2 - MeasureText(spaceThemeStr.c_str(), 30) / 2, startY + 200, 30, spaceColor); + DrawText(ballThemeStr.c_str(), screenWidth / 2 - MeasureText(ballThemeStr.c_str(), 30) / 2, startY + 240, 30, ballColor); + DrawText(paddleThemeStr.c_str(), screenWidth / 2 - MeasureText(paddleThemeStr.c_str(), 30) / 2, startY + 280, 30, paddleColor); + DrawText("Back", screenWidth / 2 - MeasureText("Back", 30) / 2, startY + 320, 30, backColor); int settingsHintWidth = MeasureText("UP/DOWN to navigate | LEFT/RIGHT to change settings | ENTER to select", 20); DrawText("UP/DOWN to navigate | LEFT/RIGHT to change settings | ENTER to select",