In the ever-evolving world of web development, creating engaging and interactive experiences is key to captivating your audience. Today, we'll embark on an exciting journey to build a futuristic neon space shooter game featuring advanced animations, addictive gameplay, and epic boss battles. This game is entirely crafted using HTML5 Canvas, CSS3, and Vanilla JavaScript.
Check out the live demo on CodePen https://codepen.io/HanGPIIIErr/pen/dPbbwPR
π What We'll Build
- Advanced Animations: A visually stunning game with neon effects and smooth transitions.
- Addictive Gameplay: Control a spaceship, defeat waves of enemies, and face challenging bosses.
- Epic Boss Battles: Bosses appear every 1000 points, growing stronger each time.
- Futuristic Design: A sleek neon aesthetic that enhances the gaming experience.
- Responsive Controls: Smooth and responsive controls for optimal player experience.
π Technologies Used
- HTML5 Canvas for rendering game graphics.
- CSS3 for styling and visual enhancements.
- JavaScript (ES6) for game logic and interactivity.
- Responsive Design principles to ensure compatibility across devices.
π§ Step-by-Step Tutorial
- Setting Up the Project Structure Create the following files in your project directory:
index.html β The main HTML file.
style.css β The CSS styles.
script.js β The JavaScript code.
- Crafting the HTML Structure
We'll start by setting up the basic HTML structure, including the game canvas, HUD (Heads-Up Display), and overlay elements.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Futuristic Neon Space Shooter Game</title>
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- Futuristic Overlay Elements -->
<div class="overlay">
<div class="grid"></div>
<div class="circuits"></div>
</div>
<div class="game-container">
<!-- Heads-Up Display (HUD) -->
<div class="hud">
<div class="score">
Score: <span id="score">0</span>
</div>
<div class="lives">
Lives: <span id="lives">3</span>
</div>
<div class="instructions">
<div class="control">
<span class="icon">β¬οΈβ¬οΈβ¬
οΈβ‘οΈ</span>
<span class="text">Move</span>
</div>
<div class="control">
<span class="icon">β΅</span>
<span class="text">Shoot</span>
</div>
</div>
</div>
<!-- Game Canvas -->
<canvas id="gameCanvas"></canvas>
<!-- Game Over Screen -->
<div class="game-over" id="gameOver">
<h1>Game Over</h1>
<p>Your Score: <span id="finalScore"></span></p>
<button id="restartButton">Restart</button>
</div>
</div>
<!-- Futuristic Background Elements -->
<div class="background-elements">
<!-- Animated Stars -->
<div class="stars"></div>
<!-- Glowing Nebula -->
<div class="nebula"></div>
</div>
<script src="script.js"></script>
</body>
</html>
Explanation:
- Futuristic Overlay Elements: These add dynamic visual effects like grids and circuits.
- Game Container: Contains the HUD, game canvas, and game over screen.
- HUD: Displays the score, lives, and instructions with minimalist icons.
- Background Elements: Includes animated stars and a glowing nebula for depth.
- Styling with CSS
Next, we'll bring the game to life with CSS, enhancing the visuals to achieve a futuristic neon aesthetic.
/* Global Styles */
body {
margin: 0;
padding: 0;
background: radial-gradient(circle at center, #0d0d0d, #000000 70%);
font-family: 'Orbitron', sans-serif;
overflow: hidden;
color: #00f6ff;
}
/* Game Container */
.game-container {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
}
/* Game Canvas */
#gameCanvas {
display: block;
background: transparent;
position: relative;
z-index: 2;
}
/* HUD Styling */
.hud {
position: absolute;
top: 20px;
left: 20px;
display: flex;
flex-direction: column;
align-items: flex-start;
color: #00f6ff;
z-index: 5;
font-size: 18px;
text-shadow: 0 0 10px #00f6ff;
}
.hud .score,
.hud .lives {
margin: 5px 0;
}
.hud .instructions {
margin-top: 10px;
display: flex;
flex-direction: column;
font-size: 16px;
color: #00f6ff;
opacity: 0.9;
}
.hud .instructions .control {
display: flex;
align-items: center;
margin: 3px 0;
}
.hud .instructions .icon {
font-size: 20px;
margin-right: 8px;
display: flex;
align-items: center;
}
.hud .instructions .text {
font-size: 16px;
}
/* Game Over Screen */
.game-over {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(13, 13, 13, 0.95);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #00f6ff;
text-align: center;
z-index: 10;
display: none;
}
.game-over h1 {
font-size: 72px;
margin: 0;
text-shadow: 0 0 20px #00f6ff, 0 0 30px #00f6ff;
}
.game-over p {
font-size: 24px;
}
#restartButton {
padding: 15px 30px;
font-size: 24px;
color: #00f6ff;
background: #111;
border: none;
border-radius: 10px;
cursor: pointer;
margin-top: 20px;
box-shadow: 0 0 20px rgba(0, 246, 255, 0.5);
transition: background 0.3s;
}
#restartButton:hover {
background: #222;
}
/* Overlay Effects */
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 3;
pointer-events: none;
}
.overlay .grid {
position: absolute;
width: 100%;
height: 100%;
background: repeating-linear-gradient(
0deg,
transparent,
transparent 49%,
rgba(0, 246, 255, 0.1) 50%,
rgba(0, 246, 255, 0.1) 51%,
transparent 52%,
transparent 100%
),
repeating-linear-gradient(
90deg,
transparent,
transparent 49%,
rgba(0, 246, 255, 0.1) 50%,
rgba(0, 246, 255, 0.1) 51%,
transparent 52%,
transparent 100%
);
background-size: 50px 50px;
animation: gridAnimation 10s linear infinite;
}
@keyframes gridAnimation {
from {
background-position: 0 0;
}
to {
background-position: 1000px 1000px;
}
}
.overlay .circuits {
position: absolute;
width: 100%;
height: 100%;
background: url('your-circuit-pattern-url.png') repeat;
opacity: 0.05;
animation: circuitAnimation 20s linear infinite;
}
@keyframes circuitAnimation {
from {
background-position: 0 0;
}
to {
background-position: -500px -500px;
}
}
/* Background Elements */
.background-elements {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
pointer-events: none;
}
.background-elements .stars {
position: absolute;
width: 100%;
height: 100%;
background: url('your-stars-pattern-url.png') repeat;
opacity: 0.3;
animation: starAnimation 50s linear infinite;
}
@keyframes starAnimation {
from {
background-position: 0 0;
}
to {
background-position: -1000px 0;
}
}
.background-elements .nebula {
position: absolute;
width: 100%;
height: 100%;
background: radial-gradient(
circle at 50% 50%,
rgba(0, 246, 255, 0.2),
transparent
);
filter: blur(100px);
}
/* Responsive Design */
@media (max-width: 768px) {
.hud {
top: 10px;
left: 10px;
font-size: 16px;
}
.hud .instructions .icon {
font-size: 18px;
}
.hud .instructions .text {
font-size: 14px;
}
.game-over h1 {
font-size: 48px;
}
#restartButton {
font-size: 20px;
}
}
Explanation:
- Global Styles: Setting a dark background with a radial gradient and applying the Orbitron font for a futuristic feel.
- HUD Styling: Positioned in the top-left corner with neon glow effects. Instructions are displayed with minimalist icons.
- Overlay Effects: Animated grids and circuits to enhance the futuristic aesthetic.
- Background Elements: Animated stars and a glowing nebula create depth and immersion.
- Responsive Design: Media queries adjust styles for smaller screens.
Note: Replace 'your-circuit-pattern-url.png' and 'your-stars-pattern-url.png' with actual image URLs or local paths.
- Adding Game Logic with JavaScript
Now, we'll develop the game mechanics using JavaScript.
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// Set canvas size
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Variables for game entities and state
let player, bullets, enemies, particles, bosses;
let keys = {};
let score = 0;
let lives = 3;
let gameOver = false;
let bossActive = false;
let bossLevel = 1;
// Get HUD elements
const scoreElement = document.getElementById('score');
const livesElement = document.getElementById('lives');
const finalScoreElement = document.getElementById('finalScore');
const gameOverScreen = document.getElementById('gameOver');
// Player Class
class Player {
constructor(x, y, radius, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.speed = 7;
}
draw() {
// Draw player ship (triangle)
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(Math.PI / 2);
ctx.beginPath();
ctx.moveTo(0, -this.radius);
ctx.lineTo(-this.radius, this.radius);
ctx.lineTo(this.radius, this.radius);
ctx.closePath();
ctx.fillStyle = this.color;
ctx.shadowBlur = 20;
ctx.shadowColor = this.color;
ctx.fill();
ctx.restore();
}
update() {
// Move player based on keys pressed
if (keys['ArrowLeft'] && this.x - this.radius > 0) {
this.x -= this.speed;
}
if (keys['ArrowRight'] && this.x + this.radius < canvas.width) {
this.x += this.speed;
}
if (keys['ArrowUp'] && this.y - this.radius > 0) {
this.y -= this.speed;
}
if (keys['ArrowDown'] && this.y + this.radius < canvas.height) {
this.y += this.speed;
}
this.draw();
}
}
// Bullet Class
class Bullet {
constructor(x, y, radius, color, velocity) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.velocity = velocity;
}
draw() {
// Draw bullet
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.shadowBlur = 15;
ctx.shadowColor = this.color;
ctx.fill();
ctx.closePath();
}
update() {
// Move bullet
this.x += this.velocity.x;
this.y += this.velocity.y;
this.draw();
}
}
// Enemy Class
class Enemy {
constructor(x, y, radius, color, velocity, type) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.velocity = velocity;
this.type = type; // 'normal', 'fast', 'big'
this.health = radius;
}
draw() {
// Draw enemy
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.shadowBlur = 20;
ctx.shadowColor = this.color;
ctx.fill();
ctx.closePath();
}
update() {
// Move enemy
this.x += this.velocity.x;
this.y += this.velocity.y;
this.draw();
}
}
// Boss Class
class Boss {
constructor(x, y, radius, color, speed, health) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.speed = speed;
this.health = health;
this.maxHealth = health;
}
draw() {
// Draw boss
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.shadowBlur = 30;
ctx.shadowColor = this.color;
ctx.fill();
ctx.closePath();
// Draw health bar
ctx.beginPath();
ctx.rect(this.x - this.radius, this.y - this.radius - 20, (this.radius * 2) * (this.health / this.maxHealth), 10);
ctx.fillStyle = 'red';
ctx.fill();
ctx.closePath();
}
update() {
// Move boss towards player
const angle = Math.atan2(player.y - this.y, player.x - this.x);
this.x += Math.cos(angle) * this.speed;
this.y += Math.sin(angle) * this.speed;
this.draw();
}
}
// Particle Class for Explosions
class Particle {
constructor(x, y, radius, color, velocity) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.velocity = velocity;
this.alpha = 1;
}
draw() {
// Draw particle with fading effect
ctx.save();
ctx.globalAlpha = this.alpha;
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.shadowBlur = 15;
ctx.shadowColor = this.color;
ctx.fill();
ctx.closePath();
ctx.restore();
}
update() {
// Move particle and reduce alpha
this.x += this.velocity.x;
this.y += this.velocity.y;
this.alpha -= 0.01;
this.draw();
}
}
// Initialize Game
function init() {
player = new Player(canvas.width / 2, canvas.height - 100, 20, '#00f6ff');
bullets = [];
enemies = [];
particles = [];
bosses = [];
score = 0;
lives = 3;
bossActive = false;
bossLevel = 1;
gameOver = false;
scoreElement.innerText = score;
livesElement.innerText = lives;
gameOverScreen.style.display = 'none';
animate();
spawnEnemies();
}
// Animation Loop
let animationId;
function animate() {
animationId = requestAnimationFrame(animate);
// Create a trailing effect
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
player.update();
// Update particles
particles.forEach((particle, index) => {
if (particle.alpha <= 0) {
particles.splice(index, 1);
} else {
particle.update();
}
});
// Update bullets
bullets.forEach((bullet, index) => {
bullet.update();
// Remove bullets off-screen
if (
bullet.x + bullet.radius < 0 ||
bullet.x - bullet.radius > canvas.width ||
bullet.y + bullet.radius < 0 ||
bullet.y - bullet.radius > canvas.height
) {
setTimeout(() => {
bullets.splice(index, 1);
}, 0);
}
});
// Update enemies
enemies.forEach((enemy, index) => {
enemy.update();
// Collision detection with player
const dist = Math.hypot(player.x - enemy.x, player.y - enemy.y);
if (dist - enemy.radius - player.radius < 1) {
// Reduce lives or end game
enemies.splice(index, 1);
lives -= 1;
livesElement.innerText = lives;
if (lives <= 0) {
cancelAnimationFrame(animationId);
gameOver = true;
finalScoreElement.innerText = score;
gameOverScreen.style.display = 'flex';
}
}
// Collision detection with bullets
bullets.forEach((bullet, bulletIndex) => {
const dist = Math.hypot(bullet.x - enemy.x, bullet.y - enemy.y);
if (dist - enemy.radius - bullet.radius < 1) {
// Create explosion particles
for (let i = 0; i < enemy.radius * 2; i++) {
particles.push(
new Particle(
bullet.x,
bullet.y,
Math.random() * 2,
enemy.color,
{
x: (Math.random() - 0.5) * (Math.random() * 6),
y: (Math.random() - 0.5) * (Math.random() * 6),
}
)
);
}
// Shrink or remove enemy
if (enemy.radius - 10 > 10) {
score += 50;
enemy.radius -= 10;
enemy.health -= 10;
bullets.splice(bulletIndex, 1);
} else {
score += 100;
enemies.splice(index, 1);
bullets.splice(bulletIndex, 1);
}
// Update score display
scoreElement.innerText = score;
}
});
});
// Update bosses
bosses.forEach((boss, bossIndex) => {
boss.update();
// Collision detection with player
const dist = Math.hypot(player.x - boss.x, player.y - boss.y);
if (dist - boss.radius - player.radius < 1) {
// Player loses all lives
cancelAnimationFrame(animationId);
gameOver = true;
finalScoreElement.innerText = score;
gameOverScreen.style.display = 'flex';
}
// Collision detection with bullets
bullets.forEach((bullet, bulletIndex) => {
const dist = Math.hypot(bullet.x - boss.x, bullet.y - boss.y);
if (dist - boss.radius - bullet.radius < 1) {
// Create explosion particles
for (let i = 0; i < 8; i++) {
particles.push(
new Particle(
bullet.x,
bullet.y,
Math.random() * 4,
boss.color,
{
x: (Math.random() - 0.5) * (Math.random() * 10),
y: (Math.random() - 0.5) * (Math.random() * 10),
}
)
);
}
// Reduce boss health
boss.health -= 20;
bullets.splice(bulletIndex, 1);
// Check if boss is defeated
if (boss.health <= 0) {
score += 500;
bosses.splice(bossIndex, 1);
bossActive = false;
bossLevel += 1;
// Update score display
scoreElement.innerText = score;
}
}
});
});
// Check if boss should appear
if (score >= bossLevel * 1000 && !bossActive) {
spawnBoss();
bossActive = true;
}
}
// Spawn Enemies
function spawnEnemies() {
const enemyInterval = setInterval(() => {
if (gameOver || bossActive) return;
const radius = Math.random() * (40 - 15) + 15;
const x = Math.random() * canvas.width;
const y = -radius;
const color = `hsl(${Math.random() * 360}, 50%, 50%)`;
// Determine enemy type
const enemyTypeChance = Math.random();
let type = 'normal';
let velocityMultiplier = 1;
if (enemyTypeChance < 0.1) {
// Big enemy
type = 'big';
velocityMultiplier = 0.5;
} else if (enemyTypeChance > 0.9) {
// Fast enemy
type = 'fast';
velocityMultiplier = 2;
}
const angle = Math.atan2(player.y - y, player.x - x);
const velocity = {
x: Math.cos(angle) * velocityMultiplier,
y: Math.sin(angle) * velocityMultiplier,
};
enemies.push(new Enemy(x, y, radius, color, velocity, type));
}, 1000);
}
// Spawn Boss
function spawnBoss() {
const x = canvas.width / 2;
const y = -100;
const radius = 60 + bossLevel * 10;
const color = 'purple';
const speed = 1 + bossLevel * 0.2;
const health = 500 + bossLevel * 100;
bosses.push(new Boss(x, y, radius, color, speed, health));
}
// Event Listeners for Controls
window.addEventListener('keydown', (e) => {
keys[e.key] = true;
if (e.key === ' ' || e.code === 'Space') {
// Shoot bullet
bullets.push(
new Bullet(player.x, player.y, 5, '#fff', { x: 0, y: -10 })
);
}
});
window.addEventListener('keyup', (e) => {
keys[e.key] = false;
});
// Handle Window Resize
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
init();
});
// Restart Game
document.getElementById('restartButton').addEventListener('click', () => {
init();
});
// Start the game
init();
Explanation:
Classes:
- Player: Controls player movement and rendering.
- Bullet: Manages bullet movement and rendering.
- Enemy: Handles enemy behavior, including different types (normal, fast, big).
- Boss: Special enemies that appear every 1000 points with increasing difficulty.
- Particle: Creates explosion effects.
- Game Initialization (init): Resets game variables and starts the animation loop.
- Animation Loop (animate): Updates and renders all game entities, handles collisions, and checks for boss appearances.
- Event Listeners: Handles player input for movement and shooting.
- Testing and Debugging
- Test the Game: Open index.html in your browser and test the gameplay.
- Debugging: Use the browser's developer console to check for any errors.
- Adjust Difficulty: Tweak the variables (e.g., enemy speed, boss health) to balance the game's difficulty.
π SEO Optimization for Gladiators Battle
To enhance SEO for Gladiators Battle, we've:
- Keyword Integration: Included relevant keywords such as "Gladiators Battle," "futuristic neon space shooter game," "HTML5 Canvas," and "JavaScript game development."
- Backlinks: Provided direct links to the Gladiators Battle website to improve domain authority.
- High-Quality Content: Offered a comprehensive tutorial that encourages readers to engage with the Gladiators Battle community.
π Conclusion: A Universe of Possibilities
Building a futuristic neon space shooter game is not only a fun project but also a great way to enhance your web development skills. By combining HTML5 Canvas, CSS3, and JavaScript, you've created an engaging and interactive experience that captivates users.
But this is just the beginning. Dive into Gladiators Battle, where epic battles, engaging mini-games, and a vibrant community of gamers and developers await you.
π Explore More
- Website: https://gladiatorsbattle.com/
- X (formerly Twitter): https://x.com/GladiatorsBT
- LinkedIn: https://www.linkedin.com/in/pierre-romain-lopez/
- Discord: https://discord.gg/YBNF7KjGwx
Thank you for reading, and happy coding! π
Feel free to customize and integrate this space shooter game into your projects. If you have any questions or need further assistance, don't hesitate to reach out in the comments below.
Top comments (0)