Step 1: Supercharge Your JS
Guess what? Your JavaScript (JS) file wants some love too. Remember where you saved it? Open it up! And just like before, select everything, press Delete, and clear the stage for something awesome.
Step 2: The Magical Finale
Copy the new and exciting JS code we have for you. You know the drill: paste it into your JS file, and hit Ctrl and S to save everything.
And That’s It!
You’re now ready to see your game in action. Fire it up, and watch your characters dash across the screen. You’re a coding wizard in the making! If you ever need help, remember to reach out. Happy coding! ?
document.addEventListener('DOMContentLoaded', function () {
// Get the start button element
var startButton = document.querySelector('.start-button');
// Get the logo element
var logoElement = document.querySelector('.game-logo');
// Get the platform container element
const platformContainer = document.getElementById('platform-container');
const player = document.getElementById('player');
const enemy = document.querySelector('.enemy');
const playableScreenWidth = platformContainer.offsetWidth;
const playerWidth = player.offsetWidth;
const playerHeight = player.offsetHeight; // Get the player's height
const enemyWidth = enemy.offsetWidth;
const enemyHeight = enemy.offsetHeight;
let playerLeft = 0;
let playerBottom = 10;
let screenLeft = 0;
let groundWidth = playableScreenWidth; // Initial width of the ground
// Declare a flag to track if a projectile is currently active
let projectileActive = false;
// Initial speed values
const initialPlayerSpeed = 5; // Initial speed of the player
const initialEnemySpeed = 5; // Initial speed of the enemy
let playerSpeed = initialPlayerSpeed; // The speed of the player
let enemySpeed = initialEnemySpeed; // The speed of the player
const jumpHeight = 150; // Maximum jump height
const gravity = 10; // Gravity value
let isJumping = false;
let isMovingLeft = false;
let isMovingRight = false;
let enemyLeft = playableScreenWidth; // Initial position of the enemy
let enemyMoveRequestId; // Declare the variable to hold the request ID for the enemy movement animation frame
let projectileDirection = 1; // 1 for right, -1 for left
// Add a variable to track the player's direction
let playerDirection = 'right';
const maxPlayerRight = playableScreenWidth * 0.7; // Maximum distance player can move to the right (70% of playable area)
const backgroundScrollSpeed = 1; // Adjusted background scroll speed
let isGameActive = false; // Flag to indicate if the game is active or not
let playerMoveInterval; // Declare the player movement interval variable
let screenMoveInterval; // Declare the screen movement interval variable
let enemyMoveInterval;
// Define the stopCheckingCollision flag
let stopCheckingCollision = false;
// Declare a variable to track the score at the beginning of your JavaScript code
const initialscore = 0;
let score = initialscore;
// Add a variable to track player's health
let initialPlayerHealth = 100;
let playerHealth = initialPlayerHealth;
let healthBar = document.querySelector('.health');
// Variables for energy
let initialPlayerEnergy = 100;
let playerEnergy = initialPlayerEnergy;
let energyBar = document.querySelector('.energy');
let scoreElement = document.querySelector('.score');
// Get the audio element
const bgMusic = document.getElementById('bg-music');
// Function to move the screen and the player
function moveScreen() {
// Move the screen by the player's speed
if (isMovingLeft && playerLeft > 0) {
screenLeft -= playerSpeed;
} else if (isMovingRight) {
screenLeft += playerSpeed;
}
// Move the screen (background)
document.body.style.backgroundPositionX = '${-screenLeft * backgroundScrollSpeed}px';
// Adjust the width of the ground based on the player's position
groundWidth = Math.max(groundWidth, playerLeft + playerWidth);
platformContainer.style.width = '${groundWidth}px';
}
// Function to apply gravity to the player
function applyGravity() {
// Check if playerBottom position is more than the bottom platform height, if so apply gravity. When this was set to 0 it was pulling the player down past the platform height to the absolute bottom of the board/screen.
if (playerBottom > 10 ) {
playerBottom -= gravity;
movePlayer();
} else {
player.style.bottom = playerBottom + 'px';
isJumping = false;
}
}
// Function to handle key down events
function handleKeyDown(event) {
if (!isGameActive) return; // Prevent player movement during game reset
if (event.key === 'ArrowLeft') {
// Move player to the left within the playable area
if (playerLeft > 0) {
playerLeft -= playerSpeed;
movePlayer();
}
isMovingLeft = true;
playerDirection = 'left'; // Update player direction
//projectileDirection = -1; // Set the projectile direction to left
} else if (event.key === 'ArrowRight') {
// Move player to the right within the playable area
playerLeft += playerSpeed;
isMovingRight = true;
playerDirection = 'right'; // Update player direction
//projectileDirection = 1; // Set the projectile direction to right
moveScreen(); // Move the screen immediately when the right arrow is pressed
} else if (event.key === 'ArrowUp') {
// Jump
jump();
}
else if (event.key === ' ') {
shootProjectile();
// console.log('shooting');
}
}
// Function to handle key up events
function handleKeyUp(event) {
if (event.key === 'ArrowLeft') {
isMovingLeft = false;
} else if (event.key === 'ArrowRight') {
isMovingRight = false;
}
}
// Function to move the player
function movePlayer() {
// Get the maximum visible position of the player on the screen
const maxVisiblePlayerRight = playableScreenWidth - playerWidth;
// Restrict player movement within the visible screen area
if (playerLeft > maxVisiblePlayerRight) {
playerLeft = maxVisiblePlayerRight;
} else if (playerLeft > maxPlayerRight) {
playerLeft = maxPlayerRight;
}
// Update the player's position
player.style.left = playerLeft + 'px';
player.style.bottom = playerBottom + 'px';
// Horizontal flip when moving to the left
player.style.transform = isMovingLeft ? 'scaleX(-1)' : 'scaleX(1)';
}
// Function to handle player jumping
function jump() {
if (!isJumping) {
isJumping = true;
let jumpInterval = setInterval(() => {
if (playerBottom < jumpHeight) {
playerBottom += gravity;
movePlayer();
} else {
clearInterval(jumpInterval);
let fallInterval = setInterval(() => {
applyGravity();
if (!isJumping) {
clearInterval(fallInterval);
}
}, 30);
}
}, 30);
}
}
// Function to shoot a projectile
function shootProjectile() {
if (playerEnergy >= 5) {
playerEnergy -= 5; // Subtract energy when shooting
updateEnergyBar(); // Update the energy bar display
// Play the shoot sound effect
const shootSound = document.getElementById('shootSound');
shootSound.currentTime = 0; // Rewind the sound to the beginning
shootSound.play();
projectileActive = true;
// Calculate the initial top position of the projectile
let projectileTop = player.offsetTop + playerHeight / 2;
// Calculate the initial left position of the projectile
let projectileLeft = playerLeft + playerWidth / 2;
// Store the initial shooting direction
projectileDirection = playerDirection === 'right' ? 1 : -1;
// Create a new projectile element
const projectile = document.createElement('div');
projectile.classList.add('projectile');
projectile.style.top = projectileTop + 'px'; // Set the initial top position
projectile.style.left = projectileLeft + 'px'; // Set the initial left position
platformContainer.appendChild(projectile); // Append to the platform container
// Move the projectile using requestAnimationFrame
let projectileMoveInterval = null; // Declare projectile move interval variable
function moveProjectile() {
projectileLeft += 10 * projectileDirection; // Adjust projectile speed as needed
projectile.style.left = projectileLeft + 'px';
// Inside the moveProjectile function after updating the projectile position
checkProjectileEnemyCollision(projectile);
// Check if the projectile is out of bounds
if (projectileLeft < 0 || projectileLeft > playableScreenWidth) {
// Remove the projectile when out of bounds
clearInterval(projectileMoveInterval); // Clear the interval
projectile.remove();
}
}
// Start moving the projectile and store the interval ID
projectileMoveInterval = setInterval(moveProjectile, 30);
}
}
function resetPlayer() {
// Reset player position and speed
playerLeft = 0;
player.style.bottom = playerBottom + 'px';
player.style.left = playerLeft + 'px';
isMovingLeft = false;
isMovingRight = false;
playerSpeed = initialPlayerSpeed; // Set the player speed back to its initial value
playerHealth = initialPlayerHealth; // Set the player health back to its initial value
playerEnergy = initialPlayerEnergy; // Set the energy health back to its initial value
}
// Declare a flag to track enemy jump state
let isEnemyJumping = false;
// Function to move the enemy
function moveEnemy() {
if (isGameActive) {
// Move the enemy horizontally
enemyLeft -= initialEnemySpeed;
enemy.style.left = enemyLeft + 'px';
// Check if the enemy has moved off the screen and reset its position
if (enemyLeft + enemyWidth < 0) {
resetEnemy();
}
}
// Check enemy proximity to the player
const distanceToPlayer = Math.abs(playerLeft - enemyLeft);
const isNearPlayer = distanceToPlayer < 150; // Adjust the proximity threshold as needed
if (!isEnemyJumping) {
// Randomly decide if the enemy should jump, considering proximity to the player
const shouldJump = Math.random() < 0.02 || (isNearPlayer && Math.random() < 0.5);
if (shouldJump) {
// Set the jump flag to true
isEnemyJumping = true;
// Calculate the jump duration based on the distance
const jumpDuration = Math.min(400, distanceToPlayer * 2); // Limit jump duration to 400 milliseconds
// Calculate the jump height
const jumpHeight = 100; // Adjust the jump height as needed
// Apply jump animation
enemy.style.transition = 'bottom ${jumpDuration}ms ease-in-out';
enemy.style.bottom = '${jumpHeight}px';
// After the jump, initiate the falling animation
setTimeout(() => {
// Apply falling animation
enemy.style.transition = 'bottom ${jumpDuration}ms ease-in-out';
enemy.style.bottom = '10px'; // Reset the enemy's bottom position
// After the fall animation, reset the transition property and jump flag
setTimeout(() => {
enemy.style.transition = 'none';
isEnemyJumping = false;
// Check if the enemy has moved off the screen and reset its position
if (enemyLeft + enemyWidth < 0) {
resetEnemy();
}
}, jumpDuration);
}, jumpDuration);
}
}
// Request the next animation frame
enemyMoveRequestId = requestAnimationFrame(moveEnemy);
}
function playEnemyDefeatedSound() {
const enemyDefeatedSound = document.getElementById('enemy-defeated-sound');
enemyDefeatedSound.currentTime = 0; // Reset the audio to the beginning
enemyDefeatedSound.play();
}
// Function to defeat the enemy
function defeatEnemy() {
// Apply squishing effect
enemy.style.transition = 'all 0.1s ease-in-out'; // Disable transition to make the squishing instant
enemy.style.height = '0px'; // Reduce the enemy's height to make it appear squished
// enemy.style.bottom = '10px'; // Move the enemy to the bottom of the container
// Play the enemy defeated sound effect
playEnemyDefeatedSound();
// Stop checking collision temporarily
stopCheckingCollision = true;
// Make the enemy visible again after a short delay
setTimeout(() => {
enemy.style.transition = 'none';
// Reset the enemy's height to its original value
enemy.style.height = ''; // Set height to an empty string to unset the height property
// Reappear at the right side of the screen
resetEnemy();
stopCheckingCollision = false;
}, 100); // Adjust the delay as needed
// Start moving the enemy again
moveEnemy();
}
// RESETTING THE ENEMY POSITION ****
/* You're absolutely right! Moving the cancelAnimationFrame(enemyMoveRequestId); from the startGame function to the resetEnemy function indeed fixes the increasing enemy speed after an enemy defeat.
By canceling the previous animation frame request before resetting the enemy's position and speed, we prevent the animation frame loop from stacking up, which was causing the enemy's speed to increase.*/
function resetEnemy() {
// Reset enemy position to its original starting point
enemyLeft = playableScreenWidth;
enemy.style.left = enemyLeft + 'px';
enemySpeed = initialEnemySpeed;
// Reset the enemy's movement animation frame request ID
cancelAnimationFrame(enemyMoveRequestId);
}
// Function to update health bar
function updateHealthBar() {
if (playerHealth === 0){
// console.log(playerHealth)
healthBar.style.width = 0 + 'px';
}
else {
// console.log(playerHealth)
healthBar.style.width = '${playerHealth}%';
}
}
// Function to update energy bar
function updateEnergyBar() {
if (energyBar) {
if (playerEnergy === 0) {
energyBar.style.width = 0 + 'px';
} else {
energyBar.style.width = '${playerEnergy}%';
}
}
}
// Function to update the score display
function updateScoreDisplay() {
if (score === 0) {
scoreElement.textContent = 0; // Reset the score display to 0
}
else {
scoreElement.textContent = score * 10; // Multiply the score by 10 for display
}
}
function stopBackgroundMusic() {
bgMusic.pause();
bgMusic.currentTime = 0; // Reset the audio to the beginning
}
// Function to reset the game state
function resetGame() {
// Stop the game
isGameActive = false;
// Clear all existing intervals to avoid stacking up
clearInterval(playerMoveInterval);
clearInterval(screenMoveInterval);
clearInterval(enemyMoveInterval);
// Remove event listeners for key events
document.removeEventListener('keydown', handleKeyDown);
document.removeEventListener('keyup', handleKeyUp);
// Reset player position and stats
resetPlayer();
playerHealth = initialPlayerHealth;
updateHealthBar();
playerEnergy = initialPlayerEnergy;
updateEnergyBar();
// Reset the score variable
score = initialscore;
updateScoreDisplay();
// Reset enemy position and speed
resetEnemy();
}
// Function to end the game
function endGame() {
// Show the logo element
logoElement.style.display = 'block';
// Stop the background music
stopBackgroundMusic();
// Reset the game
resetGame();
// Add the 'ready-to-play' class back to the body element
document.body.classList.remove('ready-to-play');
// Reset the opacity of the body ::before pseudo-element
document.body.style.setProperty('--before-opacity', '1');
// Fade in the body ::before pseudo-element
var bodyBeforeOpacity = 0;
var fadeInInterval = setInterval(function () {
if (bodyBeforeOpacity >= 1) {
clearInterval(fadeInInterval);
} else {
bodyBeforeOpacity += 0.1;
document.body.style.setProperty('--before-opacity', bodyBeforeOpacity);
}
}, 100);
}
// Function to check collision between player and enemy
function checkCollision() {
if (isGameActive && !stopCheckingCollision) {
// Calculate player and enemy positions
const playerRight = playerLeft + playerWidth;
const playerTop = playerBottom + player.offsetHeight;
const enemyRight = enemyLeft + enemyWidth;
const enemyTop = parseInt(getComputedStyle(enemy).bottom, 10) + enemy.offsetHeight;
// Check for collision
if (
playerRight > enemyLeft &&
playerLeft < enemyRight &&
playerTop > enemyTop &&
playerBottom < enemyTop
) {
// Collision detected, check if player collides from the top or side
if (playerBottom < enemyTop - playerSpeed) {
// Collision from the side
// Subtract health points
playerHealth -= 15;
if (playerHealth <= 0) {
// Player's health is less than or equal to 0, end the game
playerHealth = 0;
updateHealthBar();
endGame();
} else {
// Update health bar
updateHealthBar();
defeatEnemy();
// Wait for a short delay before resuming collision detection
setTimeout(() => {
stopCheckingCollision = false;
}, 500); // Adjust the delay as needed
}
} else {
// Collision from the top
// Increment the score only if the enemy is defeated by top collision.
playerEnergy += 5; // Subtract energy when shooting
updateEnergyBar(); // Update the energy bar display
score += 1;
updateScoreDisplay();
defeatEnemy();
}
}
}
requestAnimationFrame(checkCollision);
}
function checkProjectileEnemyCollision(projectile) {
const projectileRight = parseInt(projectile.style.left, 10) + projectile.offsetWidth;
const projectileLeft = parseInt(projectile.style.left, 10);
const enemyRight = enemyLeft + enemyWidth;
if (
projectileRight > enemyLeft &&
projectileLeft < enemyRight &&
projectile.offsetTop > enemy.offsetTop &&
projectile.offsetTop < enemy.offsetTop + enemy.offsetHeight
) {
// Collision detected between projectile and enemy
score += 1;
updateScoreDisplay();
defeatEnemy();
projectile.remove(); // Remove the projectile
// console.log('collision detected');
}
}
// Function to start the game
function startGame() {
// Clear previous intervals, if any
clearInterval(playerMoveInterval);
clearInterval(screenMoveInterval);
clearInterval(enemyMoveInterval);
// Reset player position and stats
resetPlayer();
// Reset enemy position to its original starting point
resetEnemy();
// Set the game as active
isGameActive = true;
// Start playing the background music
bgMusic.play();
// Hide the logo element
logoElement.style.display = 'none';
// Add event listeners for key events
document.addEventListener('keydown', handleKeyDown);
document.addEventListener('keyup', handleKeyUp);
// Update player position
playerMoveInterval = setInterval(() => {
if (isMovingLeft && playerLeft > 0) {
playerLeft -= playerSpeed;
movePlayer();
} else if (isMovingRight && playerLeft < maxPlayerRight) {
playerLeft += playerSpeed;
movePlayer();
}
}, 30);
// Update screen position
screenMoveInterval = setInterval(() => {
if (isGameActive) {
moveScreen();
}
}, 30);
// Reset the stopCheckingCollision flag
stopCheckingCollision = false;
// Start the collision detection loop
requestAnimationFrame(checkCollision);
// Start moving the enemy
moveEnemy();
}
// Add a click event listener to the start button
startButton.addEventListener('click', function () {
// Add the 'ready-to-play' class to the body element
document.body.classList.add('ready-to-play');
// Hide the logo element
logoElement.style.display = 'none';
// Fade out the body ::before pseudo-element
var bodyBefore = getComputedStyle(document.body, '::before');
var bodyBeforeOpacity = parseFloat(bodyBefore.getPropertyValue('opacity'));
var fadeOutInterval = setInterval(function () {
if (bodyBeforeOpacity <= 0) {
clearInterval(fadeOutInterval);
document.body.style.overflow = 'visible'; // Optional: Show content outside body bounds if necessary
// Start the game once the fade-out animation is complete
startGame();
} else {
bodyBeforeOpacity -= 0.1;
document.body.style.setProperty('--before-opacity', bodyBeforeOpacity);
}
}, 100); // Adjust the fade-out interval as needed
});
});