andreaschandra commited on
Commit
7cdee6b
·
verified ·
1 Parent(s): 93c3b14

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +582 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Cybernetic Pong X
3
- emoji: 🐢
4
  colorFrom: blue
5
- colorTo: purple
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: cybernetic-pong-x
3
+ emoji: 🐳
4
  colorFrom: blue
5
+ colorTo: gray
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,582 @@
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>Cybernetic Pong X</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script>
9
+ <style>
10
+ @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');
11
+
12
+ body {
13
+ font-family: 'Orbitron', sans-serif;
14
+ background-color: #0a0a1a;
15
+ overflow: hidden;
16
+ color: #00fffc;
17
+ }
18
+
19
+ #gameCanvas {
20
+ background-color: #000022;
21
+ border: 2px solid #00fffc;
22
+ box-shadow: 0 0 20px #00fffc, inset 0 0 20px #00fffc;
23
+ }
24
+
25
+ .particle {
26
+ position: absolute;
27
+ border-radius: 50%;
28
+ pointer-events: none;
29
+ }
30
+
31
+ .glow-text {
32
+ text-shadow: 0 0 10px #00fffc, 0 0 20px #00fffc;
33
+ }
34
+
35
+ .cyber-btn {
36
+ background: linear-gradient(45deg, #00fffc, #0088ff);
37
+ border: none;
38
+ color: #000;
39
+ font-weight: bold;
40
+ transition: all 0.3s;
41
+ box-shadow: 0 0 15px #00fffc;
42
+ }
43
+
44
+ .cyber-btn:hover {
45
+ transform: scale(1.05);
46
+ box-shadow: 0 0 25px #00fffc;
47
+ }
48
+
49
+ .grid-overlay {
50
+ position: absolute;
51
+ top: 0;
52
+ left: 0;
53
+ width: 100%;
54
+ height: 100%;
55
+ background:
56
+ linear-gradient(rgba(0, 255, 252, 0.1) 1px, transparent 1px),
57
+ linear-gradient(90deg, rgba(0, 255, 252, 0.1) 1px, transparent 1px);
58
+ background-size: 30px 30px;
59
+ pointer-events: none;
60
+ }
61
+
62
+ .score-display {
63
+ background: rgba(0, 20, 40, 0.7);
64
+ border: 2px solid #00fffc;
65
+ box-shadow: 0 0 15px #00fffc;
66
+ }
67
+ </style>
68
+ </head>
69
+ <body class="flex flex-col items-center justify-center min-h-screen">
70
+ <div class="grid-overlay"></div>
71
+
72
+ <h1 class="text-5xl font-bold mb-6 glow-text">CYBERNETIC PONG X</h1>
73
+
74
+ <div class="relative">
75
+ <canvas id="gameCanvas" width="800" height="500" class="mb-4"></canvas>
76
+
77
+ <div id="playerScore" class="score-display absolute top-4 left-4 px-4 py-2 rounded-lg text-2xl font-bold">0</div>
78
+ <div id="aiScore" class="score-display absolute top-4 right-4 px-4 py-2 rounded-lg text-2xl font-bold">0</div>
79
+
80
+ <div id="startScreen" class="absolute inset-0 flex flex-col items-center justify-center bg-black bg-opacity-80">
81
+ <h2 class="text-4xl font-bold mb-8 glow-text">READY FOR CYBER COMBAT?</h2>
82
+ <button id="startBtn" class="cyber-btn px-8 py-3 rounded-full text-xl mb-4">
83
+ <i class="fas fa-play mr-2"></i> INITIATE
84
+ </button>
85
+ <div class="flex space-x-4">
86
+ <button id="easyBtn" class="cyber-btn px-4 py-2 rounded-full">EASY MODE</button>
87
+ <button id="mediumBtn" class="cyber-btn px-4 py-2 rounded-full">NORMAL MODE</button>
88
+ <button id="hardBtn" class="cyber-btn px-4 py-2 rounded-full">HACKER MODE</button>
89
+ </div>
90
+ </div>
91
+
92
+ <div id="gameOverScreen" class="absolute inset-0 hidden flex-col items-center justify-center bg-black bg-opacity-80">
93
+ <h2 id="gameOverText" class="text-4xl font-bold mb-8 glow-text"></h2>
94
+ <button id="restartBtn" class="cyber-btn px-8 py-3 rounded-full text-xl">
95
+ <i class="fas fa-redo mr-2"></i> REBOOT
96
+ </button>
97
+ </div>
98
+ </div>
99
+
100
+ <div class="flex space-x-8 mt-6">
101
+ <div class="flex items-center">
102
+ <i class="fas fa-keyboard text-2xl mr-2 glow-text"></i>
103
+ <span class="text-xl">W/S: Move Paddle</span>
104
+ </div>
105
+ <div class="flex items-center">
106
+ <i class="fas fa-bolt text-2xl mr-2 glow-text"></i>
107
+ <span class="text-xl">SPACE: Power Shot</span>
108
+ </div>
109
+ </div>
110
+
111
+ <script>
112
+ document.addEventListener('DOMContentLoaded', () => {
113
+ const canvas = document.getElementById('gameCanvas');
114
+ const ctx = canvas.getContext('2d');
115
+ const playerScoreDisplay = document.getElementById('playerScore');
116
+ const aiScoreDisplay = document.getElementById('aiScore');
117
+ const startScreen = document.getElementById('startScreen');
118
+ const gameOverScreen = document.getElementById('gameOverScreen');
119
+ const gameOverText = document.getElementById('gameOverText');
120
+ const startBtn = document.getElementById('startBtn');
121
+ const restartBtn = document.getElementById('restartBtn');
122
+ const easyBtn = document.getElementById('easyBtn');
123
+ const mediumBtn = document.getElementById('mediumBtn');
124
+ const hardBtn = document.getElementById('hardBtn');
125
+
126
+ // Game variables
127
+ let gameRunning = false;
128
+ let difficulty = 5; // Default medium difficulty
129
+ let playerScore = 0;
130
+ let aiScore = 0;
131
+ let powerCharge = 0;
132
+ let powerActive = false;
133
+
134
+ // Paddle and ball properties
135
+ const paddleWidth = 15;
136
+ const paddleHeight = 100;
137
+ const ballSize = 15;
138
+
139
+ let playerPaddle = {
140
+ x: 30,
141
+ y: canvas.height / 2 - paddleHeight / 2,
142
+ width: paddleWidth,
143
+ height: paddleHeight,
144
+ speed: 8,
145
+ dy: 0
146
+ };
147
+
148
+ let aiPaddle = {
149
+ x: canvas.width - 30 - paddleWidth,
150
+ y: canvas.height / 2 - paddleHeight / 2,
151
+ width: paddleWidth,
152
+ height: paddleHeight,
153
+ speed: difficulty,
154
+ dy: 0
155
+ };
156
+
157
+ let ball = {
158
+ x: canvas.width / 2,
159
+ y: canvas.height / 2,
160
+ width: ballSize,
161
+ height: ballSize,
162
+ dx: 5,
163
+ dy: 5,
164
+ speed: 5,
165
+ trail: []
166
+ };
167
+
168
+ // Particles for explosions
169
+ let particles = [];
170
+
171
+ // Event listeners
172
+ startBtn.addEventListener('click', startGame);
173
+ restartBtn.addEventListener('click', restartGame);
174
+ easyBtn.addEventListener('click', () => setDifficulty(3));
175
+ mediumBtn.addEventListener('click', () => setDifficulty(5));
176
+ hardBtn.addEventListener('click', () => setDifficulty(8));
177
+
178
+ document.addEventListener('keydown', keyDownHandler);
179
+ document.addEventListener('keyup', keyUpHandler);
180
+
181
+ function setDifficulty(level) {
182
+ difficulty = level;
183
+ aiPaddle.speed = level;
184
+
185
+ // Update active button style
186
+ [easyBtn, mediumBtn, hardBtn].forEach(btn => btn.classList.remove('bg-purple-600'));
187
+ if (level === 3) easyBtn.classList.add('bg-purple-600');
188
+ if (level === 5) mediumBtn.classList.add('bg-purple-600');
189
+ if (level === 8) hardBtn.classList.add('bg-purple-600');
190
+ }
191
+
192
+ function keyDownHandler(e) {
193
+ if (!gameRunning) return;
194
+
195
+ if (e.key === 'w' || e.key === 'W') {
196
+ playerPaddle.dy = -playerPaddle.speed;
197
+ } else if (e.key === 's' || e.key === 'S') {
198
+ playerPaddle.dy = playerPaddle.speed;
199
+ } else if (e.key === ' ' && powerCharge >= 100) {
200
+ activatePowerShot();
201
+ }
202
+ }
203
+
204
+ function keyUpHandler(e) {
205
+ if (e.key === 'w' || e.key === 'W' || e.key === 's' || e.key === 'S') {
206
+ playerPaddle.dy = 0;
207
+ }
208
+ }
209
+
210
+ function activatePowerShot() {
211
+ powerActive = true;
212
+ powerCharge = 0;
213
+
214
+ // Create particles for power activation
215
+ for (let i = 0; i < 30; i++) {
216
+ createParticle(
217
+ playerPaddle.x + playerPaddle.width,
218
+ playerPaddle.y + playerPaddle.height / 2,
219
+ '#00fffc',
220
+ true
221
+ );
222
+ }
223
+
224
+ // Ball gets super speed temporarily
225
+ ball.dx = 15 * Math.sign(ball.dx);
226
+ ball.dy = 15 * Math.sign(ball.dy);
227
+
228
+ setTimeout(() => {
229
+ powerActive = false;
230
+ ball.dx = 5 * Math.sign(ball.dx);
231
+ ball.dy = 5 * Math.sign(ball.dy);
232
+ }, 1000);
233
+ }
234
+
235
+ function startGame() {
236
+ gameRunning = true;
237
+ startScreen.classList.add('hidden');
238
+ resetGame();
239
+ requestAnimationFrame(gameLoop);
240
+ }
241
+
242
+ function restartGame() {
243
+ gameOverScreen.classList.add('hidden');
244
+ playerScore = 0;
245
+ aiScore = 0;
246
+ updateScore();
247
+ resetGame();
248
+ requestAnimationFrame(gameLoop);
249
+ }
250
+
251
+ function resetGame() {
252
+ ball.x = canvas.width / 2;
253
+ ball.y = canvas.height / 2;
254
+ ball.dx = 5 * (Math.random() > 0.5 ? 1 : -1);
255
+ ball.dy = 5 * (Math.random() > 0.5 ? 1 : -1);
256
+ ball.trail = [];
257
+
258
+ playerPaddle.y = canvas.height / 2 - paddleHeight / 2;
259
+ aiPaddle.y = canvas.height / 2 - paddleHeight / 2;
260
+
261
+ powerCharge = 0;
262
+ powerActive = false;
263
+ }
264
+
265
+ function gameLoop() {
266
+ if (!gameRunning) return;
267
+
268
+ clearCanvas();
269
+ update();
270
+ draw();
271
+
272
+ requestAnimationFrame(gameLoop);
273
+ }
274
+
275
+ function clearCanvas() {
276
+ ctx.fillStyle = '#000022';
277
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
278
+
279
+ // Draw grid lines
280
+ ctx.strokeStyle = 'rgba(0, 255, 252, 0.1)';
281
+ ctx.lineWidth = 1;
282
+
283
+ // Vertical lines
284
+ for (let x = 0; x < canvas.width; x += 30) {
285
+ ctx.beginPath();
286
+ ctx.moveTo(x, 0);
287
+ ctx.lineTo(x, canvas.height);
288
+ ctx.stroke();
289
+ }
290
+
291
+ // Horizontal lines
292
+ for (let y = 0; y < canvas.height; y += 30) {
293
+ ctx.beginPath();
294
+ ctx.moveTo(0, y);
295
+ ctx.lineTo(canvas.width, y);
296
+ ctx.stroke();
297
+ }
298
+
299
+ // Center line
300
+ ctx.strokeStyle = 'rgba(0, 255, 252, 0.3)';
301
+ ctx.setLineDash([10, 10]);
302
+ ctx.beginPath();
303
+ ctx.moveTo(canvas.width / 2, 0);
304
+ ctx.lineTo(canvas.width / 2, canvas.height);
305
+ ctx.stroke();
306
+ ctx.setLineDash([]);
307
+ }
308
+
309
+ function update() {
310
+ // Update player paddle position
311
+ playerPaddle.y += playerPaddle.dy;
312
+
313
+ // Keep player paddle in bounds
314
+ if (playerPaddle.y < 0) {
315
+ playerPaddle.y = 0;
316
+ } else if (playerPaddle.y + playerPaddle.height > canvas.height) {
317
+ playerPaddle.y = canvas.height - playerPaddle.height;
318
+ }
319
+
320
+ // AI paddle follows ball with some imperfection
321
+ const aiPaddleCenter = aiPaddle.y + aiPaddle.height / 2;
322
+ const ballCenter = ball.y + ball.height / 2;
323
+
324
+ // Add some randomness to AI difficulty
325
+ const aiError = Math.random() * (difficulty * 5);
326
+
327
+ if (aiPaddleCenter < ballCenter - aiError) {
328
+ aiPaddle.dy = aiPaddle.speed;
329
+ } else if (aiPaddleCenter > ballCenter + aiError) {
330
+ aiPaddle.dy = -aiPaddle.speed;
331
+ } else {
332
+ aiPaddle.dy = 0;
333
+ }
334
+
335
+ aiPaddle.y += aiPaddle.dy;
336
+
337
+ // Keep AI paddle in bounds
338
+ if (aiPaddle.y < 0) {
339
+ aiPaddle.y = 0;
340
+ } else if (aiPaddle.y + aiPaddle.height > canvas.height) {
341
+ aiPaddle.y = canvas.height - aiPaddle.height;
342
+ }
343
+
344
+ // Update ball position
345
+ ball.x += ball.dx;
346
+ ball.y += ball.dy;
347
+
348
+ // Add current position to trail (for cool effect)
349
+ ball.trail.push({x: ball.x, y: ball.y});
350
+ if (ball.trail.length > 10) {
351
+ ball.trail.shift();
352
+ }
353
+
354
+ // Ball collision with top and bottom walls
355
+ if (ball.y < 0 || ball.y + ball.height > canvas.height) {
356
+ ball.dy = -ball.dy;
357
+ createImpactParticles(ball.x, ball.y);
358
+ }
359
+
360
+ // Ball collision with paddles
361
+ if (
362
+ ball.x < playerPaddle.x + playerPaddle.width &&
363
+ ball.x + ball.width > playerPaddle.x &&
364
+ ball.y < playerPaddle.y + playerPaddle.height &&
365
+ ball.y + ball.height > playerPaddle.y
366
+ ) {
367
+ // Calculate angle based on where ball hits paddle
368
+ const hitPosition = (ball.y - playerPaddle.y) / playerPaddle.height;
369
+ const angle = (hitPosition - 0.5) * Math.PI / 2;
370
+
371
+ ball.dx = Math.abs(ball.dx) + 0.2; // Increase speed slightly
372
+ ball.dy = Math.sin(angle) * ball.speed;
373
+
374
+ // Charge power on hit
375
+ powerCharge = Math.min(100, powerCharge + 20);
376
+
377
+ createImpactParticles(playerPaddle.x + playerPaddle.width, ball.y);
378
+ }
379
+
380
+ if (
381
+ ball.x < aiPaddle.x + aiPaddle.width &&
382
+ ball.x + ball.width > aiPaddle.x &&
383
+ ball.y < aiPaddle.y + aiPaddle.height &&
384
+ ball.y + ball.height > aiPaddle.y
385
+ ) {
386
+ // Calculate angle based on where ball hits paddle
387
+ const hitPosition = (ball.y - aiPaddle.y) / aiPaddle.height;
388
+ const angle = (hitPosition - 0.5) * Math.PI / 2;
389
+
390
+ ball.dx = -Math.abs(ball.dx) - 0.2; // Increase speed slightly
391
+ ball.dy = Math.sin(angle) * ball.speed;
392
+
393
+ createImpactParticles(aiPaddle.x, ball.y);
394
+ }
395
+
396
+ // Ball out of bounds (score)
397
+ if (ball.x < 0) {
398
+ aiScore++;
399
+ updateScore();
400
+ createExplosion(ball.x, ball.y);
401
+ resetBall();
402
+ } else if (ball.x + ball.width > canvas.width) {
403
+ playerScore++;
404
+ updateScore();
405
+ createExplosion(ball.x, ball.y);
406
+ resetBall();
407
+ }
408
+
409
+ // Update particles
410
+ updateParticles();
411
+
412
+ // Check for game over
413
+ if (playerScore >= 5 || aiScore >= 5) {
414
+ endGame();
415
+ }
416
+ }
417
+
418
+ function resetBall() {
419
+ ball.x = canvas.width / 2;
420
+ ball.y = canvas.height / 2;
421
+ ball.dx = 5 * (Math.random() > 0.5 ? 1 : -1);
422
+ ball.dy = 5 * (Math.random() > 0.5 ? 1 : -1);
423
+ ball.trail = [];
424
+
425
+ // Small delay before next round
426
+ gameRunning = false;
427
+ setTimeout(() => {
428
+ gameRunning = true;
429
+ }, 1000);
430
+ }
431
+
432
+ function updateScore() {
433
+ playerScoreDisplay.textContent = playerScore;
434
+ aiScoreDisplay.textContent = aiScore;
435
+ }
436
+
437
+ function endGame() {
438
+ gameRunning = false;
439
+ gameOverScreen.classList.remove('hidden');
440
+
441
+ if (playerScore > aiScore) {
442
+ gameOverText.textContent = "SYSTEM DOMINATION COMPLETE";
443
+ gameOverText.style.color = "#00ff00";
444
+ } else {
445
+ gameOverText.textContent = "SYSTEM FAILURE DETECTED";
446
+ gameOverText.style.color = "#ff0033";
447
+ }
448
+ }
449
+
450
+ function draw() {
451
+ // Draw ball trail
452
+ for (let i = 0; i < ball.trail.length; i++) {
453
+ const alpha = i / ball.trail.length;
454
+ ctx.fillStyle = `rgba(0, 255, 252, ${alpha * 0.5})`;
455
+ ctx.beginPath();
456
+ ctx.arc(ball.trail[i].x + ball.width / 2, ball.trail[i].y + ball.height / 2, ball.width / 2 * alpha, 0, Math.PI * 2);
457
+ ctx.fill();
458
+ }
459
+
460
+ // Draw ball
461
+ const gradient = ctx.createRadialGradient(
462
+ ball.x + ball.width / 2, ball.y + ball.height / 2, 0,
463
+ ball.x + ball.width / 2, ball.y + ball.height / 2, ball.width / 2
464
+ );
465
+ gradient.addColorStop(0, powerActive ? '#ff00ff' : '#00fffc');
466
+ gradient.addColorStop(1, powerActive ? '#ff0000' : '#0088ff');
467
+
468
+ ctx.fillStyle = gradient;
469
+ ctx.beginPath();
470
+ ctx.arc(ball.x + ball.width / 2, ball.y + ball.height / 2, ball.width / 2, 0, Math.PI * 2);
471
+ ctx.fill();
472
+
473
+ // Draw player paddle
474
+ const paddleGradient = ctx.createLinearGradient(
475
+ playerPaddle.x, playerPaddle.y,
476
+ playerPaddle.x + playerPaddle.width, playerPaddle.y + playerPaddle.height
477
+ );
478
+ paddleGradient.addColorStop(0, '#00fffc');
479
+ paddleGradient.addColorStop(1, '#0088ff');
480
+
481
+ ctx.fillStyle = paddleGradient;
482
+ ctx.fillRect(playerPaddle.x, playerPaddle.y, playerPaddle.width, playerPaddle.height);
483
+
484
+ // Draw AI paddle
485
+ const aiPaddleGradient = ctx.createLinearGradient(
486
+ aiPaddle.x, aiPaddle.y,
487
+ aiPaddle.x + aiPaddle.width, aiPaddle.y + aiPaddle.height
488
+ );
489
+ aiPaddleGradient.addColorStop(0, '#ff00ff');
490
+ aiPaddleGradient.addColorStop(1, '#ff0033');
491
+
492
+ ctx.fillStyle = aiPaddleGradient;
493
+ ctx.fillRect(aiPaddle.x, aiPaddle.y, aiPaddle.width, aiPaddle.height);
494
+
495
+ // Draw power meter
496
+ ctx.fillStyle = 'rgba(0, 20, 40, 0.7)';
497
+ ctx.fillRect(20, canvas.height - 30, 200, 20);
498
+
499
+ ctx.fillStyle = powerCharge >= 100 ? '#ff00ff' : '#00fffc';
500
+ ctx.fillRect(20, canvas.height - 30, 200 * (powerCharge / 100), 20);
501
+
502
+ ctx.strokeStyle = '#00fffc';
503
+ ctx.strokeRect(20, canvas.height - 30, 200, 20);
504
+
505
+ ctx.fillStyle = '#00fffc';
506
+ ctx.font = '14px Orbitron';
507
+ ctx.fillText('POWER SHOT', 25, canvas.height - 35);
508
+
509
+ if (powerCharge >= 100) {
510
+ ctx.fillStyle = '#ff00ff';
511
+ ctx.font = 'bold 14px Orbitron';
512
+ ctx.fillText('READY!', 150, canvas.height - 35);
513
+ }
514
+
515
+ // Draw particles
516
+ drawParticles();
517
+ }
518
+
519
+ function createImpactParticles(x, y) {
520
+ for (let i = 0; i < 10; i++) {
521
+ createParticle(x, y, '#00fffc');
522
+ }
523
+ }
524
+
525
+ function createExplosion(x, y) {
526
+ for (let i = 0; i < 50; i++) {
527
+ createParticle(x, y, i % 2 === 0 ? '#ff00ff' : '#00fffc', true);
528
+ }
529
+ }
530
+
531
+ function createParticle(x, y, color, isExplosion = false) {
532
+ const size = Math.random() * 4 + 2;
533
+ const angle = Math.random() * Math.PI * 2;
534
+ const speed = isExplosion ? Math.random() * 5 + 2 : Math.random() * 3 + 1;
535
+
536
+ particles.push({
537
+ x: x,
538
+ y: y,
539
+ size: size,
540
+ color: color,
541
+ dx: Math.cos(angle) * speed,
542
+ dy: Math.sin(angle) * speed,
543
+ life: isExplosion ? 60 : 30,
544
+ maxLife: isExplosion ? 60 : 30
545
+ });
546
+ }
547
+
548
+ function updateParticles() {
549
+ for (let i = particles.length - 1; i >= 0; i--) {
550
+ const p = particles[i];
551
+
552
+ p.x += p.dx;
553
+ p.y += p.dy;
554
+ p.life--;
555
+
556
+ // Apply gravity to explosion particles
557
+ if (p.life < p.maxLife / 2) {
558
+ p.dy += 0.1;
559
+ }
560
+
561
+ if (p.life <= 0) {
562
+ particles.splice(i, 1);
563
+ }
564
+ }
565
+ }
566
+
567
+ function drawParticles() {
568
+ for (const p of particles) {
569
+ const alpha = p.life / p.maxLife;
570
+ ctx.fillStyle = `${p.color.replace(')', `, ${alpha})`).replace('rgb', 'rgba')}`;
571
+ ctx.beginPath();
572
+ ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);
573
+ ctx.fill();
574
+ }
575
+ }
576
+
577
+ // Set default difficulty
578
+ setDifficulty(5);
579
+ });
580
+ </script>
581
+ <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=andreaschandra/cybernetic-pong-x" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
582
+ </html>