diff --git a/Assets/Fonts/comic.ttf b/Assets/Fonts/comic.ttf new file mode 100644 index 0000000..6525a27 Binary files /dev/null and b/Assets/Fonts/comic.ttf differ diff --git a/data/levels.dat b/Assets/Levels.dat similarity index 100% rename from data/levels.dat rename to Assets/Levels.dat diff --git a/data/sprites.dat b/Assets/Sprites.dat similarity index 100% rename from data/sprites.dat rename to Assets/Sprites.dat diff --git a/CMakeLists.txt b/CMakeLists.txt index bdd58d6..8dc52f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,9 +25,10 @@ option(USE_CONAN if(USE_CONAN) find_package(SDL2 REQUIRED CONFIG) find_package(SDL2_mixer REQUIRED CONFIG) + find_package(SDL2_ttf REQUIRED CONFIG) else() find_package(PkgConfig REQUIRED) - pkg_check_modules(SDL2 REQUIRED sdl2 SDL2_mixer) + pkg_check_modules(SDL2 REQUIRED sdl2 SDL2_mixer SDL2_ttf) endif() set(CMAKE_CXX_STANDARD 11) @@ -80,7 +81,7 @@ if(LINUX) endif() if(USE_CONAN) - target_link_libraries(${LIRI_EXECUTABLE_NAME} PRIVATE SDL2::SDL2 SDL2_mixer::SDL2_mixer) + target_link_libraries(${LIRI_EXECUTABLE_NAME} PRIVATE SDL2::SDL2 SDL2_mixer::SDL2_mixer SDL2_ttf::SDL2_ttf) else() target_include_directories(${LIRI_EXECUTABLE_NAME} PUBLIC ${SDL2_INCLUDE_DIRS}) target_link_libraries(${LIRI_EXECUTABLE_NAME} PRIVATE ${SDL2_LINK_LIBRARIES}) diff --git a/README.md b/README.md index 63bb43c..0b4ccad 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ Copyright (c) 2006 Dominique Roux-Serret: design & programming & graphics & website. Maf464: musics -Copyright (c) 2006 (for "menu.mod", "jeu1.xm", "jeu2.xm") MAF464 (email charcosset.b@free.fr; website http://maf464.free.fr). This music licensed under GPL license. See COPYING for details +Copyright (c) 2006 (for "menu.mod", "ingame1.xm", "ingame2.xm") MAF464 (email charcosset.b@free.fr; website http://maf464.free.fr). This music licensed under GPL license. See COPYING for details [Get it on F-Droid // for SDL_PollEvent, SDL_PRESSED, SDL_Event #include // for SDLK_DOWN, SDLK_LEFT, SDLK_RIGHT, SDLK_UP #include // for SDL_RenderPresent, SDL_RenderClear @@ -359,12 +360,14 @@ bool Game::DrawLevel(int LevelN) #endif // Displays texts for selected language - DrawText(740, 110, T_level, Sprites[fgame].Image[0]); - DrawText(740, 180, T_score, Sprites[fgame].Image[0]); - DrawText(740, 260, T_options, Sprites[fgame].Image[0]); - DrawText(740, 340, T_lives, Sprites[fgame].Image[0]); + m_screen.ChangeFontColor(255, 255, 0); + m_screen.PrintText("Level", 740-m_screen.TextLength("Level")/2, 110); + m_screen.PrintText("Score", 740-m_screen.TextLength("Score")/2, 180); + m_screen.PrintText("Config", 740-m_screen.TextLength("Config")/2, 260); + m_screen.PrintText("Lives", 740-m_screen.TextLength("Lives")/2, 340); + m_screen.ChangeFontColor(255, 255, 255); - DrawNumber(740, 140, Pref.Level + 1, Sprites[fgame].Image[0]); + m_screen.PrintText(std::to_string(Pref.Level + 1), 740 - m_screen.TextLength(std::to_string(Pref.Level + 1))/2, 140); return true; } @@ -528,8 +531,8 @@ void Game::DisplayScreen() // Display options for (i = 0; i < LT * HT; i++) { switch (T[i]) { - case C_Car: // if car sprite - m_screen.PrintSprite(car, (GameClock * 40 / 1000 + i * 7) % 50, i % LT * D_Case + D_Case / 2, i / LT * D_Case + D_Case / 2); + case C_Wagon: // if wagon sprite + m_screen.PrintSprite(wagon, (GameClock * 40 / 1000 + i * 7) % 50, i % LT * D_Case + D_Case / 2, i / LT * D_Case + D_Case / 2); break; case C_Expand: // if expander sprite m_screen.PrintSprite(expander, (GameClock * 40 / 1000 + i * 7) % 50, i % LT * D_Case + D_Case / 2, i / LT * D_Case + D_Case / 2); @@ -548,7 +551,13 @@ void Game::DisplayScreen() // When paused, asks for a key press if (Pause) { - m_screen.PrintText(T_press_any_key, LT * D_Case / 2, 300); + m_screen.ChangeFontSize(60); + m_screen.ChangeFontColor(0, 0, 0); + m_screen.PrintText("Press any key", 341 - m_screen.TextLength("Press any key")/2, 271); + m_screen.ChangeFontColor(255, 255, 0); + m_screen.PrintText("Press any key", 340 - m_screen.TextLength("Press any key")/2, 270); + m_screen.ChangeFontColor(255, 255, 255); + m_screen.ChangeFontSize(14); } // Prints a dashboard diff --git a/src/level.cc b/src/level.cc index be49ba9..7725f69 100644 --- a/src/level.cc +++ b/src/level.cc @@ -40,7 +40,7 @@ bool Level::Load() unsigned char *Buf; long L, P = 2; int i, j; - char NameLevelFile[512] = "levels.dat"; + char NameLevelFile[512] = "Assets/Levels.dat"; Utils::GetPath(NameLevelFile); L = Utils::LoadFile(NameLevelFile, Buf); diff --git a/src/loco.cc b/src/loco.cc index f21e5dd..e939560 100644 --- a/src/loco.cc +++ b/src/loco.cc @@ -118,7 +118,7 @@ void Loco::Display(Screen &screen) int cdx, cdy, cfx = 0, cfy = 0; // Attachment point for cables float lv; - // Display all wagon/(cars) + // Display all wagon for (i = 0; i < NWagon; i++) { // Search wagon points switch (Wagon[i]) { @@ -135,7 +135,7 @@ void Loco::Display(Screen &screen) lv = 20; } - // Calculate cars point's position + // Calculate wagons point's position FindPoint(D - p1, x1, y1); FindPoint(D - p2, x2, y2); @@ -186,7 +186,7 @@ void Loco::Display(Screen &screen) // Displays the cable screen.PrintCable(cdx, cdy, cfx, cfy); } - // Calculate the attachment point for the next Wagon/car + // Calculate the attachment point for the next Wagon cfx = x1 - (int)(sin(ar + M_PI) * lv); cfy = y1 - (int)(cos(ar + M_PI) * lv); @@ -222,7 +222,7 @@ void Loco::Display(Screen &screen) } } - // Add gap between the wagons/cars + // Add gap between the wagons ltrain += Pref.WagonGap; } } @@ -240,15 +240,15 @@ void Loco::TestTile(float Dist, long GameDuration, int *Level) if (D <= DMoy && D + Dist >= DMoy) { // Check if on an item switch (Level[T[LocoPos].P]) { - case C_Car: // New wagon/car - m_audio.Play(sCar); + case C_Wagon: // New wagon + m_audio.Play(sWagon); Level[T[LocoPos].P] = 1; // Remove item from level Pref.Score += 5; AddLoco(); // Add a random wagon Win = true; // Check if it was the last wagon for win condition for (i = 0; i < LT * HT; i++) { - if (Level[i] == C_Car) { + if (Level[i] == C_Wagon) { Win = false; } } @@ -291,7 +291,7 @@ void Loco::TestTile(float Dist, long GameDuration, int *Level) break; } - // Collision check with another wagon/car + // Collision check with another wagon for (i = 1; i < NWagon; i++) { vx = (float)(PosWagon[i].dx - PosWagon[0].dx); vy = (float)(PosWagon[i].dy - PosWagon[0].dy); @@ -663,9 +663,9 @@ void Loco::FindPoint(float Dist, int &x, int &y) /*********************************************/ void Loco::AddLoco() { - Wagon[NWagon] = (e_Sprite)(rand() % (car - logs_wagon) + logs_wagon); + Wagon[NWagon] = (e_Sprite)(rand() % (wagon - logs_wagon) + logs_wagon); if (Wagon[NWagon] == Wagon[NWagon - 1]) { // Avoids adding the same sprite twice - if (Wagon[NWagon] + 1 == car) { + if (Wagon[NWagon] + 1 == wagon) { Wagon[NWagon] = logs_wagon; } else { diff --git a/src/loco.h b/src/loco.h index aeab20f..e05b044 100644 --- a/src/loco.h +++ b/src/loco.h @@ -58,7 +58,7 @@ class Loco void MoveForward(int Duration, long GameDuration, int *Key, int *Level); // Makes locomotive move forward for Duration in ms void FindArrow(int *Level, int *Key); // Search the position of the next intersection bool TestDir(int FDir, int *Level); // Check if a direction/turn is possible - void AddLoco(); // Adds a random car to the locomotive + void AddLoco(); // Adds a random wagon to the locomotive inline bool Go(int FutureDirection); // Move the locomotive inline void FindPoint(float Dist, int &x, int &y); // Searching a point on the map diff --git a/src/main.cc b/src/main.cc index 49d5fab..7a79ca9 100644 --- a/src/main.cc +++ b/src/main.cc @@ -32,6 +32,7 @@ #include // for SDL_CreateWindow, SDL_DestroyWindow #include #include +#include #include "config.h" #include "preference.h" @@ -97,6 +98,7 @@ int main(int narg, char *argv[]) SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to initialize SDL: %s", SDL_GetError()); exit(-1); } + TTF_Init(); // Close the program properly when quitting atexit(SDL_Quit); @@ -142,12 +144,6 @@ int main(int narg, char *argv[]) previousTime = currentTime = SDL_GetTicks(); srand(SDL_GetTicks()); - // ask locale if first run - if (Pref.Language == -1) { - RetMenu = MainMenu.SDLMain_Language(); - LoadLanguage(); - } - // menu switch do { switch (RetMenu) { @@ -155,7 +151,7 @@ int main(int narg, char *argv[]) RetM = MainMenu.SDLMain(); break; case mLanguage: - RetM = MainMenu.SDLMain_Language(); + //RetM = MainMenu.SDLMain_Language(); break; case mOption: RetM = MainMenu.SDLMain_Options(); diff --git a/src/menu.cc b/src/menu.cc index cfc79b1..bf25391 100644 --- a/src/menu.cc +++ b/src/menu.cc @@ -21,6 +21,7 @@ // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +#define DCHILDREN #include #include #include @@ -72,6 +73,24 @@ void Sleeping() } } +/*** Add button with text to the menu array ***/ +/**********************************************/ +void AddTextButton(int Num, std::string Text, int X, int Y, Screen& ScreenObj) +{ + ScreenObj.ChangeFontSize(45); + + int textWidth = ScreenObj.TextLength(Text); + + ScreenObj.PrintText(Text, X - textWidth / 2, Y - 22); + + Menu_Py[Num].StartX = X - textWidth / 2; + Menu_Py[Num].StartY = Y - 22; + Menu_Py[Num].EndX = X + textWidth / 2; + Menu_Py[Num].EndY = Y + 22; + Menu_Py[Num].Py = Num; + Menu_Py[Num].Valid = true; +} + /*** Add an button to the menu array ***/ /***************************************/ void AddButton(int Num, e_Sprite NumSp, int X, int Y) @@ -116,16 +135,16 @@ eMenu Menu::SDLMain() Sprites[background_menu].Draw(400, 300, 0, Sprites[fmenu].Image[0]); Sprites[menu].Draw(400, 340, 0, Sprites[fmenu].Image[0]); Sprites[title].Draw(400, 65, 0, Sprites[fmenu].Image[0]); - Sprites[copyright].Draw(400, 587, 0, Sprites[fmenu].Image[0]); - - DrawText(400, 229, T_play, Sprites[fmenu].Image[0]); - AddButton(0, T_play, 400, 229); - DrawText(400, 306, T_scores, Sprites[fmenu].Image[0]); - AddButton(1, T_scores, 400, 306); - DrawText(400, 384, T_moptions, Sprites[fmenu].Image[0]); - AddButton(2, T_moptions, 400, 384); - DrawText(400, 461, T_quit, Sprites[fmenu].Image[0]); - AddButton(3, T_quit, 400, 461); + + m_screen.ChangeFontSize(14); + // Automatic year change + m_screen.PrintText(CopyrightText, 400-m_screen.TextLength(CopyrightText)/2, 575); + m_screen.ChangeFontSize(22); + + AddTextButton(0, "Play", 400, 229, m_screen); + AddTextButton(1, "Leaderboard", 400, 306, m_screen); + AddTextButton(2, "Settings", 400, 384, m_screen); + AddTextButton(3, "Exit", 400, 461, m_screen); Menu_Py[4].StartX = -1; SDL_Event event; while (SDL_PollEvent(&event)) { @@ -172,7 +191,6 @@ eMenu Menu::SDLMain() break; default: key = event.key.keysym.sym & 0x7F; // Gets the character corresponding to the key - if (CharExist(key) == true) { // if character exists for (i = 2; i >= 0; i--) { MCode[i + 1] = MCode[i]; // shift code } @@ -180,7 +198,6 @@ eMenu Menu::SDLMain() if (strcmp(MCode, "tide") == 0 || strcmp(MCode, "TIDE") == 0) { return mEdit; // If level editor selected } - } } } break; @@ -209,7 +226,7 @@ eMenu Menu::SDLMain() /*** SDL Main Menu Language choice ***/ /*************************************/ -eMenu Menu::SDLMain_Language() +/*eMenu Menu::SDLMain_Language() { int NCol = 1; int NL; @@ -347,7 +364,7 @@ eMenu Menu::SDLMain_Language() } while (true); return mQuit; -} +}*/ /*** SDL Main Menu Settings ***/ /******************************/ @@ -373,9 +390,7 @@ void Menu::InitMain_Options() AddButton(3, earth, 180, 400); // Center text left - CenterM = 120 + Sprites[T_menu].Dim[0].L / 2; - DrawText(CenterM, 490, T_menu, Sprites[fmenu].Image[0]); - AddButton(4, T_menu, CenterM, 490); + AddTextButton(4, "Menu", 100, 490, m_screen); // Sound buttons Sprites[arrows].Draw(250, 110, 1, Sprites[fmenu].Image[0]); @@ -535,7 +550,7 @@ eMenu Menu::SDLMain_Options() PyE = 2; break; case 3: // Language choice - SDLMain_Language(); + //SDLMain_Language(); PyE = 3; break; case 5: // Lower sound effects volume @@ -682,12 +697,9 @@ eMenu Menu::SDLMain_Speed() Sprites[menu].Draw(400, 340, 0, Sprites[fmenu].Image[0]); Sprites[title].Draw(400, 65, 0, Sprites[fmenu].Image[0]); - DrawText(400, 225, T_easy, Sprites[fmenu].Image[0]); - AddButton(0, T_easy, 400, 225); - DrawText(400, 340, T_normal, Sprites[fmenu].Image[0]); - AddButton(1, T_normal, 400, 340); - DrawText(400, 455, T_hard, Sprites[fmenu].Image[0]); - AddButton(2, T_hard, 400, 455); + AddTextButton(0, "Easy", 400, 225, m_screen); + AddTextButton(1, "Normal", 400, 340, m_screen); + AddTextButton(2, "Hard", 400, 455, m_screen); Menu_Py[3].StartX = -1; SDL_Event event; @@ -788,12 +800,9 @@ eMenu Menu::SDLMain_Level() Sprites[menu].Draw(400, 340, 0, Sprites[fmenu].Image[0]); Sprites[title].Draw(400, 65, 0, Sprites[fmenu].Image[0]); - DrawText(400, 225, T_new_game, Sprites[fmenu].Image[0]); - AddButton(0, T_new_game, 400, 225); - DrawText(400, 320, T_old_level, Sprites[fmenu].Image[0]); - AddButton(1, T_old_level, 400, 320); - DrawText(400, 455, T_menu, Sprites[fmenu].Image[0]); - AddButton(2, T_menu, 400, 455); + AddTextButton(0, "New game", 400, 225, m_screen); + AddTextButton(1, "Old level", 400, 340, m_screen); + AddTextButton(2, "Menu", 400, 445, m_screen); AddButton(3, arrows, 330, 380); AddButton(4, arrows, 470, 380); @@ -911,7 +920,7 @@ eMenu Menu::SDLMain_Level() m_screen.PrintSprite(arrows, 3, 470, 380); } - DrawNumber(400, 380, Level + 1); + m_screen.PrintText(std::to_string(Level + 1), 400, 380); if (PyE != 3 && PyE != 4) { Print_Main(); @@ -1092,7 +1101,7 @@ eMenu Menu::SDLMain_HR() } } - // Test if finished + // Test if Endished if (Done != -1 && Done < currentTime) { return mGame; } @@ -1161,12 +1170,9 @@ void Menu::Print_InGame() Sprites[menu].Draw(340, 300, 0, Sprites[fmenu].Image[0]); - DrawText(340, 185, T_continue, Sprites[fmenu].Image[0]); - AddButton(0, T_continue, 340, 185); - DrawText(340, 300, T_moptions, Sprites[fmenu].Image[0]); - AddButton(1, T_moptions, 340, 300); - DrawText(340, 415, T_exit_game, Sprites[fmenu].Image[0]); - AddButton(2, T_exit_game, 340, 415); + AddTextButton(0, "Continue", 340, 185, m_screen); + AddTextButton(1, "Settings", 340, 300, m_screen); + AddTextButton(2, "Exit from game", 340, 415, m_screen); Menu_Py[3].StartX = -1; } @@ -1266,34 +1272,34 @@ eMenu Menu::SDLMain_Score(bool EditScore) int i; int NEdit = -1; char Provi[256]; - int PosCur = 0; char key; - // Searches the score index to edit + // Cherche le numéro du score à remplacer si edition des scores if (EditScore) { - for (i = 7; i >= 0; i--) { + for (i = 0; i < 8; i++) { if (Pref.Sco[i].Score < Pref.Score) { NEdit = i; + break; } } if (NEdit == -1) { return mMenu; } - if (NEdit < 7) { // if shifting must be done + if (NEdit < 7) { // Si doit fair un décalage for (i = 7; i > NEdit; i--) { Pref.Sco[i].Score = Pref.Sco[i - 1].Score; - strcpy(Pref.Sco[i].Name, Pref.Sco[i - 1].Name); + Pref.Sco[i].Name = Pref.Sco[i - 1].Name; } } - // Erase name and enter score + // Efface le nouveau nom et met le score Pref.Sco[NEdit].Score = Pref.Score; - Pref.Sco[NEdit].Name[0] = 0; + Pref.Sco[NEdit].Name.clear(); } - // Sets mouse on entire display - m_mouse.Init(Menu_Py); + // Met la sourie sur tous l'ecran + m_mouse.Init(Menu_Py); // Initialise la sourie Menu_Py[0].StartX = 0; Menu_Py[0].StartY = 0; Menu_Py[0].EndX = 800; @@ -1306,41 +1312,47 @@ eMenu Menu::SDLMain_Score(bool EditScore) SDL_StartTextInput(); } - // Fetch events + // Prend les evenements do { - // Erase background + // Efface le background m_screen.CleanSpriteAndScreen(fmenu); SDL_RenderClear(sdlRenderer); - // Set background image and build display + // Prend l'image du background et fait l'affichage Sprites[background_menu].Draw(400, 300, 0, Sprites[fmenu].Image[0]); // Draw title and commands - DrawText(400, 50, T_better_scores, Sprites[fmenu].Image[0]); - DrawText(400, 550, T_press_any_key, Sprites[fmenu].Image[0]); + m_screen.ChangeFontColor(255, 255, 0); + m_screen.PrintText("Leaderboard", 400-m_screen.TextLength("Leaderboard")/2, 50); + #ifndef ANDROID + m_screen.PrintText("Press enter to continue", 400-m_screen.TextLength("Press enter to continue")/2, 550); + #else + m_screen.PrintText("Tap to continue", 400-m_screen.TextLength("Tap to continue")/2, 550); + #endif + m_screen.ChangeFontColor(255, 255, 255); // Draw scores for (i = 0; i < 8; i++) { sprintf(Provi, "%d", i + 1); - DrawString(70, 120 + i * (360 / 7), Provi, Sprites[fmenu].Image[0]); + m_screen.PrintText(Provi, 70, 120 + i * (360 / 7)); if (EditScore == false || NEdit != i) { - if (Pref.Sco[i].Name[0]) { - DrawString(140, 120 + i * (360 / 7), Pref.Sco[i].Name, Sprites[fmenu].Image[0]); + if (!Pref.Sco[i].Name.empty()) { + m_screen.PrintText(Pref.Sco[i].Name, 140, 120 + i * (360 / 7)); } else { - DrawString(140, 120 + i * (360 / 7), Points, Sprites[fmenu].Image[0]); + m_screen.PrintText(Points, 140, 120 + i * (360 / 7)); } } sprintf(Provi, "%i", Pref.Sco[i].Score); - DrawString(740 - StringLength(Provi), 120 + i * (360 / 7), Provi, Sprites[fmenu].Image[0]); + m_screen.PrintText(Provi, 740 - m_screen.TextLength(std::string(Provi)), 120 + i * (360 / 7)); } - // Erase background + // Efface le background SDL_Event event; while (SDL_PollEvent(&event)) { - m_mouse.GetEvent(event, PyE); - m_gamepad.GetEvent(event); + m_mouse.GetEvent(event, PyE); // Handle mouse + m_gamepad.GetEvent(event); // Handle gamepad switch (event.type) { case SDL_WINDOWEVENT: @@ -1348,41 +1360,31 @@ eMenu Menu::SDLMain_Score(bool EditScore) SDL_RenderPresent(sdlRenderer); } break; - case SDL_KEYDOWN: // Waits a Keyboard press + case SDL_KEYDOWN: // Prend un touche au clavier if (event.key.state == SDL_PRESSED) { - m_audio.Play(sClick); - if (EditScore == false && event.key.keysym.sym != SDLK_F12) { - event.key.keysym.sym = SDLK_RETURN; + if (NEdit >= 0 && event.key.keysym.sym == SDLK_BACKSPACE && !Pref.Sco[NEdit].Name.empty()) { + Pref.Sco[NEdit].Name.pop_back(); } + m_audio.Play(sClick); switch (event.key.keysym.sym) { case SDLK_F12: // Save screenshot if (event.key.repeat == 0) { Utils::doScreenshot(sdlRenderer); } break; - case SDLK_ESCAPE: // Validates entry + case SDLK_ESCAPE: // Valide l'entrée case SDLK_RETURN: case SDLK_KP_ENTER: if (EditScore) { SDL_StopTextInput(); } return mMenu; - case SDLK_BACKSPACE: // Erases - if (PosCur) { - PosCur--; - Pref.Sco[NEdit].Name[PosCur] = 0; - } - break; - default: - break; } } break; case SDL_TEXTINPUT: - /* Add new text onto the end of our text */ - if (StringLength(Pref.Sco[NEdit].Name) < LSCOREMAX && PosCur < 79 && CharExist(event.text.text[0])) { - PosCur += strlen(event.text.text); - strcat(Pref.Sco[NEdit].Name, event.text.text); + if (NEdit >= 0) { + Pref.Sco[NEdit].Name += event.text.text; } break; case SDL_QUIT: @@ -1393,20 +1395,24 @@ eMenu Menu::SDLMain_Score(bool EditScore) } } - // Handle variables + // Gère les variables previousTime = currentTime; currentTime = SDL_GetTicks(); Sleeping(); - if (EditScore) { // Handle the scores edition drawing - DrawString(140, 120 + NEdit * (360 / 7), Pref.Sco[NEdit].Name); + if (EditScore && NEdit >= 0 && NEdit < 8) { // Handle the scores edition drawing + if (!Pref.Sco[NEdit].Name.empty()) { + m_screen.PrintText(Pref.Sco[NEdit].Name, 140, 120 + NEdit * (360 / 7)); + } i = (currentTime / 50) % 20; // Draw cursors m_screen.PrintSprite(arrow_left, i, 110, 120 + NEdit * (360 / 7)); - m_screen.PrintSprite(arrow_right, i, 180 + StringLength(Pref.Sco[NEdit].Name), 120 + NEdit * (360 / 7)); + + int textLen = Pref.Sco[NEdit].Name.empty() ? 0 : m_screen.TextLength(Pref.Sco[NEdit].Name); + m_screen.PrintSprite(arrow_right, i, 180 + textLen, 120 + NEdit * (360 / 7)); } - // Update render + // Echange les buffets video SDL_RenderPresent(sdlRenderer); } while (true); diff --git a/src/menu.h b/src/menu.h index 5db645e..c634ea4 100644 --- a/src/menu.h +++ b/src/menu.h @@ -26,6 +26,8 @@ #include "preference.h" +#include + void Sleeping(); class Game; @@ -67,6 +69,9 @@ class Menu Screen &m_screen; Mouse &m_mouse; Gamepad &m_gamepad; + + int Year = 2026; + std::string CopyrightText = "G.P.L. Game - Copyright 2023-" + std::to_string(Year) + " By Johnny Jazeix (fork of Ri-Li originally written by D. Roux-Serret), Music by MAF"; }; #endif diff --git a/src/preference.h b/src/preference.h index f2f9eac..02c4f24 100644 --- a/src/preference.h +++ b/src/preference.h @@ -25,6 +25,7 @@ #define PREFERENCE_DOM_ #include // for SDL_MIX_MAXVOLUME +#include #define SPEED_MAX 180.0 #define SPEED_AVERAGE 120.0 @@ -58,7 +59,7 @@ /*** Possible pieces on the level ***/ #define C_None 0 #define C_Rail 1 -#define C_Car 2 +#define C_Wagon 2 #define C_Expand 3 #define C_Shrink 4 #define C_Speed 5 @@ -77,7 +78,7 @@ enum e_Difficulty { struct sScore { int Score; - char Name[80]; + std::string Name; }; /*** Old Preferences structures, UNUSED ***/ diff --git a/src/screen.cc b/src/screen.cc index 2eea0ab..199a00d 100644 --- a/src/screen.cc +++ b/src/screen.cc @@ -22,10 +22,38 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include "preference.h" -#include "sprite.h" #include "screen.h" +#include "sprite.h" +#include "utils.h" extern Sprite *Sprites; +extern SDL_Renderer *sdlRenderer; + +/*** Constructor ***/ +/*******************/ +Screen::Screen() +{ + // Loading font + char fontPath[512]; + strcpy(fontPath, "Assets/Fonts/comic.ttf"); + Utils::GetPath(fontPath); + m_font = TTF_OpenFont(fontPath, 28); + + // Selecting font color + fColor.r = 255; + fColor.g = 255; + fColor.b = 255; + fColor.a = 255; +} + +/*** Destructor ***/ +/******************/ +Screen::~Screen() +{ + // Destroying font + SDL_DestroyTexture(fontTexture); + TTF_CloseFont(m_font); +} /*** Display a sprite ***/ /************************/ @@ -40,30 +68,60 @@ void Screen::PrintCable(int dx, int dy, int fx, int fy) Sprites[rope].PrintRope(dx, dy, fx, fy); } +void Screen::ChangeFontSize(int size){ + TTF_SetFontSize(m_font, size); +} + +void Screen::ChangeFontColor(float r, float g, float b){ + fColor.r = r; + fColor.g = g; + fColor.b = b; + fColor.a = 255; +} + /*** Display a text ***/ /**********************/ -void Screen::PrintText(e_Sprite Text, int x, int y) +void Screen::PrintText(const std::string &Text, int x, int y) { - Sprites[Text].Draw(x, y, 0); + fontSurface = TTF_RenderUTF8_Blended(m_font, Text.c_str(), fColor); // Rendering text + fontTexture = SDL_CreateTextureFromSurface(sdlRenderer, fontSurface); // Creating texture + + // Setting position and size + SDL_Rect dst; + dst.x = x; + dst.y = y; + dst.w = fontSurface->w; + dst.h = fontSurface->h; + + // Rendering text + SDL_RenderCopy(sdlRenderer, fontTexture, nullptr, &dst); +} + +int Screen::TextLength(std::string Text){ + int w,h; + TTF_SizeUTF8(m_font, Text.c_str(), &w, &h); + return w; } /*** Display game settings ***/ /*****************************/ -void Screen::PrintOptions(int Nlives, int NScore) +void Screen::PrintOptions(int NV, int NScore) { int x, y; Score = NScore; - DrawNumber(740, 215, Score); + ChangeFontSize(24); + PrintText(std::to_string(Score), 740 - TextLength(std::to_string(Score))/2, 215); + ChangeFontSize(22); - if (Nlives > 10) { - Nlives = 10; // Clamp to avoid going off screen + if (NV > 10) { + NV = 10; // Clamp to avoid going off screen } - for (int i = 0; i < Nlives; ++i) { // Display lives + for (int i = 0; i < NV; ++i) { // Display lives x = i % 2; x = x * 44 + 38 + LT * D_Case; y = i / 2; - y = 384 + y * 46; + y = 394 + y * 46; Sprites[logo_health].Draw(x, y, 0); } } diff --git a/src/screen.h b/src/screen.h index e4431d7..2cc0f7f 100644 --- a/src/screen.h +++ b/src/screen.h @@ -24,23 +24,36 @@ #ifndef SCREEN_DOM_ #define SCREEN_DOM_ -#include "sprite.h" +#include +#include +#include +#include +#include #include "preference.h" +#include "string" +#include "sprite.h" class Screen { public: - Screen() = default; - ~Screen() = default; + Screen(); + ~Screen(); void PrintSprite(e_Sprite NumSpr, int Num, int x, int y); // Displays a sprite void PrintCable(int dx, int dy, int fx, int fy); // Displays a cable/rope - void PrintText(e_Sprite Text, int x, int y); // Displays text + void ChangeFontSize(int size); // Change font size + void ChangeFontColor(float r, float g, float b); + void PrintText(const std::string &Text, int x, int y); // Displays text + int TextLength(std::string Text); void PrintOptions(int Nlives, int NScore); // Displays information on the side void CleanSpriteAndScreen(e_Sprite NumSpritebackground); // Erases display with background image private: int Score { -1 }; // Stores displayed score + TTF_Font* m_font; + SDL_Color fColor; + SDL_Surface* fontSurface; + SDL_Texture* fontTexture; }; #endif diff --git a/src/sprite.cc b/src/sprite.cc index 407cd4e..098e96f 100644 --- a/src/sprite.cc +++ b/src/sprite.cc @@ -35,11 +35,6 @@ extern Sprite *Sprites; extern int NSprites; extern sNewPreference Pref; -static const char *TextOrder = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-!?*+<>%$()&;"; -static const char *TextOrder2 = "abcdefghijklmnopqrstuvwxyz0123456789,_|?*+<>%$[]&;"; -static int TextTable[256]; - -char Languages[31][16]; // Stores languages int NTexts = 0; bool shouldDrawLoading = false; @@ -67,38 +62,6 @@ void DrawLoading() } } -/*** Loads the sprite of a language ***/ -/**************************************/ -bool LoadLanguage() -{ - long L, P; - int i; - unsigned char *Buf; - char PathFile[512]; - - strcpy(PathFile, Languages[Pref.Language]); - Utils::GetPath(PathFile); - if (Utils::FileExists(PathFile) == false) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to find '%s'", Languages[Pref.Language]); - return false; - } - L = Utils::LoadFile(PathFile, Buf); - - // Reads sprites - P = 0; - for (i = 0; i < NTexts; i++) { - if (Sprites[T_level + i].N) { - Sprites[T_level + i].Delete(); - } - if (Sprites[T_level + i].Load(Buf, P) == false) { - return false; - } - } - delete[] Buf; // Frees memory from the sprite file - - return true; -} - /*** Loads the game's sprites ***/ /********************************/ bool LoadSprites() @@ -108,71 +71,28 @@ bool LoadSprites() unsigned char *Buf; int NSp; - char PathFile[512] = "language.dat"; - Utils::GetPath(PathFile); + char PathFile[512] = "Assets/Sprites.dat"; - // Initialize characters table for texts - for (i = 0; i < 256; i++) { - TextTable[i] = -1; - } - i = 0; - while (TextOrder[i] != 0) { - TextTable[(int)(TextOrder[i])] = i; - i++; - } - i = 0; - while (TextOrder2[i] != 0) { - TextTable[(int)(TextOrder2[i])] = i; - i++; - } - - // *** Loads the languages file *** - // ******************************** - if (Utils::FileExists(PathFile) == false) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to find 'language.dat'"); + // Check is exist this file + Utils::GetPath(PathFile); + if (!Utils::FileExists(PathFile)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to find 'sprites.dat'"); return false; } + // Reading this file L = Utils::LoadFile(PathFile, Buf); - - // Read the sprites count - NSp = (int)(Buf[0]) * 256 + (int)(Buf[1]); - NSp += N_SPRITESFOND + 2; - NTexts = (int)(Buf[2]) * 256 + (int)(Buf[3]); - Pref.NLanguages = (int)(Buf[4]) * 256 + (int)(Buf[5]); - - NSprites = NSp + NTexts + Pref.NLanguages; - Sprites = new Sprite[NSprites]; - - // Fetch languages names - P = 6; - for (i = 0; i < Pref.NLanguages; i++) { - strcpy(Languages[i], (char *)(Buf + P)); - P += strlen((char *)(Buf + P)) + 1; - } - - // Load languages sprite - for (i = 0; i < Pref.NLanguages; i++) { - if (Sprites[T_Language + i].Load(Buf, P) == false) { - return false; - } + if (L <= 0 || Buf == nullptr) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to load file"); + return false; } - if (Sprites[loading].Load(Buf, P) == false) { - return false; // Loading sprite - } - shouldDrawLoading = true; // can display loading sprite + P = 0; + // Calculating sprites count + NSp = (int)(Buf[P]) * 256 + (int)(Buf[P + 1]); - delete[] Buf; + Sprites = new Sprite[NSp]; + NSprites = NSp; - // *** loads sprites file *** - // ************************** - strcpy(PathFile, "sprites.dat"); - Utils::GetPath(PathFile); - if (Utils::FileExists(PathFile) == false) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to find 'sprites.dat'"); - return false; - } - L = Utils::LoadFile(PathFile, Buf); // Reads sprites P = 0; @@ -199,123 +119,10 @@ bool LoadSprites() delete[] Buf; // Frees memory from the sprites file - // *** Loads language *** - // ********************** - if (Pref.Language != -1) { - LoadLanguage(); - } - shouldDrawLoading = false; // Disable loading sprite return true; } -/*** Returns the length of a number ***/ -/**************************************/ -int NumberLength(int C) -{ - int l = 0; - - do { - l += Sprites[digits].Dim[(C % 10)].L; - C /= 10; - if (C) { - l += GAP_BETWEEN_NUMBERS; - } - } while (C); - - return l; -} - -/*** Returns the length of a string ***/ -/**************************************/ -int StringLength(char *Text) -{ - int i = 0; - int l = 0; - int Le; - - while (Text[i] != 0) { - Le = (int)(Text[i]); - if (TextTable[Le] != -1) { - l += Sprites[letters].Dim[(TextTable[Le])].L; - if (Text[i + 1] != 0) { - l += GAP_BETWEEN_LETTERS; - } - } - else { - if (Le == (int)(' ')) { - l += SPACE_LENGTH; - } - } - - i++; - } - - return l; -} - -/*** Checks if a char exists ***/ -/*******************************/ -bool CharExist(char C) -{ - if ((int)(C) < 0) { - return false; - } - if (C == ' ') { - return true; - } - if (TextTable[(int)(C)] != -1) { - return true; - } - return false; -} -/*** Displays a number ***/ -/*************************/ -void DrawNumber(int x, int y, int Number, SDL_Texture *Background) -{ - int const l = NumberLength(Number); - - x += l / 2; - do { - Sprites[digits].Draw(x - (Sprites[digits].Dim[(Number % 10)].L) / 2, y, Number % 10, Background); - x -= Sprites[digits].Dim[(Number % 10)].L + GAP_BETWEEN_NUMBERS; - Number /= 10; - } while (Number); -} - -/*** Display a string ***/ -/************************/ -void DrawString(int x, int y, char *Text, SDL_Texture *background) -{ - int i = 0; - int Le; - - // TODO Handle here unicode - while (Text[i] != 0) { - Le = (int)(Text[i]); - - if (TextTable[Le] != -1) { // If known char - Le = TextTable[Le]; - Sprites[letters].Draw(x + (Sprites[letters].Dim[Le].L / 2), y, Le, background); - x += Sprites[letters].Dim[Le].L + GAP_BETWEEN_LETTERS; - } - else { // if there's a space - if (Le == (int)(' ')) { - x += SPACE_LENGTH - GAP_BETWEEN_LETTERS; - } - } - - i++; - } -} - -/*** Display text in a language ***/ -/**********************************/ -void DrawText(int x, int y, e_Sprite Text, SDL_Texture *Background) -{ - Sprites[Text].Draw(x, y, 0, Background); -} - Sprite::~Sprite() { if (N) { diff --git a/src/sprite.h b/src/sprite.h index 7ce3117..23f96b4 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -50,7 +50,7 @@ enum e_Sprite { cargo_wagon, engine_wagon, cistern_wagon, - car, + wagon, expander, shrinker, speed, @@ -84,107 +84,12 @@ enum e_Sprite { fgame, fmenu, rope, - loading, - - T_level, - T_lives, - T_options, - T_score, - T_press_any_key, - T_continue, - T_moptions, - T_exit_game, - T_play, - T_scores, - T_better_scores, - T_quit, - T_new_game, - T_old_level, - T_menu, - T_easy, - T_normal, - T_hard, -#ifndef DCHILDREN - T_question, - T_tart1, - T_tart2, - T_tart3, - T_tart4, - T_tart5, - T_tart6, - T_tart7, - T_tart8, - T_tart9, - T_tart10, - T_tart11, - T_tart12, - T_tart13, - T_tart14, - T_tart15, - T_tart16, - T_tart17, - T_tart18, - T_tart19, - T_tart20, - T_tart21, - T_tart22, - T_tart23, - T_tart24, - T_tart25, - T_tart26, - T_tart27, - T_tart28, - T_tart29, - T_tart30, - T_art1, - T_art2, - T_art3, - T_art4, - T_art5, - T_art6, - T_art7, - T_art8, - T_art9, - T_art10, - T_art11, - T_art12, - T_art13, - T_art14, - T_art15, - T_art16, - T_art17, - T_art18, - T_art19, - T_art20, - T_art21, - T_art22, - T_art23, - T_art24, - T_art25, - T_art26, - T_art27, - T_art28, - T_art29, - T_art30, -#endif - T_Language, - - T_ENDTEXT + loading }; void DrawLoading(); // displays the loader on the startup page -bool LoadLanguage(); // Loads sprites of a language bool LoadSprites(); // Loads all sprites -int NumberLength(int C); // Returns the length in pixels of a number -int StringLength(char *Text); // Returns the length in pixels of a string. -bool CharExist(char C); // Checks if a character exists - -void DrawNumber(int x, int y, int Number, SDL_Texture *Background = nullptr); // Displays a number -void DrawString(int x, int y, char *Text, SDL_Texture *Background = nullptr); // Displays a string - -void DrawText(int x, int y, e_Sprite Text, SDL_Texture *Background = nullptr); // Displays a text in the language - class Sprite { public: diff --git a/src/utils.cc b/src/utils.cc index 27b6b65..f37d9ff 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -298,9 +298,9 @@ bool Utils::LoadPref() } Pref.Sco[i].Score = std::stoi(pv); if (pv) { - pv = ini.GetValue("highscore", nameKey.c_str(), Pref.Sco[i].Name); + pv = ini.GetValue("highscore", nameKey.c_str(), Pref.Sco[i].Name.c_str()); } - strncpy(Pref.Sco[i].Name, pv, 80); + Pref.Sco[i].Name = pv; } return true; } @@ -322,7 +322,7 @@ bool Utils::LoadPref() Pref.LevelMax[2] = oldPref.Difficulte == Hard ? oldPref.NiveauMax : 0; for (int i = 0; i < 8; ++i) { Pref.Sco[i].Score = oldPref.Sco[i].Score; - strncpy(Pref.Sco[i].Name, oldPref.Sco[i].Name, 80); + Pref.Sco[i].Name = std::string(oldPref.Sco[i].Name); } // TODO Delete old file at some file return true; @@ -354,7 +354,7 @@ void Utils::SavePref() std::string scoreKey = "score_" + std::to_string(i); std::string nameKey = "name_" + std::to_string(i); ini.SetValue("highscore", scoreKey.c_str(), std::to_string(Pref.Sco[i].Score).c_str()); - ini.SetValue("highscore", nameKey.c_str(), Pref.Sco[i].Name); + ini.SetValue("highscore", nameKey.c_str(), Pref.Sco[i].Name.c_str()); } ini.SaveFile(PathPref); }