/** * Show the game selection view. * *
* The "hidden" class is added on the footer, the game_start elements and the game_mode_selection * elements are show. The body margin is also set to 0 by adding the ingame class. *
*/ function showGameModeSelection() { document.getElementsByTagName("body")[0].classList.add("ingame"); document.getElementsByTagName("footer")[0].classList.add("hidden"); document.getElementsByClassName("game_start")[0].classList.add("hidden"); document.getElementsByClassName("game_mode_selection")[0].classList.remove("hidden"); } /** * Show the game selection view. * ** The "hidden" class is removed on the footer, the game_start elements and the game_mode_selection * elements are hidden. The body margin is also set to its normal value by removing the ingame * class. *
*/ function hideGameModeSelection() { document.getElementsByTagName("body")[0].classList.remove("ingame"); document.getElementsByTagName("footer")[0].classList.remove("hidden"); document.getElementsByClassName("game_start")[0].classList.remove("hidden"); document.getElementsByClassName("game_mode_selection")[0].classList.add("hidden"); } /** * Hide an error message on the first game_start_failed CSS element. * ** The element will be hidden by removing the hidden CSS class on the element. *
*/ function hideInvalidInputErrorMessage() { document.getElementsByClassName("game_start_failed")[0].classList.add("hidden"); } /** * Show an error message on the first game_start_failed CSS element. * ** The current error message text will be replaced by the given message and the element will be * shown, by removing the hidden CSS class on the element. *
* * @param {boolean} errorMessage the error message to show */ function showInvalidInputErrorMessage(errorMessage) { let gameStartFailedElement = document.getElementsByClassName("game_start_failed")[0]; gameStartFailedElement.textContent = errorMessage; gameStartFailedElement.classList.remove("hidden"); } /** * Determine whether a nickname is invalid. * ** A nickname is invalid when it only contains spaces characters or is empty. *
* * @returns whether a nickname is invalid */ function isNickNameInvalid() { return document.getElementById("game_username").value.trim() == ""; } /** * Determine whether a room code is invalid. * ** A room code is invalid when it only contains spaces characters or is empty. *
* * @returns whether a room code is invalid */ function isRoomCodeInvalid() { return document.getElementById("game_room_code").value.trim() == ""; } /** * Determine whether nickname and/or room code inputs are valid. * ** The nickname validity is always checked, while the room code validity is checked only when * checkRoomCode is true (because when creating a room or playing on a solo match, the room code is * not used so checking it would be useless and would require a valid room code). *
* * @param {boolean} checkRoomCode whether the room code input should be checked * @returns whether the checked inputs are valid */ function areInputsValid(checkRoomCode) { if (isNickNameInvalid()) { showInvalidInputErrorMessage("Le nom saisi n'est pas valide."); return false; } if (checkRoomCode && isRoomCodeInvalid()) { showInvalidInputErrorMessage("Le code de salon saisi n'est pas valide."); return false; } return true; } /** * Handler for the multiplayer room creation button */ function createMultiPlayerRoom() { if (!areInputsValid(false)) { return; } hideInvalidInputErrorMessage(); startGame(); } /** * Handler for the join room button */ function joinMultiPlayerRoom() { if (!areInputsValid(true)) { return; } hideInvalidInputErrorMessage(); joinGame(); } /** * Set the current theme for the game. * ** The theme preference is read from the local storage. *
* ** If accessing to the local storage is not allow, an error message which prevents playing the game * and requesting user to enable localStorage is shown, and the error is logged in the console. *
*/ function setCurrentTheme() { const htmlElement = document.getElementsByTagName("html")[0]; try { const currentTheme = localStorage.getItem("pref_theme"); if (currentTheme == "light") { htmlElement.classList.remove("dark"); htmlElement.classList.add("light"); } else { // Use dark theme by default htmlElement.classList.remove("light"); htmlElement.classList.add("dark"); } const btn = document.getElementsByClassName("theme_switcher")[0]; btn.addEventListener("pointerup", changeTheme); } catch (e) { console.error("Unable to set theme from localStorage", e); htmlElement.classList.add("dark"); } } /** * Change the theme from the current theme to its opposite. * ** If the current theme is "dark", it will become "light" and vice versa. *
* ** The new theme is saved in the localStorage, if the browser allows this action; otherwise, an * error message is shown in the console. *
*/ function changeTheme() { const currentTheme = localStorage.getItem("pref_theme"); const htmlElement = document.getElementsByTagName("html")[0]; let newTheme; if (currentTheme == "light") { htmlElement.classList.remove("light"); htmlElement.classList.add("dark"); newTheme = "dark"; } else { htmlElement.classList.remove("dark"); htmlElement.classList.add("light"); newTheme = "light"; } try { localStorage.setItem("pref_theme", newTheme); } catch (e) { console.error("Unable to save theme change to localStorage", e); } } /** * This function launches a single player game. It sends the api request to * create a game then it immediately start the game by sendind the startGame api */ async function startSoloGame(){ if (!areInputsValid(false)) { return; } hideInvalidInputErrorMessage(); username = document.getElementById("game_username").value; let data = {} data["username"] = username; await makeAPIRequest("createGame",data); start = makeAPIRequest("startGame"); start.then(()=>{ window.location.href = "/solo"; }) } /** * This function creates a multiplayer game by sending the createGame api call * then, if no error occured, redirects to the lobby page. */ async function startGame(){ username = document.getElementById("game_username").value; let data = {} data["username"] = username; response = makeAPIRequest("createGame",data); response.then((value) => { if (value["error"] != 0){ alert(value["msg"]); } else{ gameid = value["game_id"] window.location.href = "/lobby/" + gameid; } }); } /** * This function read the username and the room code in order to * join an already existing game, to do so it calls the joinGame endpoint * with the aftermentioned username and room code as parameter. */ async function joinGame(){ username = document.getElementById("game_username").value; gameid = document.getElementById("game_room_code").value; console.log(username); data = {} data["username"] = username; data["game_id"] = gameid; response = makeAPIRequest("joinGame",data); response.then((value)=>{ console.log(value); if (value["error"] != 0){ //alert(value["msg"]); } else{ window.location.href = "/lobby/" + gameid; } }) } // Set event listeners document.getElementById("play_button").addEventListener("click", showGameModeSelection); document.getElementById("back_button").addEventListener("click", hideGameModeSelection); document.getElementById("start_solo_game_button").addEventListener("click", startSoloGame); document.getElementById("create_room_button").addEventListener("click", createMultiPlayerRoom); document.getElementById("join_room_button").addEventListener("click", joinMultiPlayerRoom); // Execution of functions setCurrentTheme();