neural-canvas / index.html
JohnPork04's picture
Add 1 files
bb2ce28 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cosmic Evasion</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
font-family: 'Arial', sans-serif;
}
#game-container {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
}
#game-canvas {
display: block;
background-color: #000;
}
#ui {
position: absolute;
top: 20px;
left: 20px;
color: white;
font-size: 18px;
text-shadow: 0 0 5px rgba(0, 255, 255, 0.8);
z-index: 10;
}
#start-screen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
z-index: 20;
}
#game-over {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
z-index: 20;
}
.btn {
margin-top: 20px;
padding: 10px 30px;
background: linear-gradient(135deg, #00d2ff 0%, #3a7bd5 100%);
border: none;
border-radius: 30px;
color: white;
font-size: 18px;
cursor: pointer;
transition: all 0.3s;
box-shadow: 0 5px 15px rgba(0, 210, 255, 0.4);
}
.btn:hover {
transform: translateY(-3px);
box-shadow: 0 8px 20px rgba(0, 210, 255, 0.6);
}
.btn:active {
transform: translateY(1px);
}
</style>
</head>
<body class="bg-black">
<div id="game-container">
<canvas id="game-canvas"></canvas>
<div id="ui">
<div>Score: <span id="score">0</span></div>
<div>Distance: <span id="distance">0</span> light-years</div>
<div>Speed: <span id="speed">0</span></div>
</div>
<div id="start-screen">
<h1 class="text-4xl font-bold mb-4 text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 to-blue-500">COSMIC EVASION</h1>
<p class="text-xl mb-8">Navigate through space and avoid obstacles!</p>
<button id="start-btn" class="btn">START GAME</button>
<div class="mt-8 text-sm opacity-70">
<p>Controls: Arrow Keys or WASD to move</p>
<p>Space to boost (limited fuel)</p>
</div>
</div>
<div id="game-over">
<h1 class="text-4xl font-bold mb-4 text-transparent bg-clip-text bg-gradient-to-r from-red-400 to-pink-600">GAME OVER</h1>
<p class="text-xl mb-2">Final Score: <span id="final-score">0</span></p>
<p class="text-xl mb-8">Distance Traveled: <span id="final-distance">0</span> light-years</p>
<button id="restart-btn" class="btn">PLAY AGAIN</button>
</div>
</div>
<script>
// Game variables
const canvas = document.getElementById('game-canvas');
const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('score');
const distanceElement = document.getElementById('distance');
const speedElement = document.getElementById('speed');
const finalScoreElement = document.getElementById('final-score');
const finalDistanceElement = document.getElementById('final-distance');
const startScreen = document.getElementById('start-screen');
const gameOverScreen = document.getElementById('game-over');
const startBtn = document.getElementById('start-btn');
const restartBtn = document.getElementById('restart-btn');
// Set canvas size
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Game state
let gameRunning = false;
let score = 0;
let distance = 0;
let speed = 3;
let gameSpeed = 3;
let boostFuel = 100;
let isBoosting = false;
let backgroundOffset = 0;
let currentBackground = 0;
let obstacleSpawnTimer = 0;
let starSpawnTimer = 0;
let planetSpawnTimer = 0;
let animationFrameId;
// Background colors for different zones
const backgroundColors = [
{ top: '#000428', bottom: '#004e92' }, // Blue nebula
{ top: '#1a1a2e', bottom: '#16213e' }, // Deep space
{ top: '#0f0c29', bottom: '#302b63' }, // Purple nebula
{ top: '#3a1c71', bottom: '#d76d77' }, // Pink/purple
{ top: '#000000', bottom: '#0f2027' }, // Dark space
{ top: '#1e3c72', bottom: '#2a5298' }, // Blue space
{ top: '#614385', bottom: '#516395' }, // Purple space
{ top: '#0f2027', bottom: '#203a43' } // Dark blue
];
// Player
const player = {
x: canvas.width / 4,
y: canvas.height / 2,
width: 40,
height: 30,
speed: 5,
color: '#00d2ff',
boostColor: '#ff5e62',
isBoosting: false,
draw() {
ctx.save();
ctx.fillStyle = this.isBoosting ? this.boostColor : this.color;
// Draw spaceship
ctx.beginPath();
ctx.moveTo(this.x, this.y);
ctx.lineTo(this.x - this.width, this.y + this.height/2);
ctx.lineTo(this.x, this.y + this.height);
ctx.closePath();
ctx.fill();
// Draw boost flame if boosting
if (this.isBoosting) {
ctx.beginPath();
ctx.moveTo(this.x - this.width, this.y + this.height/2 - 5);
ctx.lineTo(this.x - this.width - 15, this.y + this.height/2);
ctx.lineTo(this.x - this.width, this.y + this.height/2 + 5);
ctx.closePath();
ctx.fill();
}
ctx.restore();
},
update() {
// Boundary checking
if (this.y < 0) this.y = 0;
if (this.y > canvas.height - this.height) this.y = canvas.height - this.height;
}
};
// Stars for background
const stars = [];
class Star {
constructor() {
this.x = canvas.width;
this.y = Math.random() * canvas.height;
this.size = Math.random() * 3;
this.speed = speed + Math.random() * 3;
this.color = `rgba(255, 255, 255, ${Math.random()})`;
}
update() {
this.x -= this.speed;
}
draw() {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
}
isOffScreen() {
return this.x + this.size < 0;
}
}
// Planets for background
const planets = [];
class Planet {
constructor() {
this.x = canvas.width;
this.y = Math.random() * canvas.height;
this.size = 50 + Math.random() * 100;
this.speed = speed * 0.5;
this.color = `hsl(${Math.random() * 360}, 70%, 50%)`;
this.hasRing = Math.random() > 0.7;
}
update() {
this.x -= this.speed;
}
draw() {
// Planet
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
// Ring
if (this.hasRing) {
ctx.strokeStyle = `hsla(${Math.random() * 360}, 80%, 60%, 0.7)`;
ctx.lineWidth = 5;
ctx.beginPath();
ctx.ellipse(this.x, this.y, this.size * 1.5, this.size * 0.3, 0, 0, Math.PI * 2);
ctx.stroke();
}
}
isOffScreen() {
return this.x + this.size < 0;
}
}
// Obstacles
const obstacles = [];
class Obstacle {
constructor() {
this.width = 40 + Math.random() * 60;
this.height = 40 + Math.random() * 100;
this.x = canvas.width;
this.y = Math.random() * (canvas.height - this.height);
this.speed = speed;
this.color = `hsl(${Math.random() * 60 + 20}, 80%, 50%)`;
this.type = Math.random() > 0.5 ? 'rectangle' : 'triangle';
}
update() {
this.x -= this.speed;
}
draw() {
ctx.fillStyle = this.color;
if (this.type === 'rectangle') {
ctx.fillRect(this.x, this.y, this.width, this.height);
} else {
ctx.beginPath();
ctx.moveTo(this.x, this.y);
ctx.lineTo(this.x + this.width, this.y + this.height/2);
ctx.lineTo(this.x, this.y + this.height);
ctx.closePath();
ctx.fill();
}
}
isOffScreen() {
return this.x + this.width < 0;
}
collidesWith(player) {
return player.x < this.x + this.width &&
player.x + player.width > this.x &&
player.y < this.y + this.height &&
player.y + player.height > this.y;
}
}
// Power-ups
const powerups = [];
class PowerUp {
constructor() {
this.x = canvas.width;
this.y = Math.random() * canvas.height;
this.radius = 15;
this.speed = speed;
this.type = Math.random() > 0.5 ? 'fuel' : 'shield';
}
update() {
this.x -= this.speed;
}
draw() {
ctx.save();
if (this.type === 'fuel') {
ctx.fillStyle = '#00d2ff';
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fill();
// Draw fuel symbol
ctx.fillStyle = '#000';
ctx.font = 'bold 20px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('F', this.x, this.y);
} else {
// Shield
ctx.fillStyle = '#3a7bd5';
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fill();
// Draw shield symbol
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius - 5, -Math.PI/4, Math.PI/4);
ctx.stroke();
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius - 8, -Math.PI/4, Math.PI/4);
ctx.stroke();
}
ctx.restore();
}
isOffScreen() {
return this.x + this.radius < 0;
}
collidesWith(player) {
const dx = this.x - (player.x + player.width/2);
const dy = this.y - (player.y + player.height/2);
const distance = Math.sqrt(dx * dx + dy * dy);
return distance < this.radius + Math.max(player.width, player.height)/2;
}
}
// Input handling
const keys = {
ArrowUp: false,
ArrowDown: false,
ArrowLeft: false,
ArrowRight: false,
w: false,
a: false,
s: false,
d: false,
' ': false
};
window.addEventListener('keydown', (e) => {
if (keys.hasOwnProperty(e.key)) {
keys[e.key] = true;
}
});
window.addEventListener('keyup', (e) => {
if (keys.hasOwnProperty(e.key)) {
keys[e.key] = false;
}
});
// Game functions
function startGame() {
gameRunning = true;
score = 0;
distance = 0;
speed = 3;
gameSpeed = 3;
boostFuel = 100;
currentBackground = 0;
backgroundOffset = 0;
obstacles.length = 0;
stars.length = 0;
planets.length = 0;
powerups.length = 0;
player.x = canvas.width / 4;
player.y = canvas.height / 2;
player.isBoosting = false;
startScreen.style.display = 'none';
gameOverScreen.style.display = 'none';
animationFrameId = requestAnimationFrame(gameLoop);
}
function endGame() {
gameRunning = false;
finalScoreElement.textContent = score;
finalDistanceElement.textContent = distance.toFixed(1);
gameOverScreen.style.display = 'flex';
cancelAnimationFrame(animationFrameId);
}
function handleInput() {
player.isBoosting = false;
// Vertical movement
if ((keys.ArrowUp || keys.w) && !(keys.ArrowDown || keys.s)) {
player.y -= player.speed;
} else if ((keys.ArrowDown || keys.s) && !(keys.ArrowUp || keys.w)) {
player.y += player.speed;
}
// Horizontal movement
if ((keys.ArrowLeft || keys.a) && !(keys.ArrowRight || keys.d)) {
player.x -= player.speed;
} else if ((keys.ArrowRight || keys.d) && !(keys.ArrowLeft || keys.a)) {
player.x += player.speed;
}
// Boost
if ((keys[' ']) && boostFuel > 0) {
player.isBoosting = true;
boostFuel -= 0.5;
gameSpeed = speed * 2;
} else {
gameSpeed = speed;
}
// Recharge boost when not in use
if (!keys[' '] && boostFuel < 100) {
boostFuel += 0.1;
}
}
function spawnObjects() {
// Spawn stars
starSpawnTimer++;
if (starSpawnTimer > 5) {
stars.push(new Star());
starSpawnTimer = 0;
}
// Spawn obstacles
obstacleSpawnTimer++;
if (obstacleSpawnTimer > 60 - Math.min(50, distance / 10)) {
obstacles.push(new Obstacle());
obstacleSpawnTimer = 0;
// Occasionally spawn power-up after obstacle
if (Math.random() > 0.7) {
powerups.push(new PowerUp());
}
}
// Spawn planets
planetSpawnTimer++;
if (planetSpawnTimer > 300) {
planets.push(new Planet());
planetSpawnTimer = 0;
}
}
function updateObjects() {
// Update stars
for (let i = stars.length - 1; i >= 0; i--) {
stars[i].update();
if (stars[i].isOffScreen()) {
stars.splice(i, 1);
}
}
// Update obstacles
for (let i = obstacles.length - 1; i >= 0; i--) {
obstacles[i].speed = gameSpeed;
obstacles[i].update();
if (obstacles[i].isOffScreen()) {
obstacles.splice(i, 1);
score += 10;
}
// Check collision
if (obstacles[i].collidesWith(player)) {
endGame();
return;
}
}
// Update planets
for (let i = planets.length - 1; i >= 0; i--) {
planets[i].speed = gameSpeed * 0.5;
planets[i].update();
if (planets[i].isOffScreen()) {
planets.splice(i, 1);
}
}
// Update power-ups
for (let i = powerups.length - 1; i >= 0; i--) {
powerups[i].speed = gameSpeed;
powerups[i].update();
if (powerups[i].isOffScreen()) {
powerups.splice(i, 1);
}
// Check collision
if (powerups[i].collidesWith(player)) {
if (powerups[i].type === 'fuel') {
boostFuel = Math.min(100, boostFuel + 30);
} else {
// Shield - temporary invincibility
// For simplicity, we'll just add score
score += 50;
}
powerups.splice(i, 1);
}
}
}
function drawBackground() {
// Gradient background based on current zone
const bgColor = backgroundColors[currentBackground % backgroundColors.length];
const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
gradient.addColorStop(0, bgColor.top);
gradient.addColorStop(1, bgColor.bottom);
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw distant stars (parallax effect)
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
for (let i = 0; i < 100; i++) {
const x = (i * 200 + backgroundOffset * 0.2) % canvas.width;
const y = (i * 150) % canvas.height;
const size = 1 + (i % 3);
ctx.beginPath();
ctx.arc(x, y, size, 0, Math.PI * 2);
ctx.fill();
}
}
function drawUI() {
// Boost fuel meter
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(20, canvas.height - 40, 200, 20);
ctx.fillStyle = '#00d2ff';
ctx.fillRect(20, canvas.height - 40, 200 * (boostFuel / 100), 20);
ctx.strokeStyle = 'white';
ctx.lineWidth = 2;
ctx.strokeRect(20, canvas.height - 40, 200, 20);
ctx.fillStyle = 'white';
ctx.font = '14px Arial';
ctx.fillText('BOOST', 25, canvas.height - 25);
}
function updateGameState() {
// Increase distance and speed over time
distance += gameSpeed * 0.01;
speed = 3 + Math.floor(distance / 20) * 0.5;
// Change background zone every 50 distance units
if (distance > (currentBackground + 1) * 50) {
currentBackground++;
}
// Update UI elements
scoreElement.textContent = score;
distanceElement.textContent = distance.toFixed(1);
speedElement.textContent = gameSpeed.toFixed(1);
// Move background for parallax effect
backgroundOffset += gameSpeed * 0.1;
}
function gameLoop() {
if (!gameRunning) return;
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw background
drawBackground();
// Handle input
handleInput();
// Spawn objects
spawnObjects();
// Update objects
updateObjects();
if (!gameRunning) return; // Check again in case collision occurred
player.update();
// Draw objects
for (const star of stars) star.draw();
for (const planet of planets) planet.draw();
for (const obstacle of obstacles) obstacle.draw();
for (const powerup of powerups) powerup.draw();
player.draw();
// Draw UI
drawUI();
// Update game state
updateGameState();
// Next frame
animationFrameId = requestAnimationFrame(gameLoop);
}
// Event listeners for buttons
startBtn.addEventListener('click', startGame);
restartBtn.addEventListener('click', startGame);
// Handle window resize
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Keep player in bounds if screen gets smaller
if (player.y > canvas.height - player.height) {
player.y = canvas.height - player.height;
}
});
// Initial setup
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=JohnPork04/neural-canvas" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>