Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

space shooter game added #397

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion my-project/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ import Othello from "./Games/Othello/Othello";
import Toppicks from "./Components/Toppicks";
import AargonAssualt from "./Games/AargonAssualt/AargonAssualt";


import Obstacle3D from "./Games/Obstacle3D/Obstacle3D";
import RollingBall from "./Games/RollingBall/RollingBall";
import SpaceShooterGame from "./Games/Space Shooter Game/SpaceShooterGame";

const App = () => {
const { user, isLoading, isError } = useTma();
Expand Down Expand Up @@ -107,6 +107,7 @@ const App = () => {
<Route path="/dice-roller" element={<DiceRoller />} />{" "}
{/* Add the new route here */}
<Route path="/flappybird" element={<FlappyBird />} />
<Route path="/space-shooter" element={<SpaceShooterGame />} />
<Route path="/pianotiles" element={<PianoTiles />} />
<Route path="/arkanoid" element={<ArkanoidGame />} />
<Route path="/duckhunt" element={<DuckHunt />} />
Expand Down
5 changes: 5 additions & 0 deletions my-project/src/Components/GameSection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ const GameSection = () => {
"Test your memory in the classic Simon Says game! Repeat the sequence of colors as it gets progressively harder. Can you keep up?",
link: "/simon-says",
},
{
name:"Space shooter",
description:"A thrilling space shooter game where players pilot a spaceship through intense battles, dodging asteroids, and defeating waves of enemy aliens to save the galaxy.",
link:"/space-shooter"
},
{
name: "Hangman",
description:
Expand Down
211 changes: 211 additions & 0 deletions my-project/src/Games/Space Shooter Game/SpaceShooterGame.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import React, { useEffect, useRef, useState } from "react";
import "./style.css"; // Importing CSS for styling
import rocket from './Images/rocket.png';
import bomb from './Images/bomb.png';
import explosionImg from './Images/explosion.png';

const SpaceShooterGame = () => {
const gameAreaRef = useRef(null);
const playerRef = useRef(null);
const [score, setScore] = useState(0);
const [isGameOver, setIsGameOver] = useState(false);
const [showStartModal, setShowStartModal] = useState(true);
const [showGameOverModal, setShowGameOverModal] = useState(false);
const bulletsRef = useRef([]);
const enemiesRef = useRef([]);
const playerXRef = useRef(0);
const canShootRef = useRef(true); // For bullet cooldown
const enemyCreationIntervalRef = useRef(null); // To keep track of enemy creation interval

useEffect(() => {
playerXRef.current = gameAreaRef.current.offsetWidth / 2; // Initialize player position
}, []);

const startGame = () => {
setShowStartModal(false);
playerXRef.current = gameAreaRef.current.offsetWidth / 2; // Reset player position
setScore(0); // Reset score
setIsGameOver(false); // Reset game state
bulletsRef.current = []; // Clear bullets
enemiesRef.current = []; // Clear enemies

// Remove all existing enemies from the DOM
const existingEnemies = document.querySelectorAll(".enemy");
existingEnemies.forEach((enemy) => enemy.remove());

// Start spawning enemies
enemyCreationIntervalRef.current = setInterval(() => {
if (isGameOver) {
clearInterval(enemyCreationIntervalRef.current);
} else {
createEnemy();
}
}, 1000);
};

const movePlayer = (direction) => {
let playerX = playerXRef.current + direction;
// Prevent the player from moving out of bounds
if (playerX < 40) playerX = 40;
if (playerX > gameAreaRef.current.offsetWidth - 50)
playerX = gameAreaRef.current.offsetWidth - 50;
playerRef.current.style.left = playerX + "px";
playerXRef.current = playerX;
};

const shootBullet = () => {
if (!canShootRef.current) return; // Prevent shooting if on cooldown

canShootRef.current = false;
setTimeout(() => {
canShootRef.current = true;
}, 300); // 300ms cooldown between shots

const bullet = document.createElement("div");
bullet.classList.add("bullet");
bullet.style.left = playerXRef.current + "px";
bullet.style.bottom = "80px";
gameAreaRef.current.appendChild(bullet);
bulletsRef.current.push(bullet);

const bulletInterval = setInterval(() => {
let bulletY = bullet.offsetTop;
bulletY -= 10;
bullet.style.top = bulletY + "px";

// Check for collision
checkCollision(bullet, bulletInterval);

// Remove if off-screen
if (bulletY < 0) {
clearInterval(bulletInterval);
bullet.remove();
bulletsRef.current.shift();
}
}, 20);
};

const createEnemy = () => {
const enemy = document.createElement("div");
enemy.classList.add("enemy");
enemy.style.backgroundImage = `url(${bomb})`;
enemy.style.backgroundSize = "cover";
enemy.style.left = Math.random() * (gameAreaRef.current.offsetWidth - 60) + "px";
gameAreaRef.current.appendChild(enemy);
enemiesRef.current.push(enemy);

const enemyInterval = setInterval(() => {
let enemyY = enemy.offsetTop;
enemyY += 5;
enemy.style.top = enemyY + "px";

// Check for collision with player
checkPlayerCollision(enemy, enemyInterval);

// Remove enemy if off-screen
if (enemyY > gameAreaRef.current.offsetHeight) {
clearInterval(enemyInterval);
enemy.remove();
enemiesRef.current.shift();
}
}, 150);
};

const checkCollision = (bullet, bulletInterval) => {
const bulletRect = bullet.getBoundingClientRect();
enemiesRef.current.forEach((enemy, index) => {
const enemyRect = enemy.getBoundingClientRect();
if (
bulletRect.left < enemyRect.right &&
bulletRect.right > enemyRect.left &&
bulletRect.top < enemyRect.bottom &&
bulletRect.bottom > enemyRect.top
) {
setScore((prevScore) => prevScore + 1);
clearInterval(bulletInterval);
bullet.remove();

// Play explosion animation
enemy.style.backgroundImage = `url(${explosionImg})`;
enemy.classList.add('explosion');
setTimeout(() => enemy.remove(), 500); // Remove after explosion
enemiesRef.current.splice(index, 1);
}
});
};

const checkPlayerCollision = (enemy, enemyInterval) => {
const playerRect = playerRef.current.getBoundingClientRect();
const enemyRect = enemy.getBoundingClientRect();
if (
playerRect.left < enemyRect.right &&
playerRect.right > enemyRect.left &&
playerRect.top < enemyRect.bottom &&
playerRect.bottom > enemyRect.top
) {
setIsGameOver(true);
setShowGameOverModal(true);
clearInterval(enemyInterval);
enemiesRef.current.forEach((enemy) => enemy.remove());
enemiesRef.current = [];
clearInterval(enemyCreationIntervalRef.current); // Stop creating new enemies
}
};

const handleRestart = () => {
setShowGameOverModal(false);
window.location.reload();
};

useEffect(() => {
const handleKeyDown = (event) => {
if (isGameOver) return;
if (event.code === "ArrowLeft") {
movePlayer(-20);
} else if (event.code === "ArrowRight") {
movePlayer(20);
} else if (event.code === "Space") {
shootBullet();
}
};

document.addEventListener("keydown", handleKeyDown);

return () => {
document.removeEventListener("keydown", handleKeyDown);
clearInterval(enemyCreationIntervalRef.current); // Clean up interval on unmount
};
}, [isGameOver]);

return (
<div className="game-container w-full h-full">
<h1 className="text-2xl mb-4 rounded-md w-full ">Space Shooter Game</h1>
<div id="gameArea" ref={gameAreaRef} className="pb-4">
<div id="scoreBoard" className="text-2xl my-4 rounded-full text-white ">Score: {score}</div>
<div id="player" ref={playerRef}>
<img src={rocket} alt="rocket" width="50" height="80" />
</div>
</div>
{showStartModal && (
<div id="startModal" className="modal show"> {/* Add 'show' class */}
<div className="modal-content">
<h1 className="bg-transparent text-black">Start Game</h1>
<button onClick={startGame} className="text-white bg-green-500 hover:bg-green-700">Start</button>
</div>
</div>
)}

{showGameOverModal && (
<div id="gameOverModal" className="modal show"> {/* Add 'show' class */}
<div className="modal-content">
<h1 className="bg-transparent text-black">Game Over</h1>
<p className="text-black text-xl">Score: {score}</p>
<button onClick={handleRestart} className="text-white bg-green-500 hover:bg-green-700 py-2 button">Restart</button>
</div>
</div>
)}
</div>
);
};

export default SpaceShooterGame;
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
108 changes: 108 additions & 0 deletions my-project/src/Games/Space Shooter Game/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@


.game-container {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}

#gameArea {
position: relative;
width: 400px;
height: 600px; /* Set a fixed height for the game area */
border: 1px solid #fff;
overflow: hidden;
background-color: #111;
border-radius: 5px;
/* Dark background for the game area */
}

#player {
position: absolute;
bottom: 0px;
left: 50%;
transform: translateX(-50%);

/* Positioning the player near the bottom */
}

.bullet {
position: absolute;
width: 5px;
height: 20px;
background-color: yellow;
bottom: 80px; /* Position it above the player */
}

.enemy {
position: absolute;
width: 50px;
height: 50px;
background-color: transparent; /* Set transparent to use background image */
}

.explosion {
animation: explode 0.5s forwards;
}

@keyframes explode {
0% { transform: scale(1); }
100% { transform: scale(1.5); opacity: 0; }
}

.modal {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
color: rgb(0 0 0);
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: transparent;
z-index: 10; /* Ensures modal is above other content */
opacity: 0; /* Start hidden */
transition: opacity 0.5s ease; /* Transition for fade effect */
}

.modal.show {
opacity: 1; /* Make visible when show class is added */
}

.modal-content {
width: 300px;
background-color: #ffffff;
padding: 20px;
border-radius: 8px;
text-align: center;
font-size: 0.7rem;
line-height: 1.75rem;
}

button {
width: 100%;
background-color: #4CAF50; /* Green */
border: none;
color: white;
padding: 10px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
border-radius: 4px;
transition: background-color 0.3s;
}

button:hover {
background-color: #45a049; /* Darker green */
}
p{
font-size: 1.25rem;
line-height: 1.75rem;
}