diff options
Diffstat (limited to 'jeu-test/tetris_lan_src/menu.c')
-rw-r--r-- | jeu-test/tetris_lan_src/menu.c | 711 |
1 files changed, 711 insertions, 0 deletions
diff --git a/jeu-test/tetris_lan_src/menu.c b/jeu-test/tetris_lan_src/menu.c new file mode 100644 index 0000000..5e6b276 --- /dev/null +++ b/jeu-test/tetris_lan_src/menu.c @@ -0,0 +1,711 @@ + +#include "includes.h" + +#define NBELEM(tab) (sizeof(tab) / sizeof(tab[0])) + +#define CURS_Acc 0x200 + +enum +{ + MENU_State_FadeIn = 0, + MENU_State_Input, + MENU_State_FadeOut, +}; +
+#define OPT_Filename "tetris.opt"
+
+#define MENU_SFX_VALIDATION e_Sfx_MenuValidate
+#define MENU_SFX_CLIC e_Sfx_MenuClic
+ +#define HISC_Nb 8 +#define HISC_NameLg (10+1) +#define HISC_Filename "high.scr" +struct SScore +{ + char pName[HISC_NameLg]; + u32 nScore; +}; +struct SScore gpHighScores[HISC_Nb]; + +struct SMenu +{ + u32 nChoix; + u32 nState; // Etat (fade in...). + + s32 nFadeVal; + + u8 nSin; // Pour bouffoner le titre. + + s16 nCursPos; // Pour faire bouger le curseur. + s16 nCursAccel; + + // Variables pour saisie du nom. + u32 nScIdx; // Pos dans la chaîne. / Pas remis à 0 ! + char pScName[HISC_NameLg]; // Nom saisi. / Pas remis à 0 ! + + u8 pScKeyDown; // Pour pseudo trigger. + u32 nScRank; // Rang de classement. + +}; +struct SMenu gMenu; + +struct SMenuItm +{ + u32 nRval; // Valeur renvoyée. MENU_Null => Pas une ligne à valider. + u32 *pVal; // Si valeur à afficher dans une ligne, un ptr dessus. + u32 nValMin, nValMax; // Bornes de la valeur ci dessus. + char pStr[16]; // Texte affiché. On remplace le @ par la valeur. +}; + + + +// Curseur - Init. +void CurseurInit(void) +{ + gMenu.nCursPos = 0; + gMenu.nCursAccel = CURS_Acc; +} + +// Curseur - Déplacement. +void CurseurMove(void) +{ + gMenu.nCursAccel -= 0x20; // Gravité. + gMenu.nCursPos += gMenu.nCursAccel; + if (gMenu.nCursPos < 0) CurseurInit(); +} + +// Menu principal - Init. +// On pourrait passer un prm au cas où il y a ait plusieurs menus du même genre. +void MenuMainInit(void) +{ + gMenu.nChoix = 0; + + gMenu.nState = MENU_State_FadeIn; + gMenu.nFadeVal = 0; + + gMenu.nSin = 0; + CurseurInit(); + +} +// Idem, avec choix qui se replace sur 1 joueur ou LAN.
+void MenuMainInit2(void)
+{
+ MenuMainInit();
+ gMenu.nChoix = gVar.nGameMode;
+}
+ +// Menu - Init misc. +void MenuInitMisc(void) +{ + MenuMainInit(); + + char pEmptyName[HISC_NameLg] = ".........."; + gMenu.nScIdx = 0; + strcpy(gMenu.pScName, pEmptyName); + +} + +// Menu principal.
+#define MENUMAIN_INTERLIGNE 25 +u32 MenuMain(void) +{ + // >>> Possibilité de sortir ça pour faire un autre menu du même type. + struct SMenuItm pItems[] = + { + { MENU_Game_1Player, NULL, 0, 0, "1 PLAYER MODE" }, + { MENU_Game_LAN, &gVar.nTCPMaster, 0, 1, "LAN PLAY : " },
+// { MENU_Null, &gExg.nStartingLevel, 1, 5, "LEVEL : @" }, + { MENU_Null, &gExg.nStartingLevel, 1, 9, "LEVEL : @" },
+ { MENU_Null, &gExg.nHandicap, 0, 5, "HANDICAP : @" }, + { MENU_HallOfFame, NULL, 0, 0, "HALL OF FAME" },
+ { MENU_Options, NULL, 0, 0, "OPTIONS" }, + { MENU_Quit, NULL, 0, 0, "QUIT" }, + }; + u32 nNbLines = NBELEM(pItems); + // <<< + + u32 nRet = MENU_Null; + u32 i; + u32 nPosX, nPosY; + + + // Selon l'état. + switch (gMenu.nState) + { + case MENU_State_FadeIn : + gMenu.nFadeVal += 4; + if (gMenu.nFadeVal > 256) + { + gMenu.nState = MENU_State_Input; + gMenu.nFadeVal = -1; + } + break; + + case MENU_State_FadeOut : + gMenu.nFadeVal -= 4; + if (gMenu.nFadeVal < 0) + { + nRet = pItems[gMenu.nChoix].nRval; // Valeur choisie par l'utilisateur. + } + break; + + case MENU_State_Input : + // Gestion du clavier. + if (gVar.pKeysTrig[TRIG_UP]) + { + if (--gMenu.nChoix >= nNbLines) gMenu.nChoix = nNbLines - 1; + Sfx_PlaySfx(MENU_SFX_CLIC, e_SfxPrio_10);
+ } + if (gVar.pKeysTrig[TRIG_DOWN]) + { + if (++gMenu.nChoix >= nNbLines) gMenu.nChoix = 0; + Sfx_PlaySfx(MENU_SFX_CLIC, e_SfxPrio_10);
+ } + + // Une valeur numérique à changer ? + if (pItems[gMenu.nChoix].pVal != NULL) + { + if (gVar.pKeysTrig[TRIG_RIGHT])
+ {
+ if (++*pItems[gMenu.nChoix].pVal > pItems[gMenu.nChoix].nValMax)
+ *pItems[gMenu.nChoix].pVal = pItems[gMenu.nChoix].nValMax;
+ else
+ Sfx_PlaySfx(MENU_SFX_CLIC, e_SfxPrio_10);
+ } + if (gVar.pKeysTrig[TRIG_LEFT])
+ {
+ if (--*(s32 *)pItems[gMenu.nChoix].pVal < (s32)pItems[gMenu.nChoix].nValMin)
+ *pItems[gMenu.nChoix].pVal = pItems[gMenu.nChoix].nValMin;
+ else
+ Sfx_PlaySfx(MENU_SFX_CLIC, e_SfxPrio_10);
+ }
+ } + + // Validation. + if ((gVar.pKeysTrig[TRIG_Return] || gVar.pKeysTrig[TRIG_Space]) && pItems[gMenu.nChoix].nRval != MENU_Null) + { + gMenu.nState = MENU_State_FadeOut; + gMenu.nFadeVal = 256; + Sfx_PlaySfx(MENU_SFX_VALIDATION, e_SfxPrio_10);
+ } + break; + } + + // Affichage. + CurseurMove(); + + // Affichage des lignes. + nPosX = 40; + nPosY = (SCR_Height - ((nNbLines * MENUMAIN_INTERLIGNE) - (MENUMAIN_INTERLIGNE / 2))) / 2; + for (i = 0; i < nNbLines; i++) + { + // Une valeur numérique ? + if (pItems[i].pVal != NULL) + { + char *pPtr = strchr(pItems[i].pStr, '@'); + if (pPtr != NULL) *pPtr = (char)(0x30 + *pItems[i].pVal); + } + + // Print. + FontPrint((SCR_Width * (nPosY + (i * MENUMAIN_INTERLIGNE))) + nPosX, pItems[i].pStr); + // Et le patch dégueulasse pour la ligne Serveur/Client...
+ if (pItems[i].nRval == MENU_Game_LAN)
+ {
+ FontPrint((SCR_Width * (nPosY + (i * MENUMAIN_INTERLIGNE))) + nPosX + (strlen(pItems[i].pStr) * 16), *pItems[i].pVal ? "SERVER" : "CLIENT");
+ }
+
+ // Curseur. + if (i == gMenu.nChoix) + { + FontPrint((SCR_Width * (nPosY + (i * MENUMAIN_INTERLIGNE))) + (nPosX - 24) - (gMenu.nCursPos >> 8), ">"); + } + } + + // Le titre. + nPosX = (s32) (cos(gMenu.nSin * 2 * PI / 256) * ((SCR_Width - (6*16)) / 2)); // Faire préca table si trop lent. + FontPrint((SCR_Width * 8) + ((SCR_Width - (6*16)) / 2) + nPosX, "TETRIS"); + FontPrint((SCR_Width * (SCR_Height - 16 - 8)) + ((SCR_Width - (6*16)) / 2) - nPosX, "TETRIS"); + gMenu.nSin++; + + Fade(gMenu.nFadeVal, gVar.pBkgMenu); + + return (nRet); // Renvoie le choix. +} +
+
+// Menu item options
+struct SOptMenuItm
+{
+ u32 nRval; // Valeur renvoyée. MENU_Null => Pas une ligne à valider.
+ u32 nBit; // Bit à XORer.
+ char pStr[16]; // Texte affiché.
+ u8 nSkipLn; // Sauter ligne ou pas.
+ char pStrBit0[10]; // Texte affiché quand bit = 0.
+ char pStrBit1[10]; // Texte affiché quand bit = 1.
+};
+
+// Menu des options.
+#define MENUOPT_INTERLIGNE 26//28
+#define MENUOPT_INTERLIGNE2 20
+u32 MenuOptions(void)
+{
+ struct SOptMenuItm pItems[] =
+ {
+ { MENU_Null, OPT_Ghost, "GHOST:", 0, "OFF", "ON" },
+ { MENU_Null, OPT_Rotation, "ROTATION:", 1, "CLOCKWISE", "REVERSE" },
+ { MENU_Null, OPT_BlocksSet, "BLOCKS SET:", 1, "NORMAL", "EXTENDED" },
+ { MENU_Null, OPT_LAN_Hole, "LAN RND HOLE:", 0, "OFF", "ON" },
+ { MENU_Null, OPT_Sound, "SOUND:", 0, "OFF", "ON" },
+ { MENU_Main, 0, "MAIN MENU", 0, "", "" },
+ };
+ u32 nNbLines = NBELEM(pItems);
+
+ u32 nRet = MENU_Null;
+ u32 i;
+ u32 nPosX, nPosY;
+
+
+ // Selon l'état.
+ switch (gMenu.nState)
+ {
+ case MENU_State_FadeIn :
+ gMenu.nFadeVal += 4;
+ if (gMenu.nFadeVal > 256)
+ {
+ gMenu.nState = MENU_State_Input;
+ gMenu.nFadeVal = -1;
+ }
+ break;
+
+ case MENU_State_FadeOut :
+ gMenu.nFadeVal -= 4;
+ if (gMenu.nFadeVal < 0)
+ {
+ Opt_Save();
+ nRet = pItems[gMenu.nChoix].nRval; // Valeur choisie par l'utilisateur.
+ }
+ break;
+
+ case MENU_State_Input :
+ // Gestion du clavier.
+ if (gVar.pKeysTrig[TRIG_UP])
+ {
+ if (--gMenu.nChoix >= nNbLines) gMenu.nChoix = nNbLines - 1;
+ Sfx_PlaySfx(MENU_SFX_CLIC, e_SfxPrio_10);
+ }
+ if (gVar.pKeysTrig[TRIG_DOWN])
+ {
+ if (++gMenu.nChoix >= nNbLines) gMenu.nChoix = 0;
+ Sfx_PlaySfx(MENU_SFX_CLIC, e_SfxPrio_10);
+ }
+
+ // Une valeur à changer ?
+ if (pItems[gMenu.nChoix].nBit != 0)
+ {
+ if (gVar.pKeysTrig[TRIG_Return] || gVar.pKeysTrig[TRIG_Space] ||
+ gVar.pKeysTrig[TRIG_LEFT] || gVar.pKeysTrig[TRIG_RIGHT])
+ {
+ gVar.nOptFlags ^= pItems[gMenu.nChoix].nBit;
+ Sfx_PlaySfx(MENU_SFX_CLIC, e_SfxPrio_10);
+ }
+ }
+
+ // Validation.
+ if ((gVar.pKeysTrig[TRIG_Return] || gVar.pKeysTrig[TRIG_Space]) && pItems[gMenu.nChoix].nRval != MENU_Null)
+ {
+ gMenu.nState = MENU_State_FadeOut;
+ gMenu.nFadeVal = 256;
+ Sfx_PlaySfx(MENU_SFX_VALIDATION, e_SfxPrio_10);
+ }
+ break;
+ }
+
+ // Affichage.
+ CurseurMove();
+
+ // Titre.
+ char pTitle[] = "OPTIONS";
+ FontPrint((SCR_Width * 8) + ((SCR_Width - (strlen(pTitle) * 16)) / 2), pTitle);
+
+ // Affichage des lignes.
+ nPosX = 40;
+ nPosY = 42;
+ for (i = 0; i < nNbLines; i++)
+ {
+ // Curseur.
+ if (i == gMenu.nChoix)
+ {
+ FontPrint((SCR_Width * nPosY) + (nPosX - 24) - (gMenu.nCursPos >> 8), ">");
+ }
+ // Print.
+ FontPrint((SCR_Width * nPosY) + nPosX, pItems[i].pStr);
+ // Valeur du bit.
+ if (pItems[i].nBit)
+ {
+ char *pStr = (gVar.nOptFlags & pItems[i].nBit ? pItems[i].pStrBit1 : pItems[i].pStrBit0);
+ if (pItems[i].nSkipLn) nPosY += MENUOPT_INTERLIGNE2;
+ FontPrint((SCR_Width * nPosY) + SCR_Width - (strlen(pStr) * 16) - 16, pStr);
+ }
+ nPosY += MENUOPT_INTERLIGNE;
+ }
+
+ Fade(gMenu.nFadeVal, gVar.pBkgMenu);
+
+ return (nRet); // Renvoie le choix.
+}
+ + +// Menu des High-scores. +u32 MenuHighScores(void) +{ + u32 nRet = MENU_Null; + u32 i; + u32 nPosX, nPosY; + + + // Selon l'état. + switch (gMenu.nState) + { + case MENU_State_FadeIn : + gMenu.nFadeVal += 4; + if (gMenu.nFadeVal > 256) + { + gMenu.nState = MENU_State_Input; + gMenu.nFadeVal = -1; + } + break; + + case MENU_State_FadeOut : + gMenu.nFadeVal -= 4; + if (gMenu.nFadeVal < 0) + { + nRet = MENU_Main; // Sortie. + } + break; + + case MENU_State_Input : + // Gestion du clavier. + if (gVar.pKeysTrig[TRIG_Return] || gVar.pKeysTrig[TRIG_Space]) + { + gMenu.nState = MENU_State_FadeOut; + gMenu.nFadeVal = 256; + Sfx_PlaySfx(MENU_SFX_VALIDATION, e_SfxPrio_10);
+ } + break; + } + + // Affichage. + //CurseurMove(); + + // Titre. + char pTitle[] = "HALL OF FAME"; + FontPrint((SCR_Width * 8) + ((SCR_Width - (strlen(pTitle) * 16)) / 2), pTitle); + + // Affichage des lignes. + nPosX = 8; + nPosY = 40; + for (i = 0; i < HISC_Nb; i++) + { + char pStr[] = " "; + + // Nom. + FontPrint((SCR_Width * (nPosY + (i * 24))) + nPosX, gpHighScores[i].pName); + // Score. + MyItoa(gpHighScores[i].nScore, pStr); + FontPrint((SCR_Width * (nPosY + (i * 24))) + SCR_Width - (7 * 16) - 8, pStr); + +// /// Curseur. / Voir plus tard, pour marquer le score qui vient d'être fait ? +// if (i == gMenu.nChoix) +// { +// FontPrint((SCR_Width * (nPosY + (i * 32))) + (nPosX - 24) - (gMenu.nCursPos >> 8), ">"); +// } + } + + Fade(gMenu.nFadeVal, gVar.pBkgMenu); + + return (nRet); +} + + +// Scores - Check si un score entre au Hall of Fame. +// Out : -1, pas dedans / >= 0, rang. +s32 Scr_CheckHighSc(u32 nScorePrm) +{ + s32 i, nRank; + + nRank = -1; + for (i = HISC_Nb - 1; i >= 0; i--) + { + if (nScorePrm >= gpHighScores[i].nScore) + { + nRank = i; + } + } + + return (nRank); +} + +// Insère un nom dans la table. +void Scr_PutNameInTable(char *pName, u32 nScore) +{ + s32 nRank = Scr_CheckHighSc(nScore); + s32 i; + + if (nRank < 0) return; // Ne devrait pas arriver. + + // Décalage de la table. + for (i = HISC_Nb - 2; i >= nRank; i--) + { + strcpy(gpHighScores[i + 1].pName, gpHighScores[i].pName); + gpHighScores[i + 1].nScore = gpHighScores[i].nScore; + } + // Le score à insérer. + strcpy(gpHighScores[nRank].pName, pName); + gpHighScores[nRank].nScore = nScore; + +} + + +// RAZ de la table des high scores. +void Scr_RazTable(void) +{ + char pDefault[HISC_NameLg] = ".........."; + u32 i; + + for (i = 0; i < HISC_Nb; i++) + { + strcpy(gpHighScores[i].pName, pDefault); + gpHighScores[i].nScore = 0; + } + +} +
+// Calcule le checksum de la table des scores.
+u32 Scr_CalcChecksum(void)
+{
+ u32 i, j;
+ u32 nChk = 0;
+
+ for (i = 0; i < HISC_Nb; i++)
+ {
+ nChk += gpHighScores[i].nScore;
+ for (j = 0; j < HISC_NameLg; j++) nChk += ((u32)gpHighScores[i].pName[j]) << (8 * (j & 3));
+ }
+ return (nChk);
+}
+
+// Lecture du fichier des high scores.
+void Scr_Load(void)
+{
+ FILE *pFile;
+ u32 nChk;
+
+ if ((pFile = fopen(HISC_Filename, "rb")) != NULL)
+ {
+ // Le fichier existe, lecture.
+ fread(gpHighScores, sizeof(struct SScore), HISC_Nb, pFile);
+ fread(&nChk, sizeof(u32), 1, pFile);
+ fclose(pFile);
+ // Checksum ok ?
+ if (nChk != Scr_CalcChecksum())
+ {
+ // Wrong checksum, RAZ table.
+ printf("Scr_Load: Wrong checksum! Resetting table.\n");
+ Scr_RazTable();
+ }
+ }
+ else
+ {
+ // Le fichier n'existe pas, RAZ table.
+ Scr_RazTable();
+ }
+
+}
+
+// Sauvegarde du fichier des high scores.
+void Scr_Save(void)
+{
+ FILE *pFile;
+ u32 nChk;
+
+ if ((pFile = fopen(HISC_Filename, "wb")) == NULL)
+ {
+ printf("Unable to save highscores table.\n");
+ return;
+ }
+ // Sauvegarde des enregistrements.
+ fwrite(gpHighScores, sizeof(struct SScore), HISC_Nb, pFile);
+ // Checksum.
+ nChk = Scr_CalcChecksum();
+ fwrite(&nChk, sizeof(u32), 1, pFile);
+ fclose(pFile);
+
+}
+
+
+// Lecture du fichier des options.
+void Opt_Load(void)
+{
+ FILE *pFile;
+
+ if ((pFile = fopen(OPT_Filename, "rb")) != NULL)
+ {
+ // Le fichier existe, lecture.
+ fread(&gVar.nOptFlags, sizeof(gVar.nOptFlags), 1, pFile);
+ fclose(pFile);
+ }
+ else
+ {
+ // Le fichier n'existe pas, raz flags.
+ gVar.nOptFlags = OPT_Rotation | OPT_Sound;
+ }
+
+}
+
+// Sauvegarde du fichier des options.
+void Opt_Save(void)
+{
+ FILE *pFile;
+
+ if ((pFile = fopen(OPT_Filename, "wb")) == NULL)
+ {
+ printf("Unable to save options.\n");
+ return;
+ }
+ // Sauvegarde des flags.
+ fwrite(&gVar.nOptFlags, sizeof(gVar.nOptFlags), 1, pFile);
+ fclose(pFile);
+
+}
+ +// Init. +void MenuGetNameInit(void) +{ + MenuMainInit(); + gMenu.pScKeyDown = 0; // Pseudo trigger pour saisie du nom. + gMenu.nScRank = Scr_CheckHighSc(gExg.nScore); // Rang. + +} + +// Saisie du nom quand high-score. +u32 MenuGetName(void) +{ + u32 nRet = MENU_Null; + u32 i; + static u8 nCligno = 0; // POur clignotement du curseur.
+ + // Selon l'état. + switch (gMenu.nState) + { + case MENU_State_FadeIn : + gMenu.nFadeVal += 4; + if (gMenu.nFadeVal > 256) + { + gMenu.nState = MENU_State_Input; + gMenu.nFadeVal = -1; + } + break; + + case MENU_State_FadeOut : + gMenu.nFadeVal -= 4; + if (gMenu.nFadeVal < 0) + { + // Si pas de nom, mettre John Doe.
+ char pDefName[] = "JOHN DOE..";
+ if (gMenu.nScIdx == 0)
+ {
+ strcpy(gMenu.pScName, pDefName);
+ gMenu.nScIdx = strlen(pDefName);
+ }
+ // Rajoute le nom à la table.
+ Scr_PutNameInTable(gMenu.pScName, gExg.nScore); + Scr_Save(); // Sauvegarde du fichier. + + nRet = MENU_Main; // Sortie. + } + break; + + case MENU_State_Input : + // Gestion du clavier. + if (gVar.pKeysTrig[TRIG_Return]) + { + gMenu.nState = MENU_State_FadeOut; + gMenu.nFadeVal = 256; + Sfx_PlaySfx(MENU_SFX_VALIDATION, e_SfxPrio_10);
+ break; + } + + // On regarde quelle touche est enfoncée. + u32 nChr = 0; + + if (gVar.pKeys[SDLK_SPACE]) nChr = ' '; + for (i = SDLK_a; i <= SDLK_z; i++) + { + if (gVar.pKeys[i]) + { + nChr = i - SDLK_a + 'A'; + break; + } + } + for (i = SDLK_0; i <= SDLK_9; i++)
+ {
+ if (gVar.pKeys[i])
+ {
+ nChr = i - SDLK_0 + '0';
+ break;
+ }
+ }
+ if (gVar.pKeys[SDLK_BACKSPACE]) + { + nChr = SDLK_BACKSPACE; + } + + // Pseudo trigger. + if (gMenu.pScKeyDown == 0 && nChr) + { + if (nChr == SDLK_BACKSPACE) + { + if (gMenu.nScIdx) gMenu.pScName[--gMenu.nScIdx] = '.'; + } + else if (gMenu.nScIdx < strlen(gMenu.pScName)) + { + gMenu.pScName[gMenu.nScIdx++] = nChr; + } + gMenu.pScKeyDown = 1; + Sfx_PlaySfx(MENU_SFX_CLIC, e_SfxPrio_10);
+ } + else if (gMenu.pScKeyDown == 1 && nChr == 0) + { + gMenu.pScKeyDown = 0; // Release. + } + break; + } + + // Affichage. + + // Lignes. + char pWin[][20] = + { + "CONGRATULATIONS!", + "YOU RANKED #@", + "ENTER YOUR NAME:" + }; + // On rajoute le rank dans sa ligne. + char *pPtr = strchr(pWin[1], '@'); + if (pPtr != NULL) *pPtr = (char)(0x31 + gMenu.nScRank); + + FontPrint((SCR_Width * (8+16+16)) + ((SCR_Width - (strlen(pWin[0]) * 16)) / 2), pWin[0]); + FontPrint((SCR_Width * (40+40+16)) + ((SCR_Width - (strlen(pWin[1]) * 16)) / 2), pWin[1]); + FontPrint((SCR_Width * (72+64+16)) + ((SCR_Width - (strlen(pWin[2]) * 16)) / 2), pWin[2]); + FontPrint((SCR_Width * (104+64+16)) + ((SCR_Width - (strlen(gMenu.pScName) * 16)) / 2), gMenu.pScName); + // Curseur.
+ if (nCligno & 16) FontPrint((SCR_Width * (104+64+28)) + ((SCR_Width - (strlen(gMenu.pScName) * 16)) / 2) + (gMenu.nScIdx * 16), "-");
+ nCligno++;
+ + Fade(gMenu.nFadeVal, gVar.pBkgMenu); + + return (nRet); +} + + + |