offerpk3 commited on
Commit
c0efcd9
·
verified ·
1 Parent(s): c8f7277

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +654 -19
index.html CHANGED
@@ -1,19 +1,654 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Deep Sea Jumper</title>
7
+ <style>
8
+ body {
9
+ margin: 0;
10
+ padding: 0;
11
+ background: linear-gradient(180deg, #87CEEB 0%, #4682B4 50%, #191970 100%);
12
+ font-family: 'Arial', sans-serif;
13
+ overflow: hidden;
14
+ display: flex;
15
+ justify-content: center;
16
+ align-items: center;
17
+ min-height: 100vh;
18
+ }
19
+
20
+ #gameContainer {
21
+ position: relative;
22
+ width: 400px;
23
+ height: 600px;
24
+ background: linear-gradient(180deg, #87CEEB 0%, #4682B4 30%, #191970 70%, #000080 100%);
25
+ border: 3px solid #2F4F4F;
26
+ border-radius: 10px;
27
+ overflow: hidden;
28
+ box-shadow: 0 0 30px rgba(0, 100, 200, 0.5);
29
+ }
30
+
31
+ #gameCanvas {
32
+ width: 100%;
33
+ height: 100%;
34
+ display: block;
35
+ }
36
+
37
+ #ui {
38
+ position: absolute;
39
+ top: 10px;
40
+ left: 10px;
41
+ color: white;
42
+ font-size: 18px;
43
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.8);
44
+ z-index: 10;
45
+ }
46
+
47
+ #gameOver {
48
+ position: absolute;
49
+ top: 50%;
50
+ left: 50%;
51
+ transform: translate(-50%, -50%);
52
+ background: rgba(0, 0, 0, 0.8);
53
+ color: white;
54
+ padding: 30px;
55
+ border-radius: 15px;
56
+ text-align: center;
57
+ display: none;
58
+ z-index: 20;
59
+ }
60
+
61
+ #startButton, #restartButton {
62
+ background: linear-gradient(45deg, #FF6B6B, #FF8E8E);
63
+ color: white;
64
+ border: none;
65
+ padding: 12px 24px;
66
+ font-size: 16px;
67
+ border-radius: 25px;
68
+ cursor: pointer;
69
+ margin-top: 15px;
70
+ transition: all 0.3s ease;
71
+ }
72
+
73
+ #startButton:hover, #restartButton:hover {
74
+ transform: scale(1.05);
75
+ box-shadow: 0 5px 15px rgba(255, 107, 107, 0.4);
76
+ }
77
+
78
+ .bubble {
79
+ position: absolute;
80
+ background: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.3));
81
+ border-radius: 50%;
82
+ animation: float 3s ease-in-out infinite;
83
+ }
84
+
85
+ @keyframes float {
86
+ 0%, 100% { transform: translateY(0px) rotate(0deg); }
87
+ 50% { transform: translateY(-20px) rotate(180deg); }
88
+ }
89
+
90
+ #instructions {
91
+ position: absolute;
92
+ bottom: 10px;
93
+ left: 50%;
94
+ transform: translateX(-50%);
95
+ color: rgba(255, 255, 255, 0.8);
96
+ font-size: 12px;
97
+ text-align: center;
98
+ }
99
+ </style>
100
+ </head>
101
+ <body>
102
+ <div id="gameContainer">
103
+ <canvas id="gameCanvas" width="400" height="600"></canvas>
104
+ <div id="ui">
105
+ <div>Depth: <span id="depth">0</span>m</div>
106
+ <div>Score: <span id="score">0</span></div>
107
+ </div>
108
+ <div id="gameOver">
109
+ <h2>Game Over!</h2>
110
+ <p>Final Depth: <span id="finalDepth">0</span>m</p>
111
+ <p>Final Score: <span id="finalScore">0</span></p>
112
+ <button id="restartButton">Dive Again</button>
113
+ </div>
114
+ <div id="instructions">
115
+ Use ARROW KEYS or A/D to move<br>
116
+ Space to jump higher
117
+ </div>
118
+ </div>
119
+
120
+ <script>
121
+ const canvas = document.getElementById('gameCanvas');
122
+ const ctx = canvas.getContext('2d');
123
+ const gameOverDiv = document.getElementById('gameOver');
124
+
125
+ // Audio context for sound effects
126
+ let audioContext;
127
+ let sounds = {};
128
+
129
+ function initAudio() {
130
+ audioContext = new (window.AudioContext || window.webkitAudioContext)();
131
+
132
+ // Create jump sound
133
+ sounds.jump = createSound(300, 0.1, 'sine');
134
+ sounds.land = createSound(150, 0.15, 'square');
135
+ sounds.ambient = createAmbientSound();
136
+ }
137
+
138
+ function createSound(frequency, duration, type = 'sine') {
139
+ return function() {
140
+ if (!audioContext) return;
141
+ const oscillator = audioContext.createOscillator();
142
+ const gainNode = audioContext.createGain();
143
+
144
+ oscillator.connect(gainNode);
145
+ gainNode.connect(audioContext.destination);
146
+
147
+ oscillator.frequency.setValueAtTime(frequency, audioContext.currentTime);
148
+ oscillator.type = type;
149
+
150
+ gainNode.gain.setValueAtTime(0.1, audioContext.currentTime);
151
+ gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + duration);
152
+
153
+ oscillator.start(audioContext.currentTime);
154
+ oscillator.stop(audioContext.currentTime + duration);
155
+ };
156
+ }
157
+
158
+ function createAmbientSound() {
159
+ return function() {
160
+ if (!audioContext) return;
161
+ const oscillator = audioContext.createOscillator();
162
+ const gainNode = audioContext.createGain();
163
+
164
+ oscillator.connect(gainNode);
165
+ gainNode.connect(audioContext.destination);
166
+
167
+ oscillator.frequency.setValueAtTime(60, audioContext.currentTime);
168
+ oscillator.type = 'sine';
169
+
170
+ gainNode.gain.setValueAtTime(0.02, audioContext.currentTime);
171
+
172
+ oscillator.start(audioContext.currentTime);
173
+ oscillator.stop(audioContext.currentTime + 0.5);
174
+ };
175
+ }
176
+
177
+ class Game {
178
+ constructor() {
179
+ this.player = {
180
+ x: 200,
181
+ y: 500,
182
+ width: 20,
183
+ height: 20,
184
+ vx: 0,
185
+ vy: 0,
186
+ onGround: false,
187
+ color: '#FF6B6B',
188
+ lastJumpTime: 0
189
+ };
190
+
191
+ this.platforms = [];
192
+ this.camera = { y: 0 };
193
+ this.depth = 0;
194
+ this.score = 0;
195
+ this.gameRunning = false;
196
+ this.keys = {};
197
+ this.particles = [];
198
+ this.bubbles = [];
199
+ this.seaCreatures = [];
200
+ this.snake = null;
201
+ this.lastCreatureSpawn = 0;
202
+
203
+ this.gravity = 0.5;
204
+ this.jumpPower = -12;
205
+ this.moveSpeed = 5;
206
+
207
+ this.generateInitialPlatforms();
208
+ this.setupEventListeners();
209
+ }
210
+
211
+ generateInitialPlatforms() {
212
+ // Starting platform
213
+ this.platforms.push({
214
+ x: 150,
215
+ y: 550,
216
+ width: 100,
217
+ height: 15,
218
+ color: '#8FBC8F'
219
+ });
220
+
221
+ // Generate platforms going down
222
+ for (let i = 1; i < 50; i++) {
223
+ this.platforms.push({
224
+ x: Math.random() * (canvas.width - 80),
225
+ y: 550 + i * 80,
226
+ width: 80 + Math.random() * 40,
227
+ height: 12,
228
+ color: this.getPlatformColor(i * 80)
229
+ });
230
+ }
231
+ }
232
+
233
+ getPlatformColor(depth) {
234
+ if (depth < 200) return '#8FBC8F'; // Light green
235
+ if (depth < 500) return '#20B2AA'; // Light sea green
236
+ if (depth < 1000) return '#4682B4'; // Steel blue
237
+ if (depth < 1500) return '#483D8B'; // Dark slate blue
238
+ return '#2F4F4F'; // Dark slate gray
239
+ }
240
+
241
+ getSeaCreatureType(depth) {
242
+ if (depth < 200) return { type: 'fish', color: '#FFD700', size: 15 };
243
+ if (depth < 400) return { type: 'jellyfish', color: '#FF69B4', size: 20 };
244
+ if (depth < 600) return { type: 'octopus', color: '#8A2BE2', size: 25 };
245
+ if (depth < 800) return { type: 'shark', color: '#708090', size: 30 };
246
+ if (depth < 1000) return { type: 'whale', color: '#4169E1', size: 40 };
247
+ return { type: 'anglerfish', color: '#32CD32', size: 35 };
248
+ }
249
+
250
+ spawnSeaCreature() {
251
+ const creatureInfo = this.getSeaCreatureType(this.depth);
252
+ const creature = {
253
+ x: Math.random() * canvas.width,
254
+ y: this.camera.y + Math.random() * canvas.height,
255
+ vx: (Math.random() - 0.5) * 3,
256
+ vy: (Math.random() - 0.5) * 2,
257
+ type: creatureInfo.type,
258
+ color: creatureInfo.color,
259
+ size: creatureInfo.size,
260
+ angle: Math.random() * Math.PI * 2,
261
+ life: 300 + Math.random() * 200
262
+ };
263
+ this.seaCreatures.push(creature);
264
+ }
265
+
266
+ spawnSnake() {
267
+ if (this.snake) return; // Only one snake at a time
268
+
269
+ this.snake = {
270
+ x: Math.random() * canvas.width,
271
+ y: this.player.y + 200, // Start below player
272
+ vx: 0,
273
+ vy: 0,
274
+ speed: 2.5,
275
+ size: 25,
276
+ color: '#8B0000',
277
+ segments: [],
278
+ targetX: this.player.x,
279
+ targetY: this.player.y
280
+ };
281
+
282
+ // Create snake segments
283
+ for (let i = 0; i < 8; i++) {
284
+ this.snake.segments.push({
285
+ x: this.snake.x - i * 15,
286
+ y: this.snake.y,
287
+ angle: 0
288
+ });
289
+ }
290
+ }
291
+
292
+ setupEventListeners() {
293
+ document.addEventListener('keydown', (e) => {
294
+ this.keys[e.code] = true;
295
+ if (e.code === 'Space') {
296
+ e.preventDefault();
297
+ if (!this.gameRunning) {
298
+ this.start();
299
+ }
300
+ }
301
+ });
302
+
303
+ document.addEventListener('keyup', (e) => {
304
+ this.keys[e.code] = false;
305
+ });
306
+
307
+ document.getElementById('restartButton').addEventListener('click', () => {
308
+ this.restart();
309
+ });
310
+
311
+ // Start game on first interaction
312
+ canvas.addEventListener('click', () => {
313
+ if (!audioContext) {
314
+ initAudio();
315
+ }
316
+ if (!this.gameRunning) {
317
+ this.start();
318
+ }
319
+ });
320
+ }
321
+
322
+ start() {
323
+ if (!audioContext) {
324
+ initAudio();
325
+ }
326
+ this.gameRunning = true;
327
+ gameOverDiv.style.display = 'none';
328
+ this.gameLoop();
329
+ }
330
+
331
+ restart() {
332
+ this.player.x = 200;
333
+ this.player.y = 500;
334
+ this.player.vx = 0;
335
+ this.player.vy = 0;
336
+ this.player.onGround = false;
337
+ this.player.lastJumpTime = 0;
338
+ this.camera.y = 0;
339
+ this.depth = 0;
340
+ this.score = 0;
341
+ this.particles = [];
342
+ this.bubbles = [];
343
+ this.seaCreatures = [];
344
+ this.snake = null;
345
+ this.lastCreatureSpawn = 0;
346
+ this.platforms = [];
347
+ this.generateInitialPlatforms();
348
+ this.start();
349
+ }
350
+
351
+ update() {
352
+ if (!this.gameRunning) return;
353
+
354
+ // Player movement
355
+ if (this.keys['ArrowLeft'] || this.keys['KeyA']) {
356
+ this.player.vx = -this.moveSpeed;
357
+ }
358
+ if (this.keys['ArrowRight'] || this.keys['KeyD']) {
359
+ this.player.vx = this.moveSpeed;
360
+ }
361
+
362
+ // Friction
363
+ this.player.vx *= 0.8;
364
+
365
+ // Gravity
366
+ this.player.vy += this.gravity;
367
+
368
+ // Update position
369
+ this.player.x += this.player.vx;
370
+ this.player.y += this.player.vy;
371
+
372
+ // Screen wrapping
373
+ if (this.player.x < 0) this.player.x = canvas.width;
374
+ if (this.player.x > canvas.width) this.player.x = 0;
375
+
376
+ // Platform collision
377
+ this.player.onGround = false;
378
+ for (let platform of this.platforms) {
379
+ if (this.player.x < platform.x + platform.width &&
380
+ this.player.x + this.player.width > platform.x &&
381
+ this.player.y < platform.y + platform.height &&
382
+ this.player.y + this.player.height > platform.y) {
383
+
384
+ if (this.player.vy > 0 && this.player.y < platform.y) {
385
+ this.player.y = platform.y - this.player.height;
386
+ this.player.vy = 0;
387
+ this.player.onGround = true;
388
+
389
+ // Create landing particles
390
+ this.createParticles(this.player.x + this.player.width/2, this.player.y + this.player.height);
391
+
392
+ if (sounds.land) sounds.land();
393
+ }
394
+ }
395
+ }
396
+
397
+ // Jumping
398
+ if ((this.keys['Space'] || this.keys['ArrowUp'] || this.keys['KeyW']) && this.player.onGround) {
399
+ this.player.vy = this.jumpPower;
400
+ this.player.onGround = false;
401
+ this.player.lastJumpTime = Date.now();
402
+ if (sounds.jump) sounds.jump();
403
+
404
+ // Create jump particles
405
+ this.createParticles(this.player.x + this.player.width/2, this.player.y + this.player.height);
406
+ }
407
+
408
+ // Spawn sea creatures every few seconds
409
+ if (Date.now() - this.lastCreatureSpawn > 2000 + Math.random() * 3000) {
410
+ this.spawnSeaCreature();
411
+ this.lastCreatureSpawn = Date.now();
412
+ }
413
+
414
+ // Spawn snake every 100 score points
415
+ if (this.score > 0 && this.score % 100 === 0 && !this.snake && this.score !== this.lastSnakeSpawn) {
416
+ this.spawnSnake();
417
+ this.lastSnakeSpawn = this.score;
418
+ }
419
+
420
+ // Update sea creatures
421
+ this.seaCreatures = this.seaCreatures.filter(creature => {
422
+ creature.x += creature.vx;
423
+ creature.y += creature.vy;
424
+ creature.angle += 0.05;
425
+
426
+ // Random direction changes
427
+ if (Math.random() < 0.02) {
428
+ creature.vx += (Math.random() - 0.5) * 0.5;
429
+ creature.vy += (Math.random() - 0.5) * 0.5;
430
+ }
431
+
432
+ // Keep creatures in bounds
433
+ if (creature.x < 0 || creature.x > canvas.width) creature.vx *= -1;
434
+
435
+ creature.life--;
436
+ return creature.life > 0 && creature.y > this.camera.y - 100 && creature.y < this.camera.y + canvas.height + 100;
437
+ });
438
+
439
+ // Update snake
440
+ if (this.snake) {
441
+ // Calculate distance to player
442
+ const dx = this.player.x - this.snake.x;
443
+ const dy = this.player.y - this.snake.y;
444
+ const distance = Math.sqrt(dx * dx + dy * dy);
445
+
446
+ // Move towards player (slower than player)
447
+ this.snake.targetX = this.player.x;
448
+ this.snake.targetY = this.player.y;
449
+
450
+ const targetDx = this.snake.targetX - this.snake.x;
451
+ const targetDy = this.snake.targetY - this.snake.y;
452
+ const targetDistance = Math.sqrt(targetDx * targetDx + targetDy * targetDy);
453
+
454
+ if (targetDistance > 5) {
455
+ this.snake.vx = (targetDx / targetDistance) * this.snake.speed;
456
+ this.snake.vy = (targetDy / targetDistance) * this.snake.speed;
457
+ }
458
+
459
+ this.snake.x += this.snake.vx;
460
+ this.snake.y += this.snake.vy;
461
+
462
+ // Update snake segments
463
+ for (let i = this.snake.segments.length - 1; i > 0; i--) {
464
+ const segment = this.snake.segments[i];
465
+ const prevSegment = this.snake.segments[i - 1];
466
+
467
+ const segDx = prevSegment.x - segment.x;
468
+ const segDy = prevSegment.y - segment.y;
469
+ const segDistance = Math.sqrt(segDx * segDx + segDy * segDy);
470
+
471
+ if (segDistance > 15) {
472
+ segment.x = prevSegment.x - (segDx / segDistance) * 15;
473
+ segment.y = prevSegment.y - (segDy / segDistance) * 15;
474
+ }
475
+
476
+ segment.angle = Math.atan2(segDy, segDx);
477
+ }
478
+
479
+ // Update head segment
480
+ this.snake.segments[0].x = this.snake.x;
481
+ this.snake.segments[0].y = this.snake.y;
482
+ this.snake.segments[0].angle = Math.atan2(this.snake.vy, this.snake.vx);
483
+
484
+ // Check if player is idle too long
485
+ const timeSinceLastJump = Date.now() - this.player.lastJumpTime;
486
+ if (this.player.onGround && timeSinceLastJump > 4000) { // 4 seconds idle
487
+ // Check if snake is close enough to bite
488
+ if (distance < 40) {
489
+ this.gameOver("The sea snake caught you! Keep moving!");
490
+ return;
491
+ }
492
+ }
493
+
494
+ // Remove snake if too far from camera
495
+ if (this.snake.y < this.camera.y - 300) {
496
+ this.snake = null;
497
+ }
498
+ }
499
+
500
+ // Camera follows player
501
+ let targetCameraY = this.player.y - canvas.height/2;
502
+ this.camera.y += (targetCameraY - this.camera.y) * 0.1;
503
+
504
+ // Update depth and score
505
+ this.depth = Math.max(0, Math.floor((this.player.y - 500) / 10));
506
+ this.score = this.depth;
507
+
508
+ // Generate more platforms
509
+ if (this.player.y > this.platforms[this.platforms.length - 1].y - 500) {
510
+ for (let i = 0; i < 10; i++) {
511
+ let lastY = this.platforms[this.platforms.length - 1].y;
512
+ this.platforms.push({
513
+ x: Math.random() * (canvas.width - 80),
514
+ y: lastY + 80 + Math.random() * 40,
515
+ width: 80 + Math.random() * 40,
516
+ height: 12,
517
+ color: this.getPlatformColor(lastY + 80)
518
+ });
519
+ }
520
+ }
521
+
522
+ // Update particles
523
+ this.particles = this.particles.filter(particle => {
524
+ particle.x += particle.vx;
525
+ particle.y += particle.vy;
526
+ particle.vy += 0.2;
527
+ particle.life--;
528
+ return particle.life > 0;
529
+ });
530
+
531
+ // Update bubbles
532
+ this.bubbles = this.bubbles.filter(bubble => {
533
+ bubble.y -= bubble.speed;
534
+ bubble.x += Math.sin(bubble.y * 0.01) * 0.5;
535
+ return bubble.y > this.camera.y - 100;
536
+ });
537
+
538
+ // Add new bubbles
539
+ if (Math.random() < 0.1) {
540
+ this.bubbles.push({
541
+ x: Math.random() * canvas.width,
542
+ y: this.camera.y + canvas.height + 20,
543
+ size: 3 + Math.random() * 8,
544
+ speed: 1 + Math.random() * 2
545
+ });
546
+ }
547
+
548
+ // Check game over
549
+ if (this.player.y > this.camera.y + canvas.height + 100) {
550
+ this.gameOver("You fell into the abyss!");
551
+ }
552
+
553
+ // Update UI
554
+ document.getElementById('depth').textContent = this.depth;
555
+ document.getElementById('score').textContent = this.score;
556
+ }
557
+
558
+ createParticles(x, y) {
559
+ for (let i = 0; i < 5; i++) {
560
+ this.particles.push({
561
+ x: x + (Math.random() - 0.5) * 20,
562
+ y: y + (Math.random() - 0.5) * 10,
563
+ vx: (Math.random() - 0.5) * 6,
564
+ vy: (Math.random() - 0.5) * 6,
565
+ life: 20 + Math.random() * 20,
566
+ color: `hsl(${180 + Math.random() * 60}, 70%, 60%)`
567
+ });
568
+ }
569
+ }
570
+
571
+ render() {
572
+ // Clear canvas with gradient background
573
+ const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
574
+ let depthRatio = Math.min(this.depth / 1000, 1);
575
+ gradient.addColorStop(0, `hsl(200, 60%, ${80 - depthRatio * 30}%)`);
576
+ gradient.addColorStop(1, `hsl(220, 80%, ${20 - depthRatio * 15}%)`);
577
+
578
+ ctx.fillStyle = gradient;
579
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
580
+
581
+ ctx.save();
582
+ ctx.translate(0, -this.camera.y);
583
+
584
+ // Draw bubbles
585
+ ctx.globalAlpha = 0.6;
586
+ for (let bubble of this.bubbles) {
587
+ ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
588
+ ctx.beginPath();
589
+ ctx.arc(bubble.x, bubble.y, bubble.size, 0, Math.PI * 2);
590
+ ctx.fill();
591
+ }
592
+ ctx.globalAlpha = 1;
593
+
594
+ // Draw platforms
595
+ for (let platform of this.platforms) {
596
+ if (platform.y > this.camera.y - 50 && platform.y < this.camera.y + canvas.height + 50) {
597
+ ctx.fillStyle = platform.color;
598
+ ctx.fillRect(platform.x, platform.y, platform.width, platform.height);
599
+
600
+ // Platform highlight
601
+ ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
602
+ ctx.fillRect(platform.x, platform.y, platform.width, 3);
603
+ }
604
+ }
605
+
606
+ // Draw particles
607
+ for (let particle of this.particles) {
608
+ ctx.fillStyle = particle.color;
609
+ ctx.globalAlpha = particle.life / 40;
610
+ ctx.fillRect(particle.x, particle.y, 3, 3);
611
+ }
612
+ ctx.globalAlpha = 1;
613
+
614
+ // Draw player
615
+ ctx.fillStyle = this.player.color;
616
+ ctx.fillRect(this.player.x, this.player.y, this.player.width, this.player.height);
617
+
618
+ // Player highlight
619
+ ctx.fillStyle = 'rgba(255, 255, 255, 0.4)';
620
+ ctx.fillRect(this.player.x, this.player.y, this.player.width, 5);
621
+
622
+ ctx.restore();
623
+ }
624
+
625
+ gameOver() {
626
+ this.gameRunning = false;
627
+ document.getElementById('finalDepth').textContent = this.depth;
628
+ document.getElementById('finalScore').textContent = this.score;
629
+ gameOverDiv.style.display = 'block';
630
+ }
631
+
632
+ gameLoop() {
633
+ if (this.gameRunning) {
634
+ this.update();
635
+ this.render();
636
+ requestAnimationFrame(() => this.gameLoop());
637
+ }
638
+ }
639
+ }
640
+
641
+ // Initialize game
642
+ const game = new Game();
643
+
644
+ // Start message
645
+ ctx.fillStyle = 'white';
646
+ ctx.font = '24px Arial';
647
+ ctx.textAlign = 'center';
648
+ ctx.fillText('Deep Sea Jumper', canvas.width/2, canvas.height/2 - 50);
649
+ ctx.font = '16px Arial';
650
+ ctx.fillText('Click or Press SPACE to Start', canvas.width/2, canvas.height/2);
651
+ ctx.fillText('Dive as deep as you can!', canvas.width/2, canvas.height/2 + 30);
652
+ </script>
653
+ </body>
654
+ </html>