2023-04-30 18:29:35 +02:00
|
|
|
function initializeGame() {
|
2023-04-29 23:26:16 +02:00
|
|
|
const gameContainer = document.getElementById('game-container');
|
|
|
|
const player = document.getElementById('player');
|
2023-04-30 18:29:35 +02:00
|
|
|
|
|
|
|
let playerSize = gameContainer.clientWidth * 0.0625; // 5% of container width
|
|
|
|
player.style.width = playerSize + 'px';
|
|
|
|
player.style.height = playerSize + 'px';
|
|
|
|
|
|
|
|
let playerX = gameContainer.clientWidth / 2 - playerSize / 2;
|
|
|
|
let playerY = gameContainer.clientHeight * 0.1;
|
2023-04-29 23:26:16 +02:00
|
|
|
const scoreElement = document.getElementById('score');
|
|
|
|
const levelElement = document.getElementById('level');
|
|
|
|
const livesElement = document.getElementById('lives');
|
|
|
|
const highScoreElement = document.getElementById('high-score');
|
|
|
|
|
2023-04-30 18:29:35 +02:00
|
|
|
let pdfSize = gameContainer.clientWidth * 0.0625; // 5% of container width
|
2024-02-06 01:00:49 +01:00
|
|
|
let projectileWidth = gameContainer.clientWidth * 0.00625;// 0.00625; // 0.5% of container width
|
2023-04-30 18:29:35 +02:00
|
|
|
let projectileHeight = gameContainer.clientHeight * 0.01667; // 1% of container height
|
2023-04-29 23:26:16 +02:00
|
|
|
|
|
|
|
let paused = false;
|
2024-02-06 01:00:49 +01:00
|
|
|
|
2023-04-29 23:26:16 +02:00
|
|
|
const fireRate = 200; // Time between shots in milliseconds
|
|
|
|
let lastProjectileTime = 0;
|
|
|
|
let lives = 3;
|
2024-02-06 01:00:49 +01:00
|
|
|
|
|
|
|
|
2023-04-29 23:26:16 +02:00
|
|
|
let highScore = localStorage.getItem('highScore') ? parseInt(localStorage.getItem('highScore')) : 0;
|
|
|
|
updateHighScore();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const keysPressed = {};
|
|
|
|
const pdfs = [];
|
|
|
|
const projectiles = [];
|
|
|
|
let score = 0;
|
|
|
|
let level = 1;
|
2024-02-06 01:00:49 +01:00
|
|
|
let pdfSpeed = 0.5;
|
2023-04-29 23:26:16 +02:00
|
|
|
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) => {
|
2023-04-30 18:29:35 +02:00
|
|
|
if (event.key === ' ') {
|
|
|
|
event.preventDefault();
|
|
|
|
}
|
2023-04-29 23:26:16 +02:00
|
|
|
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';
|
2023-04-30 18:29:35 +02:00
|
|
|
projectile.style.width = projectileWidth + 'px';
|
|
|
|
projectile.style.height = projectileHeight + 'px';
|
|
|
|
projectile.style.left = (playerX + playerSize / 2 - projectileWidth / 2) + 'px';
|
|
|
|
projectile.style.top = (gameContainer.clientHeight - playerY - playerSize) + 'px';
|
2023-04-29 23:26:16 +02:00
|
|
|
gameContainer.appendChild(projectile);
|
|
|
|
projectiles.push(projectile);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-04-30 18:29:35 +02:00
|
|
|
|
2023-04-29 23:26:16 +02:00
|
|
|
function spawnPdf() {
|
|
|
|
const pdf = document.createElement('img');
|
|
|
|
pdf.src = 'images/file-earmark-pdf.svg';
|
|
|
|
pdf.classList.add('pdf');
|
2023-04-30 18:29:35 +02:00
|
|
|
pdf.style.width = pdfSize + 'px';
|
|
|
|
pdf.style.height = pdfSize + 'px';
|
|
|
|
pdf.style.left = Math.floor(Math.random() * (gameContainer.clientWidth - pdfSize)) + 'px';
|
2023-04-29 23:26:16 +02:00
|
|
|
pdf.style.top = '0px';
|
|
|
|
gameContainer.appendChild(pdf);
|
|
|
|
pdfs.push(pdf);
|
|
|
|
}
|
|
|
|
|
2023-04-30 18:29:35 +02:00
|
|
|
|
2023-05-03 23:07:51 +02:00
|
|
|
function resetEnemies() {
|
|
|
|
pdfs.forEach((pdf) => gameContainer.removeChild(pdf));
|
|
|
|
pdfs.length = 0;
|
|
|
|
}
|
2023-04-29 23:26:16 +02:00
|
|
|
|
|
|
|
|
|
|
|
function updateGame() {
|
|
|
|
if (gameOver || paused) return;
|
|
|
|
|
2023-05-03 23:07:51 +02:00
|
|
|
for (let pdfIndex = 0; pdfIndex < pdfs.length; pdfIndex++) {
|
|
|
|
const pdf = pdfs[pdfIndex];
|
2024-02-06 01:00:49 +01:00
|
|
|
const pdfY = parseFloat(pdf.style.top) + pdfSpeed;
|
2023-04-29 23:26:16 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-05-03 23:07:51 +02:00
|
|
|
};
|
2023-04-29 23:26:16 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2023-04-30 18:29:35 +02:00
|
|
|
|
2023-05-03 23:07:51 +02:00
|
|
|
function resetGame() {
|
|
|
|
playerX = gameContainer.clientWidth / 2;
|
|
|
|
playerY = 50;
|
|
|
|
updatePlayerPosition();
|
2023-04-29 23:26:16 +02:00
|
|
|
|
2023-05-03 23:07:51 +02:00
|
|
|
pdfs.forEach((pdf) => gameContainer.removeChild(pdf));
|
|
|
|
projectiles.forEach((projectile) => gameContainer.removeChild(projectile));
|
2023-04-30 18:29:35 +02:00
|
|
|
|
2023-05-03 23:07:51 +02:00
|
|
|
pdfs.length = 0;
|
|
|
|
projectiles.length = 0;
|
|
|
|
|
|
|
|
score = 0;
|
|
|
|
level = 1;
|
|
|
|
lives = 3;
|
|
|
|
|
|
|
|
gameOver = false;
|
|
|
|
|
|
|
|
updateScore();
|
|
|
|
updateLives();
|
|
|
|
levelElement.textContent = 'Level: ' + level;
|
|
|
|
pdfSpeed = 1;
|
|
|
|
clearTimeout(spawnPdfTimeout); // Clear the existing spawnPdfTimeout
|
|
|
|
setTimeout(updateGame, 1000 / 60);
|
|
|
|
spawnPdfInterval();
|
|
|
|
}
|
2023-04-29 23:26:16 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
2024-02-06 01:00:49 +01:00
|
|
|
pdfSpeed += 0.2;
|
2023-04-29 23:26:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2023-05-03 23:07:51 +02:00
|
|
|
document.getElementById('game-container-wrapper').close();
|
2023-04-29 23:26:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let spawnPdfTimeout;
|
|
|
|
|
2024-02-06 01:00:49 +01:00
|
|
|
const BASE_SPAWN_INTERVAL_MS = 1250; // milliseconds before a new enemy spawns
|
|
|
|
const LEVEL_INCREASE_FACTOR_MS = 0; // milliseconds to decrease the spawn interval per level
|
|
|
|
const MAX_SPAWN_RATE_REDUCTION_MS = 800; // Max milliseconds from the base spawn interval
|
|
|
|
|
2023-04-29 23:26:16 +02:00
|
|
|
function spawnPdfInterval() {
|
2023-04-30 18:29:35 +02:00
|
|
|
console.log("spawnPdfInterval");
|
2023-04-29 23:26:16 +02:00
|
|
|
if (gameOver || paused) {
|
2023-04-30 18:29:35 +02:00
|
|
|
console.log("spawnPdfInterval 2");
|
2023-04-29 23:26:16 +02:00
|
|
|
clearTimeout(spawnPdfTimeout);
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 18:29:35 +02:00
|
|
|
console.log("spawnPdfInterval 3");
|
2023-04-29 23:26:16 +02:00
|
|
|
spawnPdf();
|
2024-02-06 01:00:49 +01:00
|
|
|
let spawnRateReduction = Math.min(level * LEVEL_INCREASE_FACTOR_MS, MAX_SPAWN_RATE_REDUCTION_MS);
|
|
|
|
let spawnRate = BASE_SPAWN_INTERVAL_MS - spawnRateReduction;
|
|
|
|
spawnPdfTimeout = setTimeout(spawnPdfInterval, spawnRate);
|
2023-04-29 23:26:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
updatePlayerPosition();
|
|
|
|
updateGame();
|
|
|
|
spawnPdfInterval();
|
|
|
|
|
|
|
|
|
|
|
|
document.addEventListener('visibilitychange', function() {
|
|
|
|
if (document.hidden) {
|
|
|
|
paused = true;
|
|
|
|
} else {
|
|
|
|
paused = false;
|
|
|
|
updateGame();
|
|
|
|
spawnPdfInterval();
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
2023-05-03 23:07:51 +02:00
|
|
|
window.resetGame = resetGame;
|
2023-04-30 18:29:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
window.initializeGame = initializeGame;
|