saishshinde15 commited on
Commit
cd7f8d0
·
verified ·
1 Parent(s): 227f685

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +755 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Classic Games
3
- emoji:
4
- colorFrom: purple
5
- colorTo: pink
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: classic-games
3
+ emoji: 🐳
4
+ colorFrom: blue
5
+ colorTo: blue
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,755 @@
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>Pixel Arcade - Retro Gaming</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ @import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');
11
+
12
+ body {
13
+ font-family: 'Press Start 2P', cursive;
14
+ background-color: #0f0f1a;
15
+ color: #e0e0e0;
16
+ overflow-x: hidden;
17
+ }
18
+
19
+ .pixel-border {
20
+ border: 4px solid #ff00ff;
21
+ box-shadow:
22
+ 0 0 0 4px #00ffff,
23
+ 0 0 0 8px #ff00ff,
24
+ 0 0 0 12px #ffff00;
25
+ }
26
+
27
+ .pixel-text {
28
+ text-shadow: 4px 4px 0px #ff00ff, -4px -4px 0px #00ffff;
29
+ }
30
+
31
+ .scanlines {
32
+ position: fixed;
33
+ top: 0;
34
+ left: 0;
35
+ width: 100%;
36
+ height: 100%;
37
+ background: linear-gradient(
38
+ rgba(18, 16, 16, 0) 50%,
39
+ rgba(0, 0, 0, 0.25) 50%
40
+ );
41
+ background-size: 100% 4px;
42
+ pointer-events: none;
43
+ z-index: 100;
44
+ }
45
+
46
+ .game-screen {
47
+ background: repeating-linear-gradient(
48
+ 0deg,
49
+ rgba(0, 0, 0, 0.15),
50
+ rgba(0, 0, 0, 0.15) 1px,
51
+ transparent 1px,
52
+ transparent 2px
53
+ );
54
+ }
55
+
56
+ .pixel-btn {
57
+ position: relative;
58
+ transition: all 0.2s;
59
+ }
60
+
61
+ .pixel-btn:hover {
62
+ transform: translate(-2px, -2px);
63
+ box-shadow: 4px 4px 0px #ff00ff;
64
+ }
65
+
66
+ .pixel-btn:active {
67
+ transform: translate(0, 0);
68
+ box-shadow: none;
69
+ }
70
+
71
+ @keyframes blink {
72
+ 0%, 100% { opacity: 1; }
73
+ 50% { opacity: 0.5; }
74
+ }
75
+
76
+ .blink {
77
+ animation: blink 1s infinite;
78
+ }
79
+
80
+ /* Game canvases */
81
+ #snake-game, #tetris-game, #pong-game {
82
+ border: 4px solid #00ff00;
83
+ image-rendering: pixelated;
84
+ }
85
+
86
+ #tetris-game { border-color: #ff00ff; }
87
+ #pong-game { border-color: #ffff00; }
88
+
89
+ /* CRT TV effect */
90
+ .crt-effect::before {
91
+ content: " ";
92
+ display: block;
93
+ position: absolute;
94
+ top: 0;
95
+ left: 0;
96
+ bottom: 0;
97
+ right: 0;
98
+ background: rgba(18, 16, 16, 0.1);
99
+ opacity: 0.15;
100
+ z-index: 2;
101
+ pointer-events: none;
102
+ }
103
+
104
+ .crt-effect::after {
105
+ content: " ";
106
+ display: block;
107
+ position: absolute;
108
+ top: 0;
109
+ left: 0;
110
+ bottom: 0;
111
+ right: 0;
112
+ background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06));
113
+ z-index: 2;
114
+ background-size: 100% 2px, 3px 100%;
115
+ pointer-events: none;
116
+ }
117
+
118
+ /* Tetris blocks */
119
+ .tetris-I { background-color: #00FFFF; }
120
+ .tetris-J { background-color: #0000FF; }
121
+ .tetris-L { background-color: #FF7F00; }
122
+ .tetris-O { background-color: #FFFF00; }
123
+ .tetris-S { background-color: #00FF00; }
124
+ .tetris-T { background-color: #800080; }
125
+ .tetris-Z { background-color: #FF0000; }
126
+ </style>
127
+ </head>
128
+ <body class="min-h-screen">
129
+ <!-- CRT Scanlines Effect -->
130
+ <div class="scanlines"></div>
131
+
132
+ <!-- Main Container -->
133
+ <div class="container mx-auto px-4 py-8 crt-effect">
134
+ <!-- Header -->
135
+ <header class="text-center mb-12">
136
+ <h1 class="text-5xl md:text-6xl lg:text-7xl mb-6 text-purple-400 pixel-text">PIXEL ARCADE</h1>
137
+ <p class="text-lg text-cyan-300 mb-8">RETRO GAMING EXPERIENCE</p>
138
+
139
+ <div class="flex justify-center space-x-4 mb-8">
140
+ <button class="pixel-btn bg-purple-600 text-white px-6 py-3 rounded-none">PLAY NOW</button>
141
+ <button class="pixel-btn bg-cyan-600 text-white px-6 py-3 rounded-none">HIGH SCORES</button>
142
+ <button class="pixel-btn bg-yellow-600 text-white px-6 py-3 rounded-none">ABOUT</button>
143
+ </div>
144
+
145
+ <div class="flex justify-center">
146
+ <div class="pixel-border p-4 inline-block">
147
+ <div class="bg-black p-2 game-screen">
148
+ <p class="text-green-400 blink">INSERT COIN</p>
149
+ </div>
150
+ </div>
151
+ </div>
152
+ </header>
153
+
154
+ <!-- Featured Games -->
155
+ <section class="mb-16">
156
+ <h2 class="text-3xl text-yellow-400 mb-8 text-center pixel-text">CLASSIC GAMES</h2>
157
+
158
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-8">
159
+ <!-- Snake Game -->
160
+ <div class="pixel-border p-4 bg-gray-900">
161
+ <h3 class="text-xl text-green-400 mb-4">SNAKE</h3>
162
+ <div class="relative">
163
+ <canvas id="snake-game" width="300" height="300" class="w-full bg-black"></canvas>
164
+ <div class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-70 p-2">
165
+ <p class="text-xs text-white">Arrow keys to move</p>
166
+ </div>
167
+ </div>
168
+ <button onclick="startSnakeGame()" class="pixel-btn bg-green-600 text-white px-4 py-2 mt-4 w-full">PLAY SNAKE</button>
169
+ </div>
170
+
171
+ <!-- Tetris Game -->
172
+ <div class="pixel-border p-4 bg-gray-900">
173
+ <h3 class="text-xl text-purple-400 mb-4">TETRIS</h3>
174
+ <div class="relative">
175
+ <canvas id="tetris-game" width="300" height="480" class="w-full bg-black"></canvas>
176
+ <div class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-70 p-2">
177
+ <p class="text-xs text-white">Arrow keys to move, Up to rotate</p>
178
+ </div>
179
+ </div>
180
+ <button onclick="startTetrisGame()" class="pixel-btn bg-purple-600 text-white px-4 py-2 mt-4 w-full">PLAY TETRIS</button>
181
+ </div>
182
+
183
+ <!-- Pong Game -->
184
+ <div class="pixel-border p-4 bg-gray-900">
185
+ <h3 class="text-xl text-yellow-400 mb-4">PONG</h3>
186
+ <div class="relative">
187
+ <canvas id="pong-game" width="300" height="400" class="w-full bg-black"></canvas>
188
+ <div class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-70 p-2">
189
+ <p class="text-xs text-white">W/S keys for left paddle</p>
190
+ <p class="text-xs text-white">Up/Down for right paddle</p>
191
+ </div>
192
+ </div>
193
+ <button onclick="startPongGame()" class="pixel-btn bg-yellow-600 text-white px-4 py-2 mt-4 w-full">PLAY PONG</button>
194
+ </div>
195
+ </div>
196
+ </section>
197
+
198
+ <!-- Retro Consoles -->
199
+ <section class="mb-16">
200
+ <h2 class="text-3xl text-cyan-400 mb-8 text-center pixel-text">RETRO CONSOLES</h2>
201
+
202
+ <div class="grid grid-cols-2 md:grid-cols-4 gap-6">
203
+ <div class="text-center">
204
+ <div class="pixel-border p-2 bg-gray-800 mb-2">
205
+ <i class="fas fa-gamepad text-4xl text-red-500"></i>
206
+ </div>
207
+ <p class="text-sm">NES</p>
208
+ </div>
209
+ <div class="text-center">
210
+ <div class="pixel-border p-2 bg-gray-800 mb-2">
211
+ <i class="fas fa-gamepad text-4xl text-blue-500"></i>
212
+ </div>
213
+ <p class="text-sm">SNES</p>
214
+ </div>
215
+ <div class="text-center">
216
+ <div class="pixel-border p-2 bg-gray-800 mb-2">
217
+ <i class="fas fa-gamepad text-4xl text-green-500"></i>
218
+ </div>
219
+ <p class="text-sm">SEGA</p>
220
+ </div>
221
+ <div class="text-center">
222
+ <div class="pixel-border p-2 bg-gray-800 mb-2">
223
+ <i class="fas fa-gamepad text-4xl text-yellow-500"></i>
224
+ </div>
225
+ <p class="text-sm">ATARI</p>
226
+ </div>
227
+ </div>
228
+ </section>
229
+
230
+ <!-- Footer -->
231
+ <footer class="text-center py-8 border-t border-purple-900">
232
+ <div class="flex justify-center space-x-6 mb-4">
233
+ <a href="#" class="text-purple-400 hover:text-cyan-400"><i class="fab fa-twitter"></i></a>
234
+ <a href="#" class="text-purple-400 hover:text-cyan-400"><i class="fab fa-facebook"></i></a>
235
+ <a href="#" class="text-purple-400 hover:text-cyan-400"><i class="fab fa-instagram"></i></a>
236
+ <a href="#" class="text-purple-400 hover:text-cyan-400"><i class="fab fa-discord"></i></a>
237
+ </div>
238
+ <p class="text-xs text-gray-500">© 2023 PIXEL ARCADE - ALL RIGHTS RESERVED</p>
239
+ <p class="text-xs text-gray-600 mt-2">CREATED WITH <i class="fas fa-heart text-red-500"></i> FOR RETRO GAMERS</p>
240
+ </footer>
241
+ </div>
242
+
243
+ <script>
244
+ // ========== SNAKE GAME ==========
245
+ let snakeGame;
246
+ let snakeCtx;
247
+ let snake = [];
248
+ let food = {};
249
+ let direction = 'right';
250
+ let snakeLoop;
251
+ let snakeScore = 0;
252
+
253
+ function startSnakeGame() {
254
+ snakeGame = document.getElementById('snake-game');
255
+ snakeCtx = snakeGame.getContext('2d');
256
+
257
+ // Initialize snake
258
+ snake = [
259
+ {x: 150, y: 150},
260
+ {x: 140, y: 150},
261
+ {x: 130, y: 150},
262
+ {x: 120, y: 150},
263
+ {x: 110, y: 150}
264
+ ];
265
+
266
+ // Create first food
267
+ createSnakeFood();
268
+
269
+ // Reset score
270
+ snakeScore = 0;
271
+
272
+ // Start game loop
273
+ if (snakeLoop) clearInterval(snakeLoop);
274
+ snakeLoop = setInterval(updateSnakeGame, 100);
275
+
276
+ // Focus on canvas for keyboard controls
277
+ snakeGame.focus();
278
+ }
279
+
280
+ function createSnakeFood() {
281
+ food = {
282
+ x: Math.floor(Math.random() * 30) * 10,
283
+ y: Math.floor(Math.random() * 30) * 10
284
+ };
285
+
286
+ // Make sure food doesn't appear on snake
287
+ for (let segment of snake) {
288
+ if (segment.x === food.x && segment.y === food.y) {
289
+ return createSnakeFood();
290
+ }
291
+ }
292
+ }
293
+
294
+ function updateSnakeGame() {
295
+ // Move snake
296
+ let head = {x: snake[0].x, y: snake[0].y};
297
+
298
+ switch(direction) {
299
+ case 'up': head.y -= 10; break;
300
+ case 'down': head.y += 10; break;
301
+ case 'left': head.x -= 10; break;
302
+ case 'right': head.x += 10; break;
303
+ }
304
+
305
+ // Check collision with walls
306
+ if (head.x < 0 || head.x >= snakeGame.width || head.y < 0 || head.y >= snakeGame.height) {
307
+ clearInterval(snakeLoop);
308
+ alert('Game Over! Score: ' + snakeScore);
309
+ return;
310
+ }
311
+
312
+ // Check collision with self
313
+ for (let segment of snake) {
314
+ if (segment.x === head.x && segment.y === head.y) {
315
+ clearInterval(snakeLoop);
316
+ alert('Game Over! Score: ' + snakeScore);
317
+ return;
318
+ }
319
+ }
320
+
321
+ // Check if snake ate food
322
+ if (head.x === food.x && head.y === food.y) {
323
+ snakeScore += 10;
324
+ createSnakeFood();
325
+ } else {
326
+ snake.pop(); // Remove tail if no food eaten
327
+ }
328
+
329
+ snake.unshift(head); // Add new head
330
+
331
+ // Draw everything
332
+ snakeCtx.fillStyle = 'black';
333
+ snakeCtx.fillRect(0, 0, snakeGame.width, snakeGame.height);
334
+
335
+ // Draw snake
336
+ snakeCtx.fillStyle = 'lime';
337
+ for (let segment of snake) {
338
+ snakeCtx.fillRect(segment.x, segment.y, 10, 10);
339
+ }
340
+
341
+ // Draw food
342
+ snakeCtx.fillStyle = 'red';
343
+ snakeCtx.fillRect(food.x, food.y, 10, 10);
344
+
345
+ // Draw score
346
+ snakeCtx.fillStyle = 'white';
347
+ snakeCtx.font = '20px "Press Start 2P"';
348
+ snakeCtx.fillText('Score: ' + snakeScore, 10, 25);
349
+ }
350
+
351
+ // Keyboard controls for snake
352
+ document.getElementById('snake-game').addEventListener('keydown', function(e) {
353
+ switch(e.key) {
354
+ case 'ArrowUp': if (direction !== 'down') direction = 'up'; break;
355
+ case 'ArrowDown': if (direction !== 'up') direction = 'down'; break;
356
+ case 'ArrowLeft': if (direction !== 'right') direction = 'left'; break;
357
+ case 'ArrowRight': if (direction !== 'left') direction = 'right'; break;
358
+ }
359
+ });
360
+
361
+ // ========== TETRIS GAME ==========
362
+ let tetrisGame;
363
+ let tetrisCtx;
364
+ let tetrisBoard = [];
365
+ let currentPiece;
366
+ let nextPiece;
367
+ let tetrisScore = 0;
368
+ let tetrisLoop;
369
+ let dropCounter = 0;
370
+ let dropInterval = 1000;
371
+ let lastTime = 0;
372
+ const COLS = 10;
373
+ const ROWS = 20;
374
+ const BLOCK_SIZE = 30;
375
+
376
+ // Tetris pieces
377
+ const PIECES = [
378
+ { shape: [[1,1,1,1]], color: 'tetris-I' }, // I
379
+ { shape: [[1,0,0],[1,1,1]], color: 'tetris-J' }, // J
380
+ { shape: [[0,0,1],[1,1,1]], color: 'tetris-L' }, // L
381
+ { shape: [[1,1],[1,1]], color: 'tetris-O' }, // O
382
+ { shape: [[0,1,1],[1,1,0]], color: 'tetris-S' }, // S
383
+ { shape: [[0,1,0],[1,1,1]], color: 'tetris-T' }, // T
384
+ { shape: [[1,1,0],[0,1,1]], color: 'tetris-Z' } // Z
385
+ ];
386
+
387
+ function startTetrisGame() {
388
+ tetrisGame = document.getElementById('tetris-game');
389
+ tetrisCtx = tetrisGame.getContext('2d');
390
+ tetrisGame.width = COLS * BLOCK_SIZE;
391
+ tetrisGame.height = ROWS * BLOCK_SIZE;
392
+
393
+ // Scale canvas for display
394
+ tetrisGame.style.width = '300px';
395
+ tetrisGame.style.height = '480px';
396
+
397
+ // Initialize empty board
398
+ createBoard();
399
+
400
+ // Create first piece
401
+ currentPiece = createPiece();
402
+ nextPiece = createPiece();
403
+
404
+ // Reset score
405
+ tetrisScore = 0;
406
+
407
+ // Start game loop
408
+ if (tetrisLoop) cancelAnimationFrame(tetrisLoop);
409
+ lastTime = 0;
410
+ tetrisLoop = requestAnimationFrame(updateTetrisGame);
411
+
412
+ // Focus on canvas for keyboard controls
413
+ tetrisGame.focus();
414
+ }
415
+
416
+ function createBoard() {
417
+ tetrisBoard = Array.from(Array(ROWS), () => Array(COLS).fill(0));
418
+ }
419
+
420
+ function createPiece() {
421
+ const piece = JSON.parse(JSON.stringify(PIECES[Math.floor(Math.random() * PIECES.length)]));
422
+ piece.pos = {x: Math.floor(COLS/2) - 1, y: -2};
423
+ return piece;
424
+ }
425
+
426
+ function updateTetrisGame(time = 0) {
427
+ const deltaTime = time - lastTime;
428
+ lastTime = time;
429
+
430
+ dropCounter += deltaTime;
431
+ if (dropCounter > dropInterval) {
432
+ movePieceDown();
433
+ dropCounter = 0;
434
+ }
435
+
436
+ drawTetrisGame();
437
+ tetrisLoop = requestAnimationFrame(updateTetrisGame);
438
+ }
439
+
440
+ function drawTetrisGame() {
441
+ tetrisCtx.fillStyle = 'black';
442
+ tetrisCtx.fillRect(0, 0, tetrisGame.width, tetrisGame.height);
443
+
444
+ // Draw board
445
+ drawBoard();
446
+
447
+ // Draw current piece
448
+ drawPiece();
449
+
450
+ // Draw score
451
+ tetrisCtx.fillStyle = 'white';
452
+ tetrisCtx.font = '18px "Press Start 2P"';
453
+ tetrisCtx.fillText('Score: ' + tetrisScore, 10, 25);
454
+ }
455
+
456
+ function drawBoard() {
457
+ tetrisBoard.forEach((row, y) => {
458
+ row.forEach((value, x) => {
459
+ if (value) {
460
+ tetrisCtx.fillStyle = PIECES[value-1].color;
461
+ tetrisCtx.fillRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
462
+ tetrisCtx.strokeStyle = 'black';
463
+ tetrisCtx.strokeRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
464
+ }
465
+ });
466
+ });
467
+ }
468
+
469
+ function drawPiece() {
470
+ currentPiece.shape.forEach((row, y) => {
471
+ row.forEach((value, x) => {
472
+ if (value) {
473
+ tetrisCtx.fillStyle = currentPiece.color;
474
+ tetrisCtx.fillRect(
475
+ (currentPiece.pos.x + x) * BLOCK_SIZE,
476
+ (currentPiece.pos.y + y) * BLOCK_SIZE,
477
+ BLOCK_SIZE,
478
+ BLOCK_SIZE
479
+ );
480
+ tetrisCtx.strokeStyle = 'black';
481
+ tetrisCtx.strokeRect(
482
+ (currentPiece.pos.x + x) * BLOCK_SIZE,
483
+ (currentPiece.pos.y + y) * BLOCK_SIZE,
484
+ BLOCK_SIZE,
485
+ BLOCK_SIZE
486
+ );
487
+ }
488
+ });
489
+ });
490
+ }
491
+
492
+ function movePieceDown() {
493
+ currentPiece.pos.y++;
494
+ if (collision()) {
495
+ currentPiece.pos.y--;
496
+ mergePiece();
497
+ removeRows();
498
+ currentPiece = nextPiece;
499
+ nextPiece = createPiece();
500
+
501
+ // Check game over
502
+ if (collision()) {
503
+ cancelAnimationFrame(tetrisLoop);
504
+ alert('Game Over! Score: ' + tetrisScore);
505
+ return;
506
+ }
507
+ }
508
+ dropCounter = 0;
509
+ }
510
+
511
+ function collision() {
512
+ return currentPiece.shape.some((row, y) => {
513
+ return row.some((value, x) => {
514
+ return value &&
515
+ (currentPiece.pos.x + x < 0 ||
516
+ currentPiece.pos.x + x >= COLS ||
517
+ currentPiece.pos.y + y >= ROWS ||
518
+ tetrisBoard[currentPiece.pos.y + y][currentPiece.pos.x + x]);
519
+ });
520
+ });
521
+ }
522
+
523
+ function mergePiece() {
524
+ currentPiece.shape.forEach((row, y) => {
525
+ row.forEach((value, x) => {
526
+ if (value) {
527
+ tetrisBoard[currentPiece.pos.y + y][currentPiece.pos.x + x] =
528
+ PIECES.findIndex(p => p.color === currentPiece.color) + 1;
529
+ }
530
+ });
531
+ });
532
+ }
533
+
534
+ function removeRows() {
535
+ let rowsCleared = 0;
536
+
537
+ outer: for (let y = ROWS - 1; y >= 0; y--) {
538
+ for (let x = 0; x < COLS; x++) {
539
+ if (tetrisBoard[y][x] === 0) {
540
+ continue outer;
541
+ }
542
+ }
543
+
544
+ // Remove the row
545
+ const row = tetrisBoard.splice(y, 1)[0].fill(0);
546
+ tetrisBoard.unshift(row);
547
+ y++; // Check the same row again (the row moved down)
548
+
549
+ rowsCleared++;
550
+ }
551
+
552
+ // Update score
553
+ if (rowsCleared > 0) {
554
+ tetrisScore += [100, 300, 500, 800][rowsCleared - 1] || 0;
555
+ dropInterval *= 0.9; // Increase speed
556
+ }
557
+ }
558
+
559
+ function rotatePiece() {
560
+ const originalShape = currentPiece.shape;
561
+
562
+ // Transpose and reverse rows = rotation
563
+ currentPiece.shape = currentPiece.shape[0].map((_, index) =>
564
+ currentPiece.shape.map(row => row[index]).reverse()
565
+ );
566
+
567
+ if (collision()) {
568
+ currentPiece.shape = originalShape;
569
+ }
570
+ }
571
+
572
+ // Keyboard controls for Tetris
573
+ document.getElementById('tetris-game').addEventListener('keydown', function(e) {
574
+ if (e.key === 'ArrowLeft') {
575
+ currentPiece.pos.x--;
576
+ if (collision()) currentPiece.pos.x++;
577
+ } else if (e.key === 'ArrowRight') {
578
+ currentPiece.pos.x++;
579
+ if (collision()) currentPiece.pos.x--;
580
+ } else if (e.key === 'ArrowDown') {
581
+ movePieceDown();
582
+ } else if (e.key === 'ArrowUp') {
583
+ rotatePiece();
584
+ }
585
+ });
586
+
587
+ // ========== PONG GAME ==========
588
+ let pongGame;
589
+ let pongCtx;
590
+ let pongLoop;
591
+ let leftPaddle = { y: 150, width: 10, height: 80 };
592
+ let rightPaddle = { y: 150, width: 10, height: 80 };
593
+ let ball = { x: 150, y: 200, radius: 8, dx: 4, dy: 4 };
594
+ let playerScore = 0;
595
+ let computerScore = 0;
596
+ const PADDLE_SPEED = 6;
597
+
598
+ function startPongGame() {
599
+ pongGame = document.getElementById('pong-game');
600
+ pongCtx = pongGame.getContext('2d');
601
+ pongGame.width = 300;
602
+ pongGame.height = 400;
603
+
604
+ // Reset positions
605
+ leftPaddle = { y: 150, width: 10, height: 80 };
606
+ rightPaddle = { y: 150, width: 10, height: 80 };
607
+ ball = { x: 150, y: 200, radius: 8, dx: 4, dy: 4 };
608
+ playerScore = 0;
609
+ computerScore = 0;
610
+
611
+ // Start game loop
612
+ if (pongLoop) cancelAnimationFrame(pongLoop);
613
+ pongLoop = requestAnimationFrame(updatePongGame);
614
+
615
+ // Focus on canvas for keyboard controls
616
+ pongGame.focus();
617
+ }
618
+
619
+ function updatePongGame() {
620
+ // Move ball
621
+ ball.x += ball.dx;
622
+ ball.y += ball.dy;
623
+
624
+ // Simple AI for right paddle
625
+ if (rightPaddle.y + rightPaddle.height/2 < ball.y) {
626
+ rightPaddle.y += PADDLE_SPEED - 1;
627
+ } else {
628
+ rightPaddle.y -= PADDLE_SPEED - 1;
629
+ }
630
+
631
+ // Wall collision (top/bottom)
632
+ if (ball.y - ball.radius < 0 || ball.y + ball.radius > pongGame.height) {
633
+ ball.dy = -ball.dy;
634
+ }
635
+
636
+ // Paddle collision
637
+ // Left paddle
638
+ if (
639
+ ball.dx < 0 &&
640
+ ball.x - ball.radius < leftPaddle.width &&
641
+ ball.y > leftPaddle.y &&
642
+ ball.y < leftPaddle.y + leftPaddle.height
643
+ ) {
644
+ ball.dx = -ball.dx;
645
+ // Add angle based on where ball hits paddle
646
+ const hitPos = (ball.y - (leftPaddle.y + leftPaddle.height/2)) / (leftPaddle.height/2);
647
+ ball.dy = hitPos * 5;
648
+ }
649
+
650
+ // Right paddle
651
+ if (
652
+ ball.dx > 0 &&
653
+ ball.x + ball.radius > pongGame.width - rightPaddle.width &&
654
+ ball.y > rightPaddle.y &&
655
+ ball.y < rightPaddle.y + rightPaddle.height
656
+ ) {
657
+ ball.dx = -ball.dx;
658
+ // Add angle based on where ball hits paddle
659
+ const hitPos = (ball.y - (rightPaddle.y + rightPaddle.height/2)) / (rightPaddle.height/2);
660
+ ball.dy = hitPos * 5;
661
+ }
662
+
663
+ // Score points
664
+ if (ball.x - ball.radius < 0) {
665
+ computerScore++;
666
+ resetBall();
667
+ } else if (ball.x + ball.radius > pongGame.width) {
668
+ playerScore++;
669
+ resetBall();
670
+ }
671
+
672
+ // Game over (first to 5 points)
673
+ if (playerScore >= 5 || computerScore >= 5) {
674
+ cancelAnimationFrame(pongLoop);
675
+ const winner = playerScore >= 5 ? "PLAYER" : "COMPUTER";
676
+ alert(`${winner} WINS! Final Score: ${playerScore}-${computerScore}`);
677
+ return;
678
+ }
679
+
680
+ drawPongGame();
681
+ pongLoop = requestAnimationFrame(updatePongGame);
682
+ }
683
+
684
+ function resetBall() {
685
+ ball.x = pongGame.width / 2;
686
+ ball.y = pongGame.height / 2;
687
+ ball.dx = -ball.dx;
688
+ ball.dy = Math.random() * 4 - 2;
689
+ }
690
+
691
+ function drawPongGame() {
692
+ // Draw background
693
+ pongCtx.fillStyle = 'black';
694
+ pongCtx.fillRect(0, 0, pongGame.width, pongGame.height);
695
+
696
+ // Draw center line
697
+ pongCtx.strokeStyle = '#333';
698
+ pongCtx.setLineDash([10, 10]);
699
+ pongCtx.beginPath();
700
+ pongCtx.moveTo(pongGame.width/2, 0);
701
+ pongCtx.lineTo(pongGame.width/2, pongGame.height);
702
+ pongCtx.stroke();
703
+ pongCtx.setLineDash([]);
704
+
705
+ // Draw paddles
706
+ pongCtx.fillStyle = 'cyan';
707
+ pongCtx.fillRect(0, leftPaddle.y, leftPaddle.width, leftPaddle.height);
708
+ pongCtx.fillRect(pongGame.width - rightPaddle.width, rightPaddle.y, rightPaddle.width, rightPaddle.height);
709
+
710
+ // Draw ball
711
+ pongCtx.fillStyle = 'white';
712
+ pongCtx.beginPath();
713
+ pongCtx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
714
+ pongCtx.fill();
715
+
716
+ // Draw scores
717
+ pongCtx.fillStyle = 'white';
718
+ pongCtx.font = '24px "Press Start 2P"';
719
+ pongCtx.textAlign = 'center';
720
+ pongCtx.fillText(playerScore, pongGame.width / 4, 40);
721
+ pongCtx.fillText(computerScore, (pongGame.width / 4) * 3, 40);
722
+ }
723
+
724
+ // Keyboard controls for Pong
725
+ document.addEventListener('keydown', (e) => {
726
+ switch(e.key) {
727
+ case 'w':
728
+ case 'W':
729
+ if (leftPaddle.y > 0) leftPaddle.y -= PADDLE_SPEED;
730
+ break;
731
+ case 's':
732
+ case 'S':
733
+ if (leftPaddle.y < pongGame.height - leftPaddle.height) leftPaddle.y += PADDLE_SPEED;
734
+ break;
735
+ case 'ArrowUp':
736
+ if (rightPaddle.y > 0) rightPaddle.y -= PADDLE_SPEED;
737
+ break;
738
+ case 'ArrowDown':
739
+ if (rightPaddle.y < pongGame.height - rightPaddle.height) rightPaddle.y += PADDLE_SPEED;
740
+ break;
741
+ }
742
+ });
743
+
744
+ // Make canvases focusable
745
+ document.getElementById('snake-game').tabIndex = 0;
746
+ document.getElementById('tetris-game').tabIndex = 0;
747
+ document.getElementById('pong-game').tabIndex = 0;
748
+
749
+ // Start snake game by default
750
+ window.onload = function() {
751
+ startSnakeGame();
752
+ };
753
+ </script>
754
+ <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=saishshinde15/classic-games" style="color: #fff;text-decoration: underline;" target="_blank" >🧬 Remix</a></p></body>
755
+ </html>