game init
This commit is contained in:
parent
bcb4594afa
commit
6b0fedfabf
3 changed files with 351 additions and 0 deletions
|
@ -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 a new issue