|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>Deep Sea Jumper</title> |
|
|
<style> |
|
|
body { |
|
|
margin: 0; |
|
|
padding: 0; |
|
|
background: linear-gradient(180deg, #87CEEB 0%, #4682B4 50%, #191970 100%); |
|
|
font-family: 'Arial', sans-serif; |
|
|
overflow: hidden; |
|
|
display: flex; |
|
|
justify-content: center; |
|
|
align-items: center; |
|
|
min-height: 100vh; |
|
|
} |
|
|
|
|
|
#gameContainer { |
|
|
position: relative; |
|
|
width: 400px; |
|
|
height: 600px; |
|
|
background: linear-gradient(180deg, #87CEEB 0%, #4682B4 30%, #191970 70%, #000080 100%); |
|
|
border: 3px solid #2F4F4F; |
|
|
border-radius: 10px; |
|
|
overflow: hidden; |
|
|
box-shadow: 0 0 30px rgba(0, 100, 200, 0.5); |
|
|
} |
|
|
|
|
|
#gameCanvas { |
|
|
width: 100%; |
|
|
height: 100%; |
|
|
display: block; |
|
|
} |
|
|
|
|
|
#ui { |
|
|
position: absolute; |
|
|
top: 10px; |
|
|
left: 10px; |
|
|
color: white; |
|
|
font-size: 18px; |
|
|
text-shadow: 2px 2px 4px rgba(0,0,0,0.8); |
|
|
z-index: 10; |
|
|
} |
|
|
|
|
|
#gameOver { |
|
|
position: absolute; |
|
|
top: 50%; |
|
|
left: 50%; |
|
|
transform: translate(-50%, -50%); |
|
|
background: rgba(0, 0, 0, 0.8); |
|
|
color: white; |
|
|
padding: 30px; |
|
|
border-radius: 15px; |
|
|
text-align: center; |
|
|
display: none; |
|
|
z-index: 20; |
|
|
} |
|
|
|
|
|
#startButton, #restartButton { |
|
|
background: linear-gradient(45deg, #FF6B6B, #FF8E8E); |
|
|
color: white; |
|
|
border: none; |
|
|
padding: 12px 24px; |
|
|
font-size: 16px; |
|
|
border-radius: 25px; |
|
|
cursor: pointer; |
|
|
margin-top: 15px; |
|
|
transition: all 0.3s ease; |
|
|
} |
|
|
|
|
|
#startButton:hover, #restartButton:hover { |
|
|
transform: scale(1.05); |
|
|
box-shadow: 0 5px 15px rgba(255, 107, 107, 0.4); |
|
|
} |
|
|
|
|
|
.bubble { |
|
|
position: absolute; |
|
|
background: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.3)); |
|
|
border-radius: 50%; |
|
|
animation: float 3s ease-in-out infinite; |
|
|
} |
|
|
|
|
|
@keyframes float { |
|
|
0%, 100% { transform: translateY(0px) rotate(0deg); } |
|
|
50% { transform: translateY(-20px) rotate(180deg); } |
|
|
} |
|
|
|
|
|
#instructions { |
|
|
position: absolute; |
|
|
bottom: 10px; |
|
|
left: 50%; |
|
|
transform: translateX(-50%); |
|
|
color: rgba(255, 255, 255, 0.8); |
|
|
font-size: 12px; |
|
|
text-align: center; |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
<div id="gameContainer"> |
|
|
<canvas id="gameCanvas" width="400" height="600"></canvas> |
|
|
<div id="ui"> |
|
|
<div>Depth: <span id="depth">0</span>m</div> |
|
|
<div>Score: <span id="score">0</span></div> |
|
|
</div> |
|
|
<div id="gameOver"> |
|
|
<h2>Game Over!</h2> |
|
|
<p>Final Depth: <span id="finalDepth">0</span>m</p> |
|
|
<p>Final Score: <span id="finalScore">0</span></p> |
|
|
<button id="restartButton">Dive Again</button> |
|
|
</div> |
|
|
<div id="instructions"> |
|
|
Use ARROW KEYS or A/D to move<br> |
|
|
Space to jump higher |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
const canvas = document.getElementById('gameCanvas'); |
|
|
const ctx = canvas.getContext('2d'); |
|
|
const gameOverDiv = document.getElementById('gameOver'); |
|
|
|
|
|
|
|
|
let audioContext; |
|
|
let sounds = {}; |
|
|
|
|
|
function initAudio() { |
|
|
audioContext = new (window.AudioContext || window.webkitAudioContext)(); |
|
|
|
|
|
|
|
|
sounds.jump = createSound(300, 0.1, 'sine'); |
|
|
sounds.land = createSound(150, 0.15, 'square'); |
|
|
sounds.ambient = createAmbientSound(); |
|
|
} |
|
|
|
|
|
function createSound(frequency, duration, type = 'sine') { |
|
|
return function() { |
|
|
if (!audioContext) return; |
|
|
const oscillator = audioContext.createOscillator(); |
|
|
const gainNode = audioContext.createGain(); |
|
|
|
|
|
oscillator.connect(gainNode); |
|
|
gainNode.connect(audioContext.destination); |
|
|
|
|
|
oscillator.frequency.setValueAtTime(frequency, audioContext.currentTime); |
|
|
oscillator.type = type; |
|
|
|
|
|
gainNode.gain.setValueAtTime(0.1, audioContext.currentTime); |
|
|
gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + duration); |
|
|
|
|
|
oscillator.start(audioContext.currentTime); |
|
|
oscillator.stop(audioContext.currentTime + duration); |
|
|
}; |
|
|
} |
|
|
|
|
|
function createAmbientSound() { |
|
|
return function() { |
|
|
if (!audioContext) return; |
|
|
const oscillator = audioContext.createOscillator(); |
|
|
const gainNode = audioContext.createGain(); |
|
|
|
|
|
oscillator.connect(gainNode); |
|
|
gainNode.connect(audioContext.destination); |
|
|
|
|
|
oscillator.frequency.setValueAtTime(60, audioContext.currentTime); |
|
|
oscillator.type = 'sine'; |
|
|
|
|
|
gainNode.gain.setValueAtTime(0.02, audioContext.currentTime); |
|
|
|
|
|
oscillator.start(audioContext.currentTime); |
|
|
oscillator.stop(audioContext.currentTime + 0.5); |
|
|
}; |
|
|
} |
|
|
|
|
|
class Game { |
|
|
constructor() { |
|
|
this.player = { |
|
|
x: 200, |
|
|
y: 500, |
|
|
width: 20, |
|
|
height: 20, |
|
|
vx: 0, |
|
|
vy: 0, |
|
|
onGround: false, |
|
|
color: '#FF6B6B', |
|
|
lastJumpTime: 0 |
|
|
}; |
|
|
|
|
|
this.platforms = []; |
|
|
this.camera = { y: 0 }; |
|
|
this.depth = 0; |
|
|
this.score = 0; |
|
|
this.gameRunning = false; |
|
|
this.keys = {}; |
|
|
this.particles = []; |
|
|
this.bubbles = []; |
|
|
this.seaCreatures = []; |
|
|
this.snake = null; |
|
|
this.lastCreatureSpawn = 0; |
|
|
|
|
|
this.gravity = 0.5; |
|
|
this.jumpPower = -12; |
|
|
this.moveSpeed = 5; |
|
|
|
|
|
this.generateInitialPlatforms(); |
|
|
this.setupEventListeners(); |
|
|
} |
|
|
|
|
|
generateInitialPlatforms() { |
|
|
|
|
|
this.platforms.push({ |
|
|
x: 150, |
|
|
y: 550, |
|
|
width: 100, |
|
|
height: 15, |
|
|
color: '#8FBC8F' |
|
|
}); |
|
|
|
|
|
|
|
|
for (let i = 1; i < 50; i++) { |
|
|
this.platforms.push({ |
|
|
x: Math.random() * (canvas.width - 80), |
|
|
y: 550 + i * 80, |
|
|
width: 80 + Math.random() * 40, |
|
|
height: 12, |
|
|
color: this.getPlatformColor(i * 80) |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
getPlatformColor(depth) { |
|
|
if (depth < 200) return '#8FBC8F'; |
|
|
if (depth < 500) return '#20B2AA'; |
|
|
if (depth < 1000) return '#4682B4'; |
|
|
if (depth < 1500) return '#483D8B'; |
|
|
return '#2F4F4F'; |
|
|
} |
|
|
|
|
|
getSeaCreatureType(depth) { |
|
|
if (depth < 200) return { type: 'fish', color: '#FFD700', size: 15 }; |
|
|
if (depth < 400) return { type: 'jellyfish', color: '#FF69B4', size: 20 }; |
|
|
if (depth < 600) return { type: 'octopus', color: '#8A2BE2', size: 25 }; |
|
|
if (depth < 800) return { type: 'shark', color: '#708090', size: 30 }; |
|
|
if (depth < 1000) return { type: 'whale', color: '#4169E1', size: 40 }; |
|
|
return { type: 'anglerfish', color: '#32CD32', size: 35 }; |
|
|
} |
|
|
|
|
|
spawnSeaCreature() { |
|
|
const creatureInfo = this.getSeaCreatureType(this.depth); |
|
|
const creature = { |
|
|
x: Math.random() * canvas.width, |
|
|
y: this.camera.y + Math.random() * canvas.height, |
|
|
vx: (Math.random() - 0.5) * 3, |
|
|
vy: (Math.random() - 0.5) * 2, |
|
|
type: creatureInfo.type, |
|
|
color: creatureInfo.color, |
|
|
size: creatureInfo.size, |
|
|
angle: Math.random() * Math.PI * 2, |
|
|
life: 300 + Math.random() * 200 |
|
|
}; |
|
|
this.seaCreatures.push(creature); |
|
|
} |
|
|
|
|
|
spawnSnake() { |
|
|
if (this.snake) return; |
|
|
|
|
|
this.snake = { |
|
|
x: Math.random() * canvas.width, |
|
|
y: this.player.y + 200, |
|
|
vx: 0, |
|
|
vy: 0, |
|
|
speed: 2.5, |
|
|
size: 25, |
|
|
color: '#8B0000', |
|
|
segments: [], |
|
|
targetX: this.player.x, |
|
|
targetY: this.player.y |
|
|
}; |
|
|
|
|
|
|
|
|
for (let i = 0; i < 8; i++) { |
|
|
this.snake.segments.push({ |
|
|
x: this.snake.x - i * 15, |
|
|
y: this.snake.y, |
|
|
angle: 0 |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
setupEventListeners() { |
|
|
document.addEventListener('keydown', (e) => { |
|
|
this.keys[e.code] = true; |
|
|
if (e.code === 'Space') { |
|
|
e.preventDefault(); |
|
|
if (!this.gameRunning) { |
|
|
this.start(); |
|
|
} |
|
|
} |
|
|
}); |
|
|
|
|
|
document.addEventListener('keyup', (e) => { |
|
|
this.keys[e.code] = false; |
|
|
}); |
|
|
|
|
|
document.getElementById('restartButton').addEventListener('click', () => { |
|
|
this.restart(); |
|
|
}); |
|
|
|
|
|
|
|
|
canvas.addEventListener('click', () => { |
|
|
if (!audioContext) { |
|
|
initAudio(); |
|
|
} |
|
|
if (!this.gameRunning) { |
|
|
this.start(); |
|
|
} |
|
|
}); |
|
|
} |
|
|
|
|
|
start() { |
|
|
if (!audioContext) { |
|
|
initAudio(); |
|
|
} |
|
|
this.gameRunning = true; |
|
|
gameOverDiv.style.display = 'none'; |
|
|
this.gameLoop(); |
|
|
} |
|
|
|
|
|
restart() { |
|
|
this.player.x = 200; |
|
|
this.player.y = 500; |
|
|
this.player.vx = 0; |
|
|
this.player.vy = 0; |
|
|
this.player.onGround = false; |
|
|
this.player.lastJumpTime = 0; |
|
|
this.camera.y = 0; |
|
|
this.depth = 0; |
|
|
this.score = 0; |
|
|
this.particles = []; |
|
|
this.bubbles = []; |
|
|
this.seaCreatures = []; |
|
|
this.snake = null; |
|
|
this.lastCreatureSpawn = 0; |
|
|
this.platforms = []; |
|
|
this.generateInitialPlatforms(); |
|
|
this.start(); |
|
|
} |
|
|
|
|
|
update() { |
|
|
if (!this.gameRunning) return; |
|
|
|
|
|
|
|
|
if (this.keys['ArrowLeft'] || this.keys['KeyA']) { |
|
|
this.player.vx = -this.moveSpeed; |
|
|
} |
|
|
if (this.keys['ArrowRight'] || this.keys['KeyD']) { |
|
|
this.player.vx = this.moveSpeed; |
|
|
} |
|
|
|
|
|
|
|
|
this.player.vx *= 0.8; |
|
|
|
|
|
|
|
|
this.player.vy += this.gravity; |
|
|
|
|
|
|
|
|
this.player.x += this.player.vx; |
|
|
this.player.y += this.player.vy; |
|
|
|
|
|
|
|
|
if (this.player.x < 0) this.player.x = canvas.width; |
|
|
if (this.player.x > canvas.width) this.player.x = 0; |
|
|
|
|
|
|
|
|
this.player.onGround = false; |
|
|
for (let platform of this.platforms) { |
|
|
if (this.player.x < platform.x + platform.width && |
|
|
this.player.x + this.player.width > platform.x && |
|
|
this.player.y < platform.y + platform.height && |
|
|
this.player.y + this.player.height > platform.y) { |
|
|
|
|
|
if (this.player.vy > 0 && this.player.y < platform.y) { |
|
|
this.player.y = platform.y - this.player.height; |
|
|
this.player.vy = 0; |
|
|
this.player.onGround = true; |
|
|
|
|
|
|
|
|
this.createParticles(this.player.x + this.player.width/2, this.player.y + this.player.height); |
|
|
|
|
|
if (sounds.land) sounds.land(); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if ((this.keys['Space'] || this.keys['ArrowUp'] || this.keys['KeyW']) && this.player.onGround) { |
|
|
this.player.vy = this.jumpPower; |
|
|
this.player.onGround = false; |
|
|
this.player.lastJumpTime = Date.now(); |
|
|
if (sounds.jump) sounds.jump(); |
|
|
|
|
|
|
|
|
this.createParticles(this.player.x + this.player.width/2, this.player.y + this.player.height); |
|
|
} |
|
|
|
|
|
|
|
|
if (Date.now() - this.lastCreatureSpawn > 2000 + Math.random() * 3000) { |
|
|
this.spawnSeaCreature(); |
|
|
this.lastCreatureSpawn = Date.now(); |
|
|
} |
|
|
|
|
|
|
|
|
if (this.score > 0 && this.score % 100 === 0 && !this.snake && this.score !== this.lastSnakeSpawn) { |
|
|
this.spawnSnake(); |
|
|
this.lastSnakeSpawn = this.score; |
|
|
} |
|
|
|
|
|
|
|
|
this.seaCreatures = this.seaCreatures.filter(creature => { |
|
|
creature.x += creature.vx; |
|
|
creature.y += creature.vy; |
|
|
creature.angle += 0.05; |
|
|
|
|
|
|
|
|
if (Math.random() < 0.02) { |
|
|
creature.vx += (Math.random() - 0.5) * 0.5; |
|
|
creature.vy += (Math.random() - 0.5) * 0.5; |
|
|
} |
|
|
|
|
|
|
|
|
if (creature.x < 0 || creature.x > canvas.width) creature.vx *= -1; |
|
|
|
|
|
creature.life--; |
|
|
return creature.life > 0 && creature.y > this.camera.y - 100 && creature.y < this.camera.y + canvas.height + 100; |
|
|
}); |
|
|
|
|
|
|
|
|
if (this.snake) { |
|
|
|
|
|
const dx = this.player.x - this.snake.x; |
|
|
const dy = this.player.y - this.snake.y; |
|
|
const distance = Math.sqrt(dx * dx + dy * dy); |
|
|
|
|
|
|
|
|
this.snake.targetX = this.player.x; |
|
|
this.snake.targetY = this.player.y; |
|
|
|
|
|
const targetDx = this.snake.targetX - this.snake.x; |
|
|
const targetDy = this.snake.targetY - this.snake.y; |
|
|
const targetDistance = Math.sqrt(targetDx * targetDx + targetDy * targetDy); |
|
|
|
|
|
if (targetDistance > 5) { |
|
|
this.snake.vx = (targetDx / targetDistance) * this.snake.speed; |
|
|
this.snake.vy = (targetDy / targetDistance) * this.snake.speed; |
|
|
} |
|
|
|
|
|
this.snake.x += this.snake.vx; |
|
|
this.snake.y += this.snake.vy; |
|
|
|
|
|
|
|
|
for (let i = this.snake.segments.length - 1; i > 0; i--) { |
|
|
const segment = this.snake.segments[i]; |
|
|
const prevSegment = this.snake.segments[i - 1]; |
|
|
|
|
|
const segDx = prevSegment.x - segment.x; |
|
|
const segDy = prevSegment.y - segment.y; |
|
|
const segDistance = Math.sqrt(segDx * segDx + segDy * segDy); |
|
|
|
|
|
if (segDistance > 15) { |
|
|
segment.x = prevSegment.x - (segDx / segDistance) * 15; |
|
|
segment.y = prevSegment.y - (segDy / segDistance) * 15; |
|
|
} |
|
|
|
|
|
segment.angle = Math.atan2(segDy, segDx); |
|
|
} |
|
|
|
|
|
|
|
|
this.snake.segments[0].x = this.snake.x; |
|
|
this.snake.segments[0].y = this.snake.y; |
|
|
this.snake.segments[0].angle = Math.atan2(this.snake.vy, this.snake.vx); |
|
|
|
|
|
|
|
|
const timeSinceLastJump = Date.now() - this.player.lastJumpTime; |
|
|
if (this.player.onGround && timeSinceLastJump > 4000) { |
|
|
|
|
|
if (distance < 40) { |
|
|
this.gameOver("The sea snake caught you! Keep moving!"); |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (this.snake.y < this.camera.y - 300) { |
|
|
this.snake = null; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
let targetCameraY = this.player.y - canvas.height/2; |
|
|
this.camera.y += (targetCameraY - this.camera.y) * 0.1; |
|
|
|
|
|
|
|
|
this.depth = Math.max(0, Math.floor((this.player.y - 500) / 10)); |
|
|
this.score = this.depth; |
|
|
|
|
|
|
|
|
if (this.player.y > this.platforms[this.platforms.length - 1].y - 500) { |
|
|
for (let i = 0; i < 10; i++) { |
|
|
let lastY = this.platforms[this.platforms.length - 1].y; |
|
|
this.platforms.push({ |
|
|
x: Math.random() * (canvas.width - 80), |
|
|
y: lastY + 80 + Math.random() * 40, |
|
|
width: 80 + Math.random() * 40, |
|
|
height: 12, |
|
|
color: this.getPlatformColor(lastY + 80) |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
this.particles = this.particles.filter(particle => { |
|
|
particle.x += particle.vx; |
|
|
particle.y += particle.vy; |
|
|
particle.vy += 0.2; |
|
|
particle.life--; |
|
|
return particle.life > 0; |
|
|
}); |
|
|
|
|
|
|
|
|
this.bubbles = this.bubbles.filter(bubble => { |
|
|
bubble.y -= bubble.speed; |
|
|
bubble.x += Math.sin(bubble.y * 0.01) * 0.5; |
|
|
return bubble.y > this.camera.y - 100; |
|
|
}); |
|
|
|
|
|
|
|
|
if (Math.random() < 0.1) { |
|
|
this.bubbles.push({ |
|
|
x: Math.random() * canvas.width, |
|
|
y: this.camera.y + canvas.height + 20, |
|
|
size: 3 + Math.random() * 8, |
|
|
speed: 1 + Math.random() * 2 |
|
|
}); |
|
|
} |
|
|
|
|
|
|
|
|
if (this.player.y > this.camera.y + canvas.height + 100) { |
|
|
this.gameOver("You fell into the abyss!"); |
|
|
} |
|
|
|
|
|
|
|
|
document.getElementById('depth').textContent = this.depth; |
|
|
document.getElementById('score').textContent = this.score; |
|
|
} |
|
|
|
|
|
createParticles(x, y) { |
|
|
for (let i = 0; i < 5; i++) { |
|
|
this.particles.push({ |
|
|
x: x + (Math.random() - 0.5) * 20, |
|
|
y: y + (Math.random() - 0.5) * 10, |
|
|
vx: (Math.random() - 0.5) * 6, |
|
|
vy: (Math.random() - 0.5) * 6, |
|
|
life: 20 + Math.random() * 20, |
|
|
color: `hsl(${180 + Math.random() * 60}, 70%, 60%)` |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
render() { |
|
|
|
|
|
const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height); |
|
|
let depthRatio = Math.min(this.depth / 1000, 1); |
|
|
gradient.addColorStop(0, `hsl(200, 60%, ${80 - depthRatio * 30}%)`); |
|
|
gradient.addColorStop(1, `hsl(220, 80%, ${20 - depthRatio * 15}%)`); |
|
|
|
|
|
ctx.fillStyle = gradient; |
|
|
ctx.fillRect(0, 0, canvas.width, canvas.height); |
|
|
|
|
|
ctx.save(); |
|
|
ctx.translate(0, -this.camera.y); |
|
|
|
|
|
|
|
|
ctx.globalAlpha = 0.6; |
|
|
for (let bubble of this.bubbles) { |
|
|
ctx.fillStyle = 'rgba(255, 255, 255, 0.3)'; |
|
|
ctx.beginPath(); |
|
|
ctx.arc(bubble.x, bubble.y, bubble.size, 0, Math.PI * 2); |
|
|
ctx.fill(); |
|
|
} |
|
|
ctx.globalAlpha = 1; |
|
|
|
|
|
|
|
|
for (let platform of this.platforms) { |
|
|
if (platform.y > this.camera.y - 50 && platform.y < this.camera.y + canvas.height + 50) { |
|
|
ctx.fillStyle = platform.color; |
|
|
ctx.fillRect(platform.x, platform.y, platform.width, platform.height); |
|
|
|
|
|
|
|
|
ctx.fillStyle = 'rgba(255, 255, 255, 0.3)'; |
|
|
ctx.fillRect(platform.x, platform.y, platform.width, 3); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for (let particle of this.particles) { |
|
|
ctx.fillStyle = particle.color; |
|
|
ctx.globalAlpha = particle.life / 40; |
|
|
ctx.fillRect(particle.x, particle.y, 3, 3); |
|
|
} |
|
|
ctx.globalAlpha = 1; |
|
|
|
|
|
|
|
|
ctx.fillStyle = this.player.color; |
|
|
ctx.fillRect(this.player.x, this.player.y, this.player.width, this.player.height); |
|
|
|
|
|
|
|
|
ctx.fillStyle = 'rgba(255, 255, 255, 0.4)'; |
|
|
ctx.fillRect(this.player.x, this.player.y, this.player.width, 5); |
|
|
|
|
|
ctx.restore(); |
|
|
} |
|
|
|
|
|
gameOver() { |
|
|
this.gameRunning = false; |
|
|
document.getElementById('finalDepth').textContent = this.depth; |
|
|
document.getElementById('finalScore').textContent = this.score; |
|
|
gameOverDiv.style.display = 'block'; |
|
|
} |
|
|
|
|
|
gameLoop() { |
|
|
if (this.gameRunning) { |
|
|
this.update(); |
|
|
this.render(); |
|
|
requestAnimationFrame(() => this.gameLoop()); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const game = new Game(); |
|
|
|
|
|
|
|
|
ctx.fillStyle = 'white'; |
|
|
ctx.font = '24px Arial'; |
|
|
ctx.textAlign = 'center'; |
|
|
ctx.fillText('Deep Sea Jumper', canvas.width/2, canvas.height/2 - 50); |
|
|
ctx.font = '16px Arial'; |
|
|
ctx.fillText('Click or Press SPACE to Start', canvas.width/2, canvas.height/2); |
|
|
ctx.fillText('Dive as deep as you can!', canvas.width/2, canvas.height/2 + 30); |
|
|
</script> |
|
|
</body> |
|
|
</html> |