mirror of
				https://github.com/Frooodle/Stirling-PDF.git
				synced 2025-11-01 01:21:18 +01:00 
			
		
		
		
	game init
This commit is contained in:
		
							parent
							
								
									bcb4594afa
								
							
						
					
					
						commit
						6b0fedfabf
					
				@ -14,6 +14,13 @@ public class GeneralWebController {
 | 
			
		||||
        model.addAttribute("currentPage", "merge-pdfs");
 | 
			
		||||
        return "merge-pdfs";
 | 
			
		||||
    }
 | 
			
		||||
    @GetMapping("/game")
 | 
			
		||||
    @Hidden
 | 
			
		||||
    public String gameForm(Model model) {
 | 
			
		||||
        model.addAttribute("currentPage", "game");
 | 
			
		||||
        return "game";
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @GetMapping("/multi-tool")
 | 
			
		||||
    @Hidden
 | 
			
		||||
    public String multiToolForm(Model model) {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										264
									
								
								src/main/resources/static/js/game.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								src/main/resources/static/js/game.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,264 @@
 | 
			
		||||
document.addEventListener('DOMContentLoaded', function() {
 | 
			
		||||
 | 
			
		||||
    const gameContainer = document.getElementById('game-container');
 | 
			
		||||
    const player = document.getElementById('player');
 | 
			
		||||
    const scoreElement = document.getElementById('score');
 | 
			
		||||
    const levelElement = document.getElementById('level');
 | 
			
		||||
    const livesElement = document.getElementById('lives');
 | 
			
		||||
    const highScoreElement = document.getElementById('high-score');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    let playerX = gameContainer.clientWidth / 2;
 | 
			
		||||
    let playerY = 50;
 | 
			
		||||
    let paused = false;
 | 
			
		||||
    const fireRate = 200; // Time between shots in milliseconds
 | 
			
		||||
    let lastProjectileTime = 0;
 | 
			
		||||
    let lives = 3;
 | 
			
		||||
    let highScore = localStorage.getItem('highScore') ? parseInt(localStorage.getItem('highScore')) : 0;
 | 
			
		||||
    updateHighScore();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    const keysPressed = {};
 | 
			
		||||
    const pdfs = [];
 | 
			
		||||
    const projectiles = [];
 | 
			
		||||
    let score = 0;
 | 
			
		||||
    let level = 1;
 | 
			
		||||
    let pdfSpeed = 1;
 | 
			
		||||
    let gameOver = false;
 | 
			
		||||
 | 
			
		||||
    function handleKeys() {
 | 
			
		||||
	    if (keysPressed['ArrowLeft']) {
 | 
			
		||||
	        playerX -= 10;
 | 
			
		||||
	    }
 | 
			
		||||
	    if (keysPressed['ArrowRight']) {
 | 
			
		||||
	        playerX += 10;
 | 
			
		||||
	    }
 | 
			
		||||
	    if (keysPressed[' '] && !gameOver) {
 | 
			
		||||
	        const currentTime = new Date().getTime();
 | 
			
		||||
	        if (currentTime - lastProjectileTime >= fireRate) {
 | 
			
		||||
	            shootProjectile();
 | 
			
		||||
	            lastProjectileTime = currentTime;
 | 
			
		||||
	        }
 | 
			
		||||
	    }
 | 
			
		||||
	    updatePlayerPosition();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    document.addEventListener('keydown', (event) => {
 | 
			
		||||
        keysPressed[event.key] = true;
 | 
			
		||||
        handleKeys();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    document.addEventListener('keyup', (event) => {
 | 
			
		||||
        keysPressed[event.key] = false;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    function updatePlayerPosition() {
 | 
			
		||||
        player.style.left = playerX + 'px';
 | 
			
		||||
        player.style.bottom = playerY + 'px';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function updateLives() {
 | 
			
		||||
        livesElement.textContent = 'Lives: ' + lives;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function updateHighScore() {
 | 
			
		||||
        highScoreElement.textContent = 'High Score: ' + highScore;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    function shootProjectile() {
 | 
			
		||||
        const projectile = document.createElement('div');
 | 
			
		||||
        projectile.classList.add('projectile');
 | 
			
		||||
        projectile.style.backgroundColor = 'black';
 | 
			
		||||
        projectile.style.width = '5px';
 | 
			
		||||
        projectile.style.height = '10px';
 | 
			
		||||
        projectile.style.left = playerX + 20 + 'px';
 | 
			
		||||
        projectile.style.top = (gameContainer.clientHeight - playerY - 20) + 'px';
 | 
			
		||||
        gameContainer.appendChild(projectile);
 | 
			
		||||
        projectiles.push(projectile);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    function spawnPdf() {
 | 
			
		||||
        const pdf = document.createElement('img');
 | 
			
		||||
        pdf.src = 'images/file-earmark-pdf.svg';
 | 
			
		||||
        pdf.classList.add('pdf');
 | 
			
		||||
        pdf.style.left = Math.floor(Math.random() * (gameContainer.clientWidth - 50)) + 'px';
 | 
			
		||||
        pdf.style.top = '0px';
 | 
			
		||||
        gameContainer.appendChild(pdf);
 | 
			
		||||
        pdfs.push(pdf);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
function resetEnemies() {
 | 
			
		||||
    pdfs.forEach((pdf) => gameContainer.removeChild(pdf));
 | 
			
		||||
    pdfs.length = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    function updateGame() {
 | 
			
		||||
        if (gameOver || paused) return;
 | 
			
		||||
 | 
			
		||||
        pdfs.forEach((pdf, pdfIndex) => {
 | 
			
		||||
            const pdfY = parseInt(pdf.style.top) + pdfSpeed;
 | 
			
		||||
            if (pdfY + 50 > gameContainer.clientHeight) {
 | 
			
		||||
                gameContainer.removeChild(pdf);
 | 
			
		||||
                pdfs.splice(pdfIndex, 1);
 | 
			
		||||
 | 
			
		||||
                // Deduct 2 points when a PDF gets past the player
 | 
			
		||||
                score -= 0;
 | 
			
		||||
                updateScore();
 | 
			
		||||
 | 
			
		||||
                // Decrease lives and check if game over
 | 
			
		||||
                lives--;
 | 
			
		||||
                updateLives();
 | 
			
		||||
                if (lives <= 0) {
 | 
			
		||||
                    endGame();
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            } else {
 | 
			
		||||
                pdf.style.top = pdfY + 'px';
 | 
			
		||||
 | 
			
		||||
                // Check for collision with player
 | 
			
		||||
                if (collisionDetected(player, pdf)) {
 | 
			
		||||
                    lives--;
 | 
			
		||||
                    updateLives();
 | 
			
		||||
                    resetEnemies();
 | 
			
		||||
                    if (lives <= 0) {
 | 
			
		||||
                        endGame();
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        function resetGame() {
 | 
			
		||||
            playerX = gameContainer.clientWidth / 2;
 | 
			
		||||
            playerY = 50;
 | 
			
		||||
            updatePlayerPosition();
 | 
			
		||||
 | 
			
		||||
            pdfs.forEach((pdf) => gameContainer.removeChild(pdf));
 | 
			
		||||
            projectiles.forEach((projectile) => gameContainer.removeChild(projectile));
 | 
			
		||||
 | 
			
		||||
            pdfs.length = 0;
 | 
			
		||||
            projectiles.length = 0;
 | 
			
		||||
 | 
			
		||||
            score = 0;
 | 
			
		||||
            level = 1;
 | 
			
		||||
            lives = 3;
 | 
			
		||||
            pdfSpeed = 2;
 | 
			
		||||
            gameOver = false;
 | 
			
		||||
 | 
			
		||||
            updateScore();
 | 
			
		||||
            updateLevel();
 | 
			
		||||
            updateLives();
 | 
			
		||||
 | 
			
		||||
            setTimeout(updateGame, 1000 / 60);
 | 
			
		||||
            spawnPdfInterval();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        projectiles.forEach((projectile, projectileIndex) => {
 | 
			
		||||
            const projectileY = parseInt(projectile.style.top) - 10;
 | 
			
		||||
            if (projectileY < 0) {
 | 
			
		||||
                gameContainer.removeChild(projectile);
 | 
			
		||||
                projectiles.splice(projectileIndex, 1);
 | 
			
		||||
            } else {
 | 
			
		||||
                projectile.style.top = projectileY + 'px';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for (let pdfIndex = 0; pdfIndex < pdfs.length; pdfIndex++) {
 | 
			
		||||
                const pdf = pdfs[pdfIndex];
 | 
			
		||||
                if (collisionDetected(projectile, pdf)) {
 | 
			
		||||
                    gameContainer.removeChild(pdf);
 | 
			
		||||
                    gameContainer.removeChild(projectile);
 | 
			
		||||
                    pdfs.splice(pdfIndex, 1);
 | 
			
		||||
                    projectiles.splice(projectileIndex, 1);
 | 
			
		||||
                    score = score + 10;
 | 
			
		||||
                    updateScore();
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        setTimeout(updateGame, 1000 / 60);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    function updateScore() {
 | 
			
		||||
	    scoreElement.textContent = 'Score: ' + score;
 | 
			
		||||
	    checkLevelUp();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    function checkLevelUp() {
 | 
			
		||||
        const newLevel = Math.floor(score / 100) + 1;
 | 
			
		||||
        if (newLevel > level) {
 | 
			
		||||
            level = newLevel;
 | 
			
		||||
            levelElement.textContent = 'Level: ' + level;
 | 
			
		||||
            pdfSpeed += 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function collisionDetected(a, b) {
 | 
			
		||||
        const rectA = a.getBoundingClientRect();
 | 
			
		||||
        const rectB = b.getBoundingClientRect();
 | 
			
		||||
        return (
 | 
			
		||||
            rectA.left < rectB.right &&
 | 
			
		||||
            rectA.right > rectB.left &&
 | 
			
		||||
            rectA.top < rectB.bottom &&
 | 
			
		||||
            rectA.bottom > rectB.top
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function endGame() {
 | 
			
		||||
        gameOver = true;
 | 
			
		||||
        if (score > highScore) {
 | 
			
		||||
            highScore = score;
 | 
			
		||||
            localStorage.setItem('highScore', highScore);
 | 
			
		||||
            updateHighScore();
 | 
			
		||||
        }
 | 
			
		||||
        alert('Game Over! Your final score is: ' + score);
 | 
			
		||||
        resetGame();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    let spawnPdfTimeout;
 | 
			
		||||
 | 
			
		||||
    function spawnPdfInterval() {
 | 
			
		||||
        if (gameOver || paused) {
 | 
			
		||||
            clearTimeout(spawnPdfTimeout);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        spawnPdf();
 | 
			
		||||
        spawnPdfTimeout = setTimeout(spawnPdfInterval, 1000 - level * 50);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    updatePlayerPosition();
 | 
			
		||||
    updateGame();
 | 
			
		||||
    spawnPdfInterval();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    document.addEventListener('visibilitychange', function() {
 | 
			
		||||
        if (document.hidden) {
 | 
			
		||||
            paused = true;
 | 
			
		||||
        } else {
 | 
			
		||||
            paused = false;
 | 
			
		||||
            updateGame();
 | 
			
		||||
            spawnPdfInterval();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										80
									
								
								src/main/resources/templates/game.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/main/resources/templates/game.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,80 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
 | 
			
		||||
 | 
			
		||||
<th:block th:insert="~{fragments/common :: head(title=#{pageRemover.title})}"></th:block>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
  <div id="page-container">
 | 
			
		||||
    <div id="content-wrap">
 | 
			
		||||
      <div th:insert="~{fragments/navbar.html :: navbar}"></div>
 | 
			
		||||
      <br> <br>
 | 
			
		||||
      <div class="container">
 | 
			
		||||
        <div class="row justify-content-center">
 | 
			
		||||
          <div class="col-md-6">
 | 
			
		||||
            <div class="game-container-wrapper" style="position: relative;">
 | 
			
		||||
              <div id="game-container">
 | 
			
		||||
                       <div id="score">Score: 0</div>
 | 
			
		||||
        <div id="lives">Lives: 3</div>
 | 
			
		||||
        <div id="level">Level: 1</div>
 | 
			
		||||
        <div id="high-score">High Score: 0</div>
 | 
			
		||||
                  <img src="favicon.svg" class="player" id="player">
 | 
			
		||||
              </div>
 | 
			
		||||
              <style>
 | 
			
		||||
    #game-container {
 | 
			
		||||
        position: relative;
 | 
			
		||||
        width: 800px;
 | 
			
		||||
        height: 600px;
 | 
			
		||||
        background-color: white;
 | 
			
		||||
        margin: auto;
 | 
			
		||||
        overflow: hidden;
 | 
			
		||||
    }
 | 
			
		||||
    .pdf, .player, .projectile {
 | 
			
		||||
        position: absolute;
 | 
			
		||||
    }
 | 
			
		||||
    .pdf {
 | 
			
		||||
        width: 50px;
 | 
			
		||||
        height: 50px;
 | 
			
		||||
    }
 | 
			
		||||
    .player {
 | 
			
		||||
        width: 50px;
 | 
			
		||||
        height: 50px;
 | 
			
		||||
    }
 | 
			
		||||
    .projectile {
 | 
			
		||||
        background-color: black  !important;
 | 
			
		||||
        width: 5px;
 | 
			
		||||
        height: 10px;
 | 
			
		||||
    }
 | 
			
		||||
    #score, #level, #lives,#high-score  {
 | 
			
		||||
        color: black;
 | 
			
		||||
        font-family: sans-serif;
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        font-size: 24px;
 | 
			
		||||
    }
 | 
			
		||||
    #score {
 | 
			
		||||
        top: 10px;
 | 
			
		||||
        left: 10px;
 | 
			
		||||
    }
 | 
			
		||||
    #level {
 | 
			
		||||
        top: 10px;
 | 
			
		||||
        right: 10px;
 | 
			
		||||
    }
 | 
			
		||||
    #lives {
 | 
			
		||||
	    top: 10px;
 | 
			
		||||
	    left: 190px;
 | 
			
		||||
	}
 | 
			
		||||
	#high-score {
 | 
			
		||||
	    top: 10px;
 | 
			
		||||
	    left: 290px;
 | 
			
		||||
	}
 | 
			
		||||
              </style>
 | 
			
		||||
              <script src="js/game.js"></script>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div th:insert="~{fragments/footer.html :: footer}"></div>
 | 
			
		||||
  </div>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user