Simple Invaders
Code breakdown
HTML Structure:
The code sets up the basic HTML structure for the Space Invaders game.
It includes the <head> section for the title and the <body> section where the game elements will be placed.
CSS Styling:
This section defines the CSS styles for the game elements.
The #game element represents the game container, with a fixed width and height, centered margin, and a border.
The .invader class represents each individual invader, with a fixed width, height, and red background color.
The #player element represents the player's ship, with a fixed width, height, blue background color, and positioned at the bottom of the game container.
The #bullet element represents the bullet fired by the player, with a fixed width, height, black background color, and initially positioned at the player's ship.
JavaScript Code:
The code uses the DOMContentLoaded event to ensure that the JavaScript code runs only after the HTML elements have been loaded and parsed.
Game Initialization:
This section initializes variables and retrieves references to key game elements.
The player, bullet, and game variables store references to the player's ship, bullet, and game container elements, respectively.
The invaders variable stores references to all the invader elements in the game using the getElementsByClassName method.
The playerSpeed, bulletSpeed, and invaderSpeed variables control the movement speed of the player, bullet, and invaders, respectively.
The bulletInterval and invaderInterval variables will store the IDs of the interval functions responsible for moving the bullet and the invaders.
Player Movement:
This section listens for the keydown event on the document, which is triggered when a key is pressed.
The event listener function handles player movement and bullet shooting based on the key pressed.
Player Movement Implementation:
Inside the event listener function, the code gets the pressed key and the current position of the player's ship.
If the left arrow key is pressed and the player is not at the leftmost edge of the game container, the player's ship is moved to the left by subtracting the playerSpeed value from its left position.
If the right arrow key is pressed and the player is not at the rightmost edge, the player's ship is moved to the right by adding the playerSpeed value to its left position.
If the spacebar key is pressed, the code checks if there is no active bullet (based on the bulletInterval). If there is no bullet, the code positions the bullet just above the center of the player's ship and starts moving the bullet upwards by invoking the moveBullet function at regular intervals.
Bullet Shooting:
When the spacebar is pressed and there is no active bullet, the code positions the bullet just above the center of the player's ship and starts moving the bullet upwards by invoking the moveBullet function at regular intervals using the setInterval function.
The bulletInterval variable stores the ID of the interval, preventing multiple bullets from being fired simultaneously.
Moving the Bullet:
The moveBullet function is responsible for moving the bullet upwards and checking for collision or reaching the top edge of the game container.
Inside the moveBullet function, the code gets the current position of the bullet and moves it upwards by subtracting the bulletSpeed value from its top position.
If the bullet reaches the top edge of the game container, the code clears the interval to stop moving the bullet and resets the bulletInterval variable to allow shooting a new bullet.
Otherwise, the code checks for collisions with the invaders by invoking the checkCollision function.
Collision Detection:
The checkCollision function is responsible for detecting collisions between the bullet and the invaders.
Inside the function, the code iterates over all the invader elements using a loop.
For each invader, it obtains the positions and dimensions of the bullet and the invader using the getBoundingClientRect method.
It then checks if there is a collision between the bullet and the current invader using the isColliding helper function.
If a collision is detected, the code can perform actions such as removing the invader and stopping the bullet.
Collision Detection Implementation:
Inside the checkCollision function, the code uses a loop to iterate over all the invader elements.
For each invader, it obtains the positions and dimensions of the bullet and the invader using the getBoundingClientRect method.
It then checks if there is a collision between the bullet and the current invader by invoking the isColliding helper function and passing the bullet and invader rectangles.
If a collision is detected, the code can perform actions such as removing the invader and stopping the bullet.
Helper Function - isColliding:
This helper function takes two rectangles as input and checks if they are colliding.
It compares the positions and dimensions of the two rectangles to determine if they overlap.
The function returns a boolean value indicating whether a collision has occurred.
Invader Movement:
This section sets up an interval function to move the invaders at regular intervals.
The invaderInterval variable stores the ID of the interval function, allowing us to clear it later to stop the movement.
Inside the interval function, the code iterates over all the invader elements.
For each invader, it gets the current position and movement speed.
It then updates the invader's left position based on the speed and changes the top position if the invader reaches the edge of the game container.
Additionally, it checks if an invader reaches the bottom edge of the game container, resulting in a game over.
Game Over:
The gameOver function is responsible for stopping the game when it ends.
It clears the interval functions for moving the invaders and the bullet.
It displays an alert message to notify the player that the game is over.
Program Details (HTML)
<!DOCTYPE html>
<html>
<head>
<title>Space Invaders</title>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<div id="game">
<div id="player"></div>
<div id="bullet"></div>
<div class="invader" style="top: 40px; left: 40px;"></div>
<div class="invader" style="top: 40px; left: 80px;"></div>
<div class="invader" style="top: 40px; left: 120px;"></div>
<!-- Add more invader elements as desired -->
</div>
<script src="script.js"></script>
</body>
</html>
Program Details (CSS)
<style>
#game {
width: 480px;
height: 320px;
margin: 0 auto;
position: relative;
border: 2px solid #000;
}
.invader {
width: 20px;
height: 20px;
background: #f00;
position: absolute;
}
#player {
width: 40px;
height: 20px;
background: #00f;
position: absolute;
bottom: 0;
}
#bullet {
width: 2px;
height: 10px;
background: #000;
position: absolute;
}
</style>
Program Details (JAVASCIPT)
<script>
document.addEventListener('DOMContentLoaded', () => {
const player = document.getElementById('player');
const bullet = document.getElementById('bullet');
const invaders = document.getElementsByClassName('invader');
const game = document.getElementById('game');
const playerSpeed = 5;
const bulletSpeed = 10;
let invaderSpeed = 2;
let bulletInterval = null;
let invaderInterval = null;
document.addEventListener('keydown', (event) => {
const key = event.key;
const playerLeft = parseInt(getComputedStyle(player).left);
if (key === 'ArrowLeft' && playerLeft > 0) {
player.style.left = `${playerLeft - playerSpeed}px`;
} else if (key === 'ArrowRight' && playerLeft < game.clientWidth - player.clientWidth) {
player.style.left = `${playerLeft + playerSpeed}px`;
} else if (key === ' ') {
if (!bulletInterval) {
bullet.style.left = `${playerLeft + player.clientWidth / 2 - bullet.clientWidth / 2}px`;
bullet.style.top = `${game.clientHeight - player.clientHeight - bullet.clientHeight}px`;
bulletInterval = setInterval(moveBullet, 20);
}
}
});
function moveBullet() {
const bulletTop = parseInt(getComputedStyle(bullet).top);
bullet.style.top = `${bulletTop - bulletSpeed}px`;
if (bulletTop <= 0) {
clearInterval(bulletInterval);
bulletInterval = null;
} else {
checkCollision();
}
}
function checkCollision() {
const bulletRect = bullet.getBoundingClientRect();
for (let i = 0; i < invaders.length; i++) {
const invader = invaders[i];
const invaderRect = invader.getBoundingClientRect();
if (isColliding(bulletRect, invaderRect)) {
invader.remove();
clearInterval(bulletInterval);
bulletInterval = null;
break;
}
}
}
function isColliding(rect1, rect2) {
return rect1.left < rect2.right &&
rect1.right > rect2.left &&
rect1.top < rect2.bottom &&
rect1.bottom > rect2.top;
}
function moveInvaders() {
invaderInterval = setInterval(() => {
for (let i = 0; i < invaders.length; i++) {
const invader = invaders[i];
const invaderLeft = parseInt(getComputedStyle(invader).left);
const invaderTop = parseInt(getComputedStyle(invader).top);
invader.style.left = `${invaderLeft + invaderSpeed}px`;
if (invaderLeft >= game.clientWidth - invader.clientWidth || invaderLeft <= 0) {
invader.style.top = `${invaderTop + 20}px`;
invaderSpeed *= -1;
}
if (invaderTop >= game.clientHeight - invader.clientHeight) {
gameOver();
}
}
}, 200);
}
function gameOver() {
clearInterval(invaderInterval);
clearInterval(bulletInterval);
alert('Game Over');
}
moveInvaders();
});
</script>