diff --git a/index.html b/index.html index 97a211f2a511b6734a0f565d97b6da136df8c6af..eeefd36b3e3ed4463a258c06e5bc1f099fb22397 100644 --- a/index.html +++ b/index.html @@ -22,8 +22,7 @@ <div class="topBar"> <div class="gameTitle">Flappy Birds</div> <div class="menuOptions"> - <div class="menuItem">Game</div> - <div class="menuItem" id="scoresButton">Scores</div> + <div class="menuItem" id="infoButton">Info</div> </div> </div> @@ -48,21 +47,22 @@ <span class="score_title"></span> <span class="score_val"></span> </div> - <!-- Schwierigkeitsgrad-Auswahl im difficultyContainer --> - <div id="difficultyContainer" class="difficultyContainer"> - <label for="difficulty">Wähle den Schwierigkeitsgrad:</label> - <select id="difficulty"> - <option value="langsam">Langsam</option> - <option value="normal">Normal</option> - <option value="schnell">Schnell</option> - </select> - </div> - - + <div class="start-container"> <button class="start-button" id="start-button">Start</button> - <!-- Eingabefeld für den Spielernamen --> - <input type="text" id="playerNameInput" placeholder="Enter your name" class="inputField"> + </div> + + <div id="infoBox" class="infoBox"> + <div class="infoContent"> + <span class="closeButton" id="closeInfoBox">×</span> + <h2>Spiel-Info</h2> + <p> + Willkommen zu Flappy Birds! Das Ziel dieses Spiels ist es, den Vogel durch die Lücken zwischen den Rohren fliegen zu lassen, ohne dabei die Rohre oder den Boden zu berühren. + Steuere den Vogel, indem du deine Handbewegungen verwendest. Du musst rechtzeitig springen, um Hindernisse zu vermeiden. + Jeder erfolgreiche Durchgang durch ein Rohr erhöht deinen Punktestand. + Viel Spaß beim Spielen! + </p> + </div> </div> diff --git a/script.js b/script.js index 716dd22cdbf844724a73afab6b96610a9d1f5441..7518c5ab01bf54c980ae392b24b62e004d467a98 100644 --- a/script.js +++ b/script.js @@ -1,245 +1,217 @@ +// Der Hauptkonzept dieses Codes basiert auf dem Flappy Bird Spiel von: +// https://github.com/kaizhelam/Flappy-Bird-Games -// Wähle das Vogel-Element und das Bild aus let bird = document.querySelector('.bird'); let img = document.getElementById('bird-1'); -// Hole die Eigenschaften des Vogel-Elements und des Hintergrund-Elements let bird_props = bird.getBoundingClientRect(); let background = document.querySelector('.background').getBoundingClientRect(); -// Wähle die Elemente für den Punktestand, Nachricht und Titel aus let score_val = document.querySelector('.score_val'); let message = document.querySelector('.GameOverMessage'); let score_title = document.querySelector('.score_title'); let bird_dy = 0; -let difficulty = 'schnell'; -let gravity = 0; -let move_speed = 0; -let iPipeseperation= 0; -let jumpheight = 0 +let gravity = 0.05; +let move_speed = 3.5; +let iPipeseperation = 130; +let jumpheight = -5.6; -let realX = 1 -let realY = 1 -let oldY = 0 -let birdflag = false +let realX = 1; +let realY = 1; +let oldY = 0; +let birdflag = false; const mascot = document.getElementById("mascot"); const speechBubble = document.getElementById("speechBubble"); -//Mascot let speaking = false; let mouthInterval; let textIndex = 0; let currentText = ''; -let showNextLetterTimeout; // Timeout-Variable für die showNextLetter-Funktion -// Verbinde mit Websocket +let showNextLetterTimeout; + const ws = new WebSocket("ws://localhost:453/ws"); -//Cursor let cursor = document.getElementById("cursor"); let flag = false; -let click = null +let click = null; ws.onmessage = function (event){ const data = JSON.parse(event.data); realY= window.innerHeight * data.y; realX= window.innerWidth * data.x; - click = data.click + click = data.click; cursor.style.left = (realX) + "px"; cursor.style.top = (realY) + "px"; if(click && !flag){ const Element = document.elementFromPoint(realX, realY); if (Element) { - simulateClick(Element) + simulateClick(Element); } } - }; - +}; -// Setze den Spielzustand auf "Start" und verstecke das Vogelbild let game_state = 'Start'; img.style.display = 'none'; message.classList.add('messageStyle'); - function setSpeech() { - return new Promise( + return new Promise( function (resolve, reject) { - let synth = window.speechSynthesis; - let id; + let synth = window.speechSynthesis; + let id; - id = setInterval(() => { - if (synth.getVoices().length !== 0) { - resolve(synth.getVoices()); - clearInterval(id); - } - }, 10); - } - ) + id = setInterval(() => { + if (synth.getVoices().length !== 0) { + resolve(synth.getVoices()); + clearInterval(id); + } + }, 10); } - function speak(text) { - speaking = true; - currentText = text; - textIndex = 0; - const speechBubble = document.getElementById("speechBubble"); - speechBubble.textContent = ''; // Leeren Sie den Text in der Sprechblase - clearInterval(mouthInterval); - mouthInterval = setInterval(toggleMouth, 500); // Ändern Sie die Zeitintervalle je nach Bedarf - showNextLetterTimeout = setTimeout(showNextLetter, 50); // Timeout für die showNextLetter-Funktion starten - } + ) +} - function showNextLetter() { - const speechBubble = document.getElementById("speechBubble"); - if (textIndex < currentText.length) { - speechBubble.textContent += currentText.charAt(textIndex); - textIndex++; - showNextLetterTimeout = setTimeout(showNextLetter, 50); // Timer für die nächste Buchstabe anzeigen - } else { - speaking = false; - clearInterval(mouthInterval); - resetMouth(); - } - } +function speak(text) { + speaking = true; + currentText = text; + textIndex = 0; + const speechBubble = document.getElementById("speechBubble"); + speechBubble.textContent = ''; + clearInterval(mouthInterval); + mouthInterval = setInterval(toggleMouth, 500); + showNextLetterTimeout = setTimeout(showNextLetter, 50); +} - function toggleMouth() { - mascot.classList.toggle('mouth-open'); - mascot.classList.toggle('mouth-closed'); +function showNextLetter() { + const speechBubble = document.getElementById("speechBubble"); + if (textIndex < currentText.length) { + speechBubble.textContent += currentText.charAt(textIndex); + textIndex++; + showNextLetterTimeout = setTimeout(showNextLetter, 50); + } else { + speaking = false; + clearInterval(mouthInterval); + resetMouth(); } +} - function resetMouth() { - - mascot.classList.remove('mouth-open'); - mascot.classList.remove('mouth-closed'); - } +function toggleMouth() { + mascot.classList.toggle('mouth-open'); + mascot.classList.toggle('mouth-closed'); +} - document.getElementById("mascot").addEventListener("click", function() { +function resetMouth() { + mascot.classList.remove('mouth-open'); + mascot.classList.remove('mouth-closed'); +} - if (!speaking) { +document.getElementById("mascot").addEventListener("click", function() { + if (!speaking) { + speechSynthesis.cancel(); + speak("Willkommen zu Flappy Birds! Deine Hand wird als Cursor erkannt, nutze diese um auf Start zu drücken. Weiche den Hindernissen aus indem du mit deiner Hand den Vogel springen lässt. Pass auf, falls der Vogel sich den Kopf stößt oder gegen eine der Röhren fliegt, ist es vorbei!"); + let s = setSpeech(); + let speech = new SpeechSynthesisUtterance(); + s.then((voices) => { + speech.voice = voices.find(a => a.lang === "de-DE"); + speech.text = currentText; + speech.lang = "de-DE"; + speech.volume = 1; + speech.voiceURI = "native"; speechSynthesis.cancel(); - speak("Willkommen zu Flappy Birds! Deine Hand wird als Cursor erkannt, nutze diese um auf Start zu drücken." + - " Weiche den Hindernissen aus indem du mit deiner Hand den Vogel springen lässt. Pass auf, falls der Vogel sich " + - "den Kopf stößt oder gegen eine der Röhren fliegt, ist es vorbei!"); - let s = setSpeech(); - let speech = new SpeechSynthesisUtterance(); - console.log(window.speechSynthesis.getVoices()) - s.then((voices) => { - //const voices = window.speechSynthesis.getVoices(); - console.log(voices.findIndex(a => a.lang === "de-DE")); - speech.voice = voices[voices.findIndex(a => a.lang === "de-DE")]; - speech.text = currentText; - speech.lang = "de-DE"; - speech.volume = 1; - speech.voiceURI = "native"; - speechSynthesis.cancel(); - window.speechSynthesis.speak(speech); - speechBubble.style.display = "block"; // Sprechblase anzeigen - }); + window.speechSynthesis.speak(speech); + speechBubble.style.display = "block"; + }); + } else { + speechSynthesis.cancel(); + speaking = false; + clearInterval(mouthInterval); + resetMouth(); + speechBubble.style.display = "none"; + clearTimeout(showNextLetterTimeout); + } +}); - } else { - speechSynthesis.cancel(); - speaking = false; - clearInterval(mouthInterval); - resetMouth(); - speechBubble.style.display = "none"; // Sprechblase ausblenden - clearTimeout(showNextLetterTimeout); // Timeout für die showNextLetter-Funktion löschen +document.addEventListener('DOMContentLoaded', () => { + const startButton = document.getElementById('start-button'); + startButton.addEventListener('click', () => { + if (game_state !== 'Play') { + message.innerHTML = ''; + score_title.innerHTML = 'Score : '; + score_val.innerHTML = '0'; + message.classList.remove('messageStyle'); + startButton.style.display = 'none'; + play(); } }); + const infoButton = document.getElementById('infoButton'); + const infoBox = document.getElementById('infoBox'); + const closeInfoBox = document.getElementById('closeInfoBox'); + infoButton.addEventListener('click', () => { + infoBox.style.display = 'block'; + }); + closeInfoBox.addEventListener('click', () => { + infoBox.style.display = 'none'; + }); -// Führe den folgenden Code aus, sobald das DOM geladen ist -document.addEventListener('DOMContentLoaded', () => { - - const playerNameInput = document.getElementById('playerNameInput'); - const scoresButton = document.getElementById('scoresButton'); - const scoreBoard = document.getElementById('scoreBoard'); - const scoreList = document.getElementById('scoreList'); - let scores = JSON.parse(localStorage.getItem('scores')) || []; - - // Event-Listener für den Mausklick auf den Start-Button - - - const startButton = document.getElementById('start-button'); - startButton.addEventListener('click', () => { - if (game_state !== 'Play') { - message.innerHTML = ''; - score_title.innerHTML = 'Score : '; - score_val.innerHTML = '0'; - message.classList.remove('messageStyle'); - startButton.style.display = 'none'; - play(); // Starte das Spiel - } + window.addEventListener('click', (event) => { + if (event.target === infoBox) { + infoBox.style.display = 'none'; } -)}); + }); +}); function simulateClick(element) { if (element) { - element.click(); // Klickereignis auf der derzeitigen cardElement -}} + element.click(); + } +} function setRestartButton(){ - var container = document.getElementById("gameover") + var container = document.getElementById("gameover"); const restartButton = document.createElement('button'); restartButton.textContent = "Play again!"; - restartButton.id = "restartButton"; // Eindeutige ID für den Neustart-Button - restartButton.classList.add("start-button") + restartButton.id = "restartButton"; + restartButton.classList.add("start-button"); restartButton.addEventListener('click', play); container.appendChild(restartButton); } -// Hauptspiellogik function play() { game_state = 'Play'; - // Entferne alle Rohre, zeige das Vogelbild, setze die Startposition des Vogels und starte das Spiel document.querySelectorAll('.pipe_sprite').forEach((e) => { e.remove(); }); - // Stoppe die Nachrichten- und Bildaktualisierungsintervalle img.style.display = 'block'; bird.style.top = '40vh'; - if (difficulty === 'langsam' || difficulty === 'normal' || difficulty === 'schnell') { - - //Passe die Bewegungsgeschwindigkeit basierend auf dem Schwierigkeitsgrad an - if (difficulty === 'langsam') { - move_speed = 1; - gravity = 0.01; - iPipeseperation = 600; - jumpheight = -1.6; - } - else if (difficulty === 'normal') { - move_speed = 2.5; - gravity = 0.03; - iPipeseperation = 190; - jumpheight = -3.6; - } - else if (difficulty === 'schnell') { - move_speed = 3.5; - gravity = 0.05; - iPipeseperation = 130; - jumpheight = -5.6; + + // Set up an interval to increase the bird's speed over time + let speedIncreaseInterval = setInterval(() => { + if (game_state === 'Play') { + move_speed += 0.1; // Increase the speed by 0.1 + gravity += 0.001; // Increase the gravity slightly + } else { + clearInterval(speedIncreaseInterval); // Clear the interval if the game is not in Play state } + }, 5000); // Increase the speed every 5 seconds requestAnimationFrame(create_pipe); - } function move() { - if (game_state !== 'Play') { return; } - // Überprüfe Kollisionen mit den Rohren und Spielende let pipe_sprite = document.querySelectorAll('.pipe_sprite'); pipe_sprite.forEach((element) => { let pipe_sprite_props = element.getBoundingClientRect(); bird_props = bird.getBoundingClientRect(); - // Kollisionserkennung if (pipe_sprite_props.right <= 0) { element.remove(); - } - else { + } else { if (bird_props.left < pipe_sprite_props.left + pipe_sprite_props.width && bird_props.left + bird_props.width > pipe_sprite_props.left && bird_props.top < pipe_sprite_props.top + pipe_sprite_props.height && @@ -248,7 +220,7 @@ function play() { document.querySelector('.GameOverMessage').innerHTML = 'Game Over'.fontcolor('red'); message.classList.add('GameOverMessageStyle'); img.style.display = 'none'; - setRestartButton() + setRestartButton(); } else { if (pipe_sprite_props.right < bird_props.left && pipe_sprite_props.right + move_speed >= bird_props.left && @@ -263,83 +235,63 @@ function play() { } requestAnimationFrame(move); - // Funktion für die Anwendung der Gravitation auf den Vogel - function apply_gravity() { if (game_state != 'Play') return; bird_dy += gravity; if ((realY + 50) < oldY && !birdflag) { - birdflag = true + birdflag = true; bird_dy = jumpheight; setTimeout(() => { img.src = 'images/Bird.png'; }, "300"); img.src = 'images/Bird-2.png'; setTimeout(()=> { - birdflag = false - }, "400") - + birdflag = false; + }, "400"); } - oldY = realY + oldY = realY; - - // Überprüfe, ob der Vogel den Bildschirmrand berührt und das Spiel beendet if (bird_props.top <= 0 || bird_props.bottom >= background.bottom) { game_state = 'End'; message.style.left = '28vw'; window.location.reload(); message.classList.remove('GameOverMessageStyle'); - setRestartButton() + setRestartButton(); return; } - // Aktualisiere die Vogelposition basierend auf der Gravitation bird.style.top = `${parseFloat(bird.style.top) + bird_dy}px`; bird_props = bird.getBoundingClientRect(); requestAnimationFrame(apply_gravity); } requestAnimationFrame(apply_gravity); - // Funktion zum Erstellen und Bewegen der Rohre let pipe_separation = 0; let pipe_gap = 35; - function create_pipe() { - // Überprüfe, ob das Spiel läuft if (game_state !== 'Play') return; - // Erzeuge neue Rohre, wenn der Abstand groß genug ist if (pipe_separation > iPipeseperation) { pipe_separation = 0; - // Zufällige Position für das obere Rohr berechnen let pipe_posi = Math.floor(Math.random() * 43) + 8; - //Erzeuge das obere Rohr let pipe_sprite_inv = document.createElement('div'); pipe_sprite_inv.className = 'pipe_sprite'; - pipe_sprite_inv.style.top = pipe_posi - 70 + 'vh';//Position des oberen Rohrs - pipe_sprite_inv.style.left = '100vw';// Beginne außerhalb des sichtabaren Bereichs + pipe_sprite_inv.style.top = pipe_posi - 70 + 'vh'; + pipe_sprite_inv.style.left = '100vw'; - //Füge das obere Rohr dem Dokumet hinzu document.body.appendChild(pipe_sprite_inv); - //Erzeuge das untere Rohr let pipe_sprite = document.createElement('div'); pipe_sprite.className = 'pipe_sprite'; - pipe_sprite.style.top = pipe_posi + pipe_gap + 'vh'; // Position des unteren Rohrs - pipe_sprite.style.left = '100vw'; // Beginne außerhalb des Sichtbaren Bereichs - pipe_sprite.increase_score = '1'; // Markiere das Rohr zur Punktzählung + pipe_sprite.style.top = pipe_posi + pipe_gap + 'vh'; + pipe_sprite.style.left = '100vw'; + pipe_sprite.increase_score = '1'; - // Füge das untere Rohr dem Dokument hinzu document.body.appendChild(pipe_sprite); } - // Inkrementiere den Abstandzähler pipe_separation++; - - //Wiederhole die Funktion, um kontinuierlich neue Rohre zu erstellen requestAnimationFrame(create_pipe); } - - } diff --git a/style.css b/style.css index b5c3108cf1a692bc1beefa48a6a833ee4c1e9fa9..b6b683adbbdb51cbcc0a4ea2a76c48795e17657c 100644 --- a/style.css +++ b/style.css @@ -13,17 +13,6 @@ position: absolute; z-index: 100000; } -/* Stil für das Eingabefeld */ -.inputField { - position: fixed; - top: 20vh; - left: 50%; - transform: translateX(-50%); - padding: 10px; - font-size: 16px; - border-radius: 5px; - border: 1px solid #ccc; -} .start-container { display: flex; @@ -90,14 +79,6 @@ } -/* Stil für den Difficulty Container */ -.difficultyContainer { - position: fixed; - top:10; - left: 0; - padding: 10px; - background-color: rgba(255, 255, 255, 0.5); -} /* Stil für den Vogel */ @@ -236,3 +217,30 @@ z-index: 1000; margin-top: 10px; } + +.infoBox { + display: none; + position: fixed; + z-index: 1000; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + width: 80%; + max-width: 500px; + background-color: white; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); + padding: 20px; + border-radius: 10px; +} + +.infoContent { + position: relative; +} + +.closeButton { + position: absolute; + top: 10px; + right: 10px; + font-size: 24px; + cursor: pointer; +}