-
Notifications
You must be signed in to change notification settings - Fork 839
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f64e004
commit 3b1ac75
Showing
6 changed files
with
463 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# Shadow Runner | ||
|
||
Shadow Runner is a simple browser-based game where the player must navigate through obstacles and collect power-ups to score points. The game area scrolls continuously, and the player must avoid obstacles while collecting power-ups to increase their score. | ||
|
||
## Table of Contents | ||
|
||
- [Gameplay](#gameplay) | ||
- [Usage](#usage) | ||
- [Controls](#controls) | ||
- [Code Structure](#code-structure) | ||
|
||
## Gameplay | ||
|
||
- **Objective**: Avoid obstacles and collect power-ups to score points. | ||
- **Scoring**: | ||
- Yellow Squares: -5 points | ||
- Green Triangles: +10 points | ||
- Red Balls: +15 points | ||
- Double points in darker areas | ||
|
||
## Usage | ||
|
||
1. Open `index.html` in your web browser to start the game. | ||
|
||
## Controls | ||
|
||
- Use the **Arrow** keys to move the player. | ||
|
||
## Code Structure | ||
|
||
- **HTML**: [index.html](index.html) | ||
- Defines the game layout and elements. | ||
- **CSS**: [style.css](style.css) | ||
- Styles the game elements and animations. | ||
- **JavaScript**: [script.js](script.js) | ||
- Implements the game logic and interactions. | ||
|
||
### Key JavaScript Functions and Variables | ||
|
||
- **Variables**: | ||
- `gameArea`: The main game area element. | ||
- `player`: The player element. | ||
- `startButton`: The button to start the game. | ||
- `scoreDisplay`: The element displaying the score. | ||
- `timeDisplay`: The element displaying the remaining time. | ||
- `gameInterval`: The interval for the game loop. | ||
- `lights`, `obstacles`, `powerUps`: Arrays to hold game elements. | ||
- `isGameRunning`: Boolean indicating if the game is running. | ||
- `score`: The player's score. | ||
- `time`: The remaining time. | ||
|
||
- **Functions**: | ||
- `startGame()`: Starts the game. | ||
- `resetGame()`: Resets the game state. | ||
- `updateHUD()`: Updates the HUD with the current score and time. | ||
- `moveElements()`: Moves game elements (lights, obstacles, power-ups). | ||
- `updateGame()`: Updates the game state. | ||
- `checkCollisions()`: Checks for collisions between the player and game elements. | ||
- `gameOver(win)`: Ends the game and displays the win/lose message. | ||
- `createLights()`, `createObstacles()`, `createPowerUps()`: Creates game elements. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Shadow Runner</title> | ||
<link rel="stylesheet" href="style.css"> | ||
</head> | ||
<body> | ||
<div class="game-container"> | ||
<div class="game-area" id="game-area"> | ||
<div class="background" id="background"></div> | ||
<div class="player" id="player"></div> | ||
<div class="win-message" id="win-message">Game Over</div> | ||
<div class="lose-message" id="lose-message">Game Over</div> | ||
</div> | ||
<div class="hud"> | ||
<div class="score" id="score">Score: 0</div> | ||
<div class="time" id="time">Time: 60</div> | ||
</div> | ||
<div class="controls"> | ||
<button id="start-button">Start Game</button> | ||
</div> | ||
<div class="instructions"> | ||
<h2>How to Play</h2> | ||
<ul> | ||
<li>Use <strong>Arrow</strong> keys to move the player.</li> | ||
<li>Yellow Squares: -5 points, Green Triangles: +10 points, Red Balls: +15 points</li> | ||
<li>Double points in darker areas</li> | ||
</ul> | ||
</div> | ||
</div> | ||
<script src="script.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
const gameArea = document.getElementById('game-area'); | ||
const player = document.getElementById('player'); | ||
const startButton = document.getElementById('start-button'); | ||
const background = document.getElementById('background'); | ||
const scoreDisplay = document.getElementById('score'); | ||
const timeDisplay = document.getElementById('time'); | ||
const winMessage = document.getElementById('win-message'); | ||
const loseMessage = document.getElementById('lose-message'); | ||
|
||
let gameInterval; | ||
let lights = []; | ||
let obstacles = []; | ||
let powerUps = []; | ||
let isGameRunning = false; | ||
let score = 0; | ||
let time = 60; | ||
|
||
startButton.addEventListener('click', startGame); | ||
|
||
function startGame() { | ||
resetGame(); | ||
isGameRunning = true; | ||
gameInterval = setInterval(updateGame, 20); | ||
} | ||
|
||
function resetGame() { | ||
isGameRunning = false; | ||
clearInterval(gameInterval); | ||
lights.forEach(light => gameArea.removeChild(light)); | ||
obstacles.forEach(obstacle => gameArea.removeChild(obstacle)); | ||
powerUps.forEach(powerUp => gameArea.removeChild(powerUp)); | ||
lights = []; | ||
obstacles = []; | ||
powerUps = []; | ||
score = 0; | ||
time = 60; | ||
updateHUD(); | ||
winMessage.style.display = 'none'; | ||
loseMessage.style.display = 'none'; | ||
player.style.top = '50%'; | ||
player.style.left = '50%'; | ||
createLights(); | ||
createObstacles(); | ||
createPowerUps(); | ||
} | ||
|
||
function updateHUD() { | ||
scoreDisplay.textContent = `Score: ${score}`; | ||
timeDisplay.textContent = `Time: ${time}`; | ||
} | ||
|
||
function moveElements() { | ||
lights.forEach((light, index) => { | ||
const top = parseFloat(light.style.top); | ||
if (top > gameArea.offsetHeight) { | ||
gameArea.removeChild(light); | ||
lights.splice(index, 1); | ||
createLights(); | ||
} else { | ||
light.style.top = `${top + 2}px`; | ||
} | ||
}); | ||
|
||
obstacles.forEach((obstacle, index) => { | ||
const top = parseFloat(obstacle.style.top); | ||
if (top > gameArea.offsetHeight) { | ||
gameArea.removeChild(obstacle); | ||
obstacles.splice(index, 1); | ||
createObstacles(); | ||
} else { | ||
obstacle.style.top = `${top + 2}px`; | ||
} | ||
}); | ||
|
||
powerUps.forEach((powerUp, index) => { | ||
const top = parseFloat(powerUp.style.top); | ||
if (top > gameArea.offsetHeight) { | ||
gameArea.removeChild(powerUp); | ||
powerUps.splice(index, 1); | ||
createPowerUps(); | ||
} else { | ||
powerUp.style.top = `${top + 2}px`; | ||
} | ||
}); | ||
} | ||
|
||
function updateGame() { | ||
moveElements(); | ||
checkCollisions(); | ||
updatePlayerPosition(); | ||
updateHUD(); | ||
} | ||
|
||
function checkCollisions() { | ||
const isShadowPresent = document.getElementById('background').classList.contains('shadow'); | ||
const player = document.getElementById('player'); | ||
const gameArea = document.getElementById('game-area'); | ||
const scoreElement = document.getElementById('score'); | ||
|
||
lights.forEach((light, index) => { | ||
if (isColliding(player, light)) { | ||
if (isShadowPresent) { | ||
light.style.width = `${parseFloat(light.style.width) * 2}px`; | ||
light.style.height = `${parseFloat(light.style.height) * 2}px`; | ||
score -= 10; | ||
} else { | ||
score -= 5; | ||
} | ||
gameArea.removeChild(light); | ||
lights.splice(index, 1); | ||
createLights(); | ||
} | ||
}); | ||
|
||
obstacles.forEach((obstacle, index) => { | ||
if (isColliding(player, obstacle)) { | ||
if (isShadowPresent) { | ||
obstacle.style.width = `${parseFloat(obstacle.style.width) * 2}px`; | ||
obstacle.style.height = `${parseFloat(obstacle.style.height) * 2}px`; | ||
score += 30; | ||
} else { | ||
score += 15; | ||
} | ||
gameArea.removeChild(obstacle); | ||
obstacles.splice(index, 1); | ||
createObstacles(); | ||
} | ||
}); | ||
|
||
powerUps.forEach((powerUp, index) => { | ||
if (isColliding(player, powerUp)) { | ||
if (isShadowPresent) { | ||
powerUp.style.width = `${parseFloat(powerUp.style.width) * 2}px`; | ||
powerUp.style.height = `${parseFloat(powerUp.style.height) * 2}px`; | ||
score += 20; // Double score if shadow is present | ||
} else { | ||
score += 10; | ||
} | ||
gameArea.removeChild(powerUp); | ||
powerUps.splice(index, 1); | ||
createPowerUps(); | ||
} | ||
}); | ||
|
||
scoreElement.textContent = `Score: ${score}`; | ||
} | ||
|
||
function isColliding(element1, element2) { | ||
const rect1 = element1.getBoundingClientRect(); | ||
const rect2 = element2.getBoundingClientRect(); | ||
|
||
return !( | ||
rect1.top > rect2.bottom || | ||
rect1.bottom < rect2.top || | ||
rect1.right < rect2.left || | ||
rect1.left > rect2.right | ||
); | ||
} | ||
|
||
function updatePlayerPosition() { | ||
if (keysPressed['ArrowUp']) { | ||
player.style.top = `${Math.max(0, player.offsetTop - 5)}px`; | ||
} | ||
if (keysPressed['ArrowDown']) { | ||
player.style.top = `${Math.min(gameArea.offsetHeight - player.offsetHeight, player.offsetTop + 5)}px`; | ||
} | ||
if (keysPressed['ArrowLeft']) { | ||
player.style.left = `${Math.max(0, player.offsetLeft - 5)}px`; | ||
} | ||
if (keysPressed['ArrowRight']) { | ||
player.style.left = `${Math.min(gameArea.offsetWidth - player.offsetWidth, player.offsetLeft + 5)}px`; | ||
} | ||
} | ||
|
||
const keysPressed = {}; | ||
window.addEventListener('keydown', event => { | ||
keysPressed[event.key] = true; | ||
}); | ||
window.addEventListener('keyup', event => { | ||
delete keysPressed[event.key]; | ||
}); | ||
|
||
function gameOver(win) { | ||
isGameRunning = false; | ||
clearInterval(gameInterval); | ||
if (win) { | ||
winMessage.style.display = 'block'; | ||
} else { | ||
loseMessage.style.display = 'block'; | ||
} | ||
} | ||
|
||
setInterval(() => { | ||
if (isGameRunning && time > 0) { | ||
time--; | ||
updateHUD(); | ||
} else if (isGameRunning && time <= 0) { | ||
gameOver(true); | ||
} | ||
}, 1000); | ||
|
||
function createLights() { | ||
const light = document.createElement('div'); | ||
light.className = 'light'; | ||
light.style.top = '0px'; | ||
light.style.left = `${Math.random() * (gameArea.offsetWidth - 100)}px`; | ||
gameArea.appendChild(light); | ||
lights.push(light); | ||
} | ||
|
||
function createObstacles() { | ||
const obstacle = document.createElement('div'); | ||
obstacle.className = 'obstacle'; | ||
obstacle.style.top = '0px'; | ||
obstacle.style.left = `${Math.random() * (gameArea.offsetWidth - 30)}px`; | ||
gameArea.appendChild(obstacle); | ||
obstacles.push(obstacle); | ||
} | ||
|
||
function createPowerUps() { | ||
const powerUp = document.createElement('div'); | ||
powerUp.className = 'power-up'; | ||
powerUp.style.top = '0px'; | ||
powerUp.style.left = `${Math.random() * (gameArea.offsetWidth - 40)}px`; | ||
gameArea.appendChild(powerUp); | ||
powerUps.push(powerUp); | ||
} |
Oops, something went wrong.