ApprikatAI commited on
Commit
4372718
·
verified ·
1 Parent(s): 5584692

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +799 -19
index.html CHANGED
@@ -1,19 +1,799 @@
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="es">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Tetris - Juego Completo</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ :root {
15
+ --primary-color: #1a1a2e;
16
+ --secondary-color: #16213e;
17
+ --accent-color: #0f3460;
18
+ --tetris-blue: #00d9ff;
19
+ --tetris-purple: #e94560;
20
+ --tetris-yellow: #ffbe0b;
21
+ --tetris-green: #8ac926;
22
+ --tetris-red: #ff595e;
23
+ --tetris-orange: #ff9f1c;
24
+ --tetris-pink: #ff006e;
25
+ --tetris-cyan: #00f5ff;
26
+ --text-color: #ffffff;
27
+ --grid-size: 30px;
28
+ }
29
+
30
+ body {
31
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
32
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
33
+ color: var(--text-color);
34
+ min-height: 100vh;
35
+ display: flex;
36
+ flex-direction: column;
37
+ align-items: center;
38
+ padding: 20px;
39
+ overflow-x: hidden;
40
+ }
41
+
42
+ header {
43
+ width: 100%;
44
+ text-align: center;
45
+ margin-bottom: 20px;
46
+ }
47
+
48
+ h1 {
49
+ font-size: 3rem;
50
+ margin-bottom: 10px;
51
+ background: linear-gradient(90deg, var(--tetris-blue), var(--tetris-purple));
52
+ -webkit-background-clip: text;
53
+ -webkit-text-fill-color: transparent;
54
+ text-shadow: 0 0 30px rgba(0, 217, 255, 0.5);
55
+ }
56
+
57
+ .built-with {
58
+ font-size: 0.9rem;
59
+ opacity: 0.8;
60
+ margin-top: 5px;
61
+ }
62
+
63
+ .built-with a {
64
+ color: var(--tetris-blue);
65
+ text-decoration: none;
66
+ transition: all 0.3s ease;
67
+ }
68
+
69
+ .built-with a:hover {
70
+ text-decoration: underline;
71
+ transform: scale(1.05);
72
+ }
73
+
74
+ .game-container {
75
+ display: flex;
76
+ flex-wrap: wrap;
77
+ justify-content: center;
78
+ gap: 30px;
79
+ max-width: 1200px;
80
+ width: 100%;
81
+ }
82
+
83
+ .game-board {
84
+ background: rgba(0, 0, 0, 0.3);
85
+ border-radius: 10px;
86
+ padding: 10px;
87
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
88
+ border: 2px solid rgba(255, 255, 255, 0.1);
89
+ }
90
+
91
+ .grid {
92
+ display: grid;
93
+ grid-template-columns: repeat(10, var(--grid-size));
94
+ grid-template-rows: repeat(20, var(--grid-size));
95
+ gap: 1px;
96
+ background: rgba(0, 0, 0, 0.5);
97
+ border: 1px solid rgba(255, 255, 255, 0.1);
98
+ }
99
+
100
+ .cell {
101
+ width: var(--grid-size);
102
+ height: var(--grid-size);
103
+ background: rgba(0, 0, 0, 0.8);
104
+ border-radius: 2px;
105
+ transition: all 0.1s ease;
106
+ }
107
+
108
+ .cell.filled {
109
+ border: 1px solid rgba(255, 255, 255, 0.3);
110
+ }
111
+
112
+ .cell.I { background-color: var(--tetris-cyan); }
113
+ .cell.O { background-color: var(--tetris-yellow); }
114
+ .cell.T { background-color: var(--tetris-purple); }
115
+ .cell.S { background-color: var(--tetris-green); }
116
+ .cell.Z { background-color: var(--tetris-red); }
117
+ .cell.J { background-color: var(--tetris-blue); }
118
+ .cell.L { background-color: var(--tetris-orange); }
119
+
120
+ .sidebar {
121
+ display: flex;
122
+ flex-direction: column;
123
+ gap: 20px;
124
+ min-width: 250px;
125
+ }
126
+
127
+ .info-panel {
128
+ background: rgba(0, 0, 0, 0.3);
129
+ border-radius: 10px;
130
+ padding: 20px;
131
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
132
+ border: 2px solid rgba(255, 255, 255, 0.1);
133
+ }
134
+
135
+ .info-panel h2 {
136
+ font-size: 1.5rem;
137
+ margin-bottom: 15px;
138
+ color: var(--tetris-blue);
139
+ }
140
+
141
+ .score-display, .level-display, .lines-display {
142
+ font-size: 1.2rem;
143
+ margin: 10px 0;
144
+ display: flex;
145
+ justify-content: space-between;
146
+ }
147
+
148
+ .score-value, .level-value, .lines-value {
149
+ font-weight: bold;
150
+ color: var(--tetris-yellow);
151
+ }
152
+
153
+ .next-piece-container {
154
+ margin-top: 20px;
155
+ }
156
+
157
+ .next-piece-grid {
158
+ display: grid;
159
+ grid-template-columns: repeat(4, 20px);
160
+ grid-template-rows: repeat(4, 20px);
161
+ gap: 1px;
162
+ background: rgba(0, 0, 0, 0.5);
163
+ padding: 10px;
164
+ border-radius: 5px;
165
+ margin: 10px auto;
166
+ width: fit-content;
167
+ }
168
+
169
+ .next-cell {
170
+ width: 20px;
171
+ height: 20px;
172
+ background: rgba(0, 0, 0, 0.8);
173
+ border-radius: 2px;
174
+ }
175
+
176
+ .next-cell.filled {
177
+ border: 1px solid rgba(255, 255, 255, 0.3);
178
+ }
179
+
180
+ .controls {
181
+ margin-top: 20px;
182
+ }
183
+
184
+ .control-button {
185
+ background: linear-gradient(135deg, var(--accent-color), var(--secondary-color));
186
+ color: var(--text-color);
187
+ border: none;
188
+ padding: 12px 24px;
189
+ border-radius: 5px;
190
+ font-size: 1rem;
191
+ cursor: pointer;
192
+ transition: all 0.3s ease;
193
+ margin: 5px;
194
+ width: 100%;
195
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
196
+ }
197
+
198
+ .control-button:hover {
199
+ transform: translateY(-2px);
200
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
201
+ }
202
+
203
+ .control-button:active {
204
+ transform: translateY(0);
205
+ }
206
+
207
+ .control-button.play {
208
+ background: linear-gradient(135deg, var(--tetris-green), var(--tetris-blue));
209
+ }
210
+
211
+ .control-button.pause {
212
+ background: linear-gradient(135deg, var(--tetris-purple), var(--tetris-pink));
213
+ }
214
+
215
+ .instructions {
216
+ margin-top: 20px;
217
+ font-size: 0.9rem;
218
+ opacity: 0.8;
219
+ line-height: 1.5;
220
+ }
221
+
222
+ .game-over {
223
+ position: absolute;
224
+ top: 50%;
225
+ left: 50%;
226
+ transform: translate(-50%, -50%);
227
+ background: rgba(0, 0, 0, 0.9);
228
+ padding: 30px;
229
+ border-radius: 10px;
230
+ text-align: center;
231
+ display: none;
232
+ z-index: 100;
233
+ box-shadow: 0 0 50px rgba(0, 0, 0, 0.8);
234
+ }
235
+
236
+ .game-over h2 {
237
+ color: var(--tetris-red);
238
+ margin-bottom: 20px;
239
+ font-size: 2rem;
240
+ }
241
+
242
+ .game-over p {
243
+ margin-bottom: 20px;
244
+ font-size: 1.2rem;
245
+ }
246
+
247
+ .mobile-controls {
248
+ display: none;
249
+ flex-direction: column;
250
+ gap: 10px;
251
+ margin-top: 20px;
252
+ }
253
+
254
+ .control-row {
255
+ display: flex;
256
+ justify-content: center;
257
+ gap: 10px;
258
+ }
259
+
260
+ .mobile-button {
261
+ width: 60px;
262
+ height: 60px;
263
+ background: rgba(255, 255, 255, 0.1);
264
+ border: 2px solid rgba(255, 255, 255, 0.3);
265
+ border-radius: 10px;
266
+ display: flex;
267
+ align-items: center;
268
+ justify-content: center;
269
+ font-size: 1.5rem;
270
+ cursor: pointer;
271
+ transition: all 0.2s ease;
272
+ }
273
+
274
+ .mobile-button:active {
275
+ background: rgba(255, 255, 255, 0.2);
276
+ transform: scale(0.95);
277
+ }
278
+
279
+ @media (max-width: 768px) {
280
+ :root {
281
+ --grid-size: 20px;
282
+ }
283
+
284
+ h1 {
285
+ font-size: 2rem;
286
+ }
287
+
288
+ .sidebar {
289
+ min-width: 200px;
290
+ }
291
+
292
+ .next-piece-grid {
293
+ grid-template-columns: repeat(4, 15px);
294
+ grid-template-rows: repeat(4, 15px);
295
+ }
296
+
297
+ .next-cell {
298
+ width: 15px;
299
+ height: 15px;
300
+ }
301
+
302
+ .mobile-controls {
303
+ display: flex;
304
+ }
305
+
306
+ .control-button {
307
+ padding: 10px 20px;
308
+ font-size: 0.9rem;
309
+ }
310
+ }
311
+
312
+ @media (max-width: 480px) {
313
+ :root {
314
+ --grid-size: 15px;
315
+ }
316
+
317
+ h1 {
318
+ font-size: 1.5rem;
319
+ }
320
+
321
+ .game-container {
322
+ gap: 15px;
323
+ }
324
+
325
+ .sidebar {
326
+ min-width: 150px;
327
+ }
328
+ }
329
+
330
+ .particle {
331
+ position: absolute;
332
+ pointer-events: none;
333
+ opacity: 0;
334
+ animation: particle-float 1s ease-out forwards;
335
+ }
336
+
337
+ @keyframes particle-float {
338
+ 0% {
339
+ opacity: 1;
340
+ transform: translateY(0) scale(1);
341
+ }
342
+ 100% {
343
+ opacity: 0;
344
+ transform: translateY(-50px) scale(0.5);
345
+ }
346
+ }
347
+ </style>
348
+ </head>
349
+ <body>
350
+ <header>
351
+ <h1>Tetris</h1>
352
+ <div class="built-with">
353
+ Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a>
354
+ </div>
355
+ </header>
356
+
357
+ <main class="game-container">
358
+ <div class="game-board">
359
+ <div class="grid" id="gameGrid"></div>
360
+ </div>
361
+
362
+ <aside class="sidebar">
363
+ <div class="info-panel">
364
+ <h2>Puntuación</h2>
365
+ <div class="score-display">
366
+ <span>Puntos:</span>
367
+ <span class="score-value" id="score">0</span>
368
+ </div>
369
+ <div class="level-display">
370
+ <span>Nivel:</span>
371
+ <span class="level-value" id="level">1</span>
372
+ </div>
373
+ <div class="lines-display">
374
+ <span>Líneas:</span>
375
+ <span class="lines-value" id="lines">0</span>
376
+ </div>
377
+ </div>
378
+
379
+ <div class="info-panel next-piece-container">
380
+ <h2>Siguiente Pieza</h2>
381
+ <div class="next-piece-grid" id="nextPieceGrid"></div>
382
+ </div>
383
+
384
+ <div class="info-panel controls">
385
+ <button class="control-button play" id="startBtn">Iniciar Juego</button>
386
+ <button class="control-button pause" id="pauseBtn">Pausar</button>
387
+ <div class="instructions">
388
+ <p><strong>Controles:</strong></p>
389
+ <p>← → Mover</p>
390
+ <p>↑ Rotar</p>
391
+ <p>↓ Bajar rápido</p>
392
+ <p>Espacio: Dropear</p>
393
+ </div>
394
+ </div>
395
+
396
+ <div class="mobile-controls">
397
+ <div class="control-row">
398
+ <div class="mobile-button" id="rotateBtn">↻</div>
399
+ </div>
400
+ <div class="control-row">
401
+ <div class="mobile-button" id="leftBtn">←</div>
402
+ <div class="mobile-button" id="downBtn">↓</div>
403
+ <div class="mobile-button" id="rightBtn">→</div>
404
+ </div>
405
+ <div class="control-row">
406
+ <div class="mobile-button" id="dropBtn">⇓</div>
407
+ </div>
408
+ </div>
409
+ </aside>
410
+ </main>
411
+
412
+ <div class="game-over" id="gameOver">
413
+ <h2>¡Juego Terminado!</h2>
414
+ <p>Puntuación final: <span id="finalScore">0</span></p>
415
+ <button class="control-button play" id="restartBtn">Reiniciar</button>
416
+ </div>
417
+
418
+ <script>
419
+ class Tetris {
420
+ constructor() {
421
+ this.grid = document.getElementById('gameGrid');
422
+ this.nextPieceGrid = document.getElementById('nextPieceGrid');
423
+ this.scoreElement = document.getElementById('score');
424
+ this.levelElement = document.getElementById('level');
425
+ this.linesElement = document.getElementById('lines');
426
+ this.gameOverElement = document.getElementById('gameOver');
427
+ this.finalScoreElement = document.getElementById('finalScore');
428
+
429
+ this.board = [];
430
+ this.currentPiece = null;
431
+ this.nextPiece = null;
432
+ this.score = 0;
433
+ this.level = 1;
434
+ this.lines = 0;
435
+ this.gameRunning = false;
436
+ this.gamePaused = false;
437
+ this.dropInterval = null;
438
+ this.dropSpeed = 1000;
439
+
440
+ this.boardWidth = 10;
441
+ this.boardHeight = 20;
442
+
443
+ this.pieces = [
444
+ { name: 'I', shape: [[1,1,1,1]], color: 'I' },
445
+ { name: 'O', shape: [[1,1],[1,1]], color: 'O' },
446
+ { name: 'T', shape: [[0,1,0],[1,1,1]], color: 'T' },
447
+ { name: 'S', shape: [[0,1,1],[1,1,0]], color: 'S' },
448
+ { name: 'Z', shape: [[1,1,0],[0,1,1]], color: 'Z' },
449
+ { name: 'J', shape: [[1,0,0],[1,1,1]], color: 'J' },
450
+ { name: 'L', shape: [[0,0,1],[1,1,1]], color: 'L' }
451
+ ];
452
+
453
+ this.init();
454
+ }
455
+
456
+ init() {
457
+ this.createBoard();
458
+ this.setupEventListeners();
459
+ this.renderNextPiece();
460
+ }
461
+
462
+ createBoard() {
463
+ this.board = Array(this.boardHeight).fill().map(() => Array(this.boardWidth).fill(0));
464
+ this.grid.innerHTML = '';
465
+
466
+ for (let y = 0; y < this.boardHeight; y++) {
467
+ for (let x = 0; x < this.boardWidth; x++) {
468
+ const cell = document.createElement('div');
469
+ cell.className = 'cell';
470
+ cell.dataset.x = x;
471
+ cell.dataset.y = y;
472
+ this.grid.appendChild(cell);
473
+ }
474
+ }
475
+ }
476
+
477
+ setupEventListeners() {
478
+ document.getElementById('startBtn').addEventListener('click', () => this.startGame());
479
+ document.getElementById('pauseBtn').addEventListener('click', () => this.togglePause());
480
+ document.getElementById('restartBtn').addEventListener('click', () => this.restartGame());
481
+
482
+ // Mobile controls
483
+ document.getElementById('rotateBtn').addEventListener('click', () => this.rotatePiece());
484
+ document.getElementById('leftBtn').addEventListener('click', () => this.movePiece(-1, 0));
485
+ document.getElementById('rightBtn').addEventListener('click', () => this.movePiece(1, 0));
486
+ document.getElementById('downBtn').addEventListener('click', () => this.movePiece(0, 1));
487
+ document.getElementById('dropBtn').addEventListener('click', () => this.dropPiece());
488
+
489
+ document.addEventListener('keydown', (e) => {
490
+ if (!this.gameRunning || this.gamePaused) return;
491
+
492
+ switch(e.key) {
493
+ case 'ArrowLeft':
494
+ e.preventDefault();
495
+ this.movePiece(-1, 0);
496
+ break;
497
+ case 'ArrowRight':
498
+ e.preventDefault();
499
+ this.movePiece(1, 0);
500
+ break;
501
+ case 'ArrowDown':
502
+ e.preventDefault();
503
+ this.movePiece(0, 1);
504
+ break;
505
+ case 'ArrowUp':
506
+ e.preventDefault();
507
+ this.rotatePiece();
508
+ break;
509
+ case ' ':
510
+ e.preventDefault();
511
+ this.dropPiece();
512
+ break;
513
+ }
514
+ });
515
+ }
516
+
517
+ startGame() {
518
+ if (this.gameRunning) return;
519
+
520
+ this.gameRunning = true;
521
+ this.gamePaused = false;
522
+ this.score = 0;
523
+ this.level = 1;
524
+ this.lines = 0;
525
+ this.dropSpeed = 1000;
526
+ this.updateScore();
527
+ this.createBoard();
528
+ this.spawnPiece();
529
+ this.startDrop();
530
+ }
531
+
532
+ togglePause() {
533
+ if (!this.gameRunning) return;
534
+
535
+ this.gamePaused = !this.gamePaused;
536
+ if (this.gamePaused) {
537
+ clearInterval(this.dropInterval);
538
+ } else {
539
+ this.startDrop();
540
+ }
541
+ }
542
+
543
+ restartGame() {
544
+ this.gameOverElement.style.display = 'none';
545
+ this.startGame();
546
+ }
547
+
548
+ spawnPiece() {
549
+ if (!this.nextPiece) {
550
+ this.nextPiece = this.getRandomPiece();
551
+ }
552
+
553
+ this.currentPiece = {
554
+ ...this.nextPiece,
555
+ x: Math.floor(this.boardWidth / 2) - Math.floor(this.nextPiece.shape[0].length / 2),
556
+ y: 0
557
+ };
558
+
559
+ this.nextPiece = this.getRandomPiece();
560
+ this.renderNextPiece();
561
+
562
+ if (this.collision()) {
563
+ this.endGame();
564
+ }
565
+ }
566
+
567
+ getRandomPiece() {
568
+ const piece = this.pieces[Math.floor(Math.random() * this.pieces.length)];
569
+ return {
570
+ shape: piece.shape,
571
+ color: piece.color,
572
+ name: piece.name
573
+ };
574
+ }
575
+
576
+ renderNextPiece() {
577
+ this.nextPieceGrid.innerHTML = '';
578
+
579
+ for (let y = 0; y < 4; y++) {
580
+ for (let x = 0; x < 4; x++) {
581
+ const cell = document.createElement('div');
582
+ cell.className = 'next-cell';
583
+
584
+ if (this.nextPiece &&
585
+ y < this.nextPiece.shape.length &&
586
+ x < this.nextPiece.shape[0].length &&
587
+ this.nextPiece.shape[y][x]) {
588
+ cell.classList.add('filled', `cell.${this.nextPiece.color}`);
589
+ }
590
+
591
+ this.nextPieceGrid.appendChild(cell);
592
+ }
593
+ }
594
+ }
595
+
596
+ startDrop() {
597
+ clearInterval(this.dropInterval);
598
+ this.dropInterval = setInterval(() => {
599
+ this.movePiece(0, 1);
600
+ }, this.dropSpeed);
601
+ }
602
+
603
+ movePiece(dx, dy) {
604
+ if (!this.currentPiece || this.gamePaused) return;
605
+
606
+ this.currentPiece.x += dx;
607
+ this.currentPiece.y += dy;
608
+
609
+ if (this.collision()) {
610
+ this.currentPiece.x -= dx;
611
+ this.currentPiece.y -= dy;
612
+
613
+ if (dy > 0) {
614
+ this.lockPiece();
615
+ }
616
+ }
617
+
618
+ this.render();
619
+ }
620
+
621
+ rotatePiece() {
622
+ if (!this.currentPiece || this.gamePaused) return;
623
+
624
+ const rotated = this.rotateMatrix(this.currentPiece.shape);
625
+ const previousShape = this.currentPiece.shape;
626
+ this.currentPiece.shape = rotated;
627
+
628
+ if (this.collision()) {
629
+ this.currentPiece.shape = previousShape;
630
+ } else {
631
+ this.render();
632
+ }
633
+ }
634
+
635
+ rotateMatrix(matrix) {
636
+ const rows = matrix.length;
637
+ const cols = matrix[0].length;
638
+ const rotated = Array(cols).fill().map(() => Array(rows).fill(0));
639
+
640
+ for (let i = 0; i < rows; i++) {
641
+ for (let j = 0; j < cols; j++) {
642
+ rotated[j][rows - 1 - i] = matrix[i][j];
643
+ }
644
+ }
645
+
646
+ return rotated;
647
+ }
648
+
649
+ dropPiece() {
650
+ if (!this.currentPiece || this.gamePaused) return;
651
+
652
+ while (!this.collision()) {
653
+ this.currentPiece.y++;
654
+ }
655
+ this.currentPiece.y--;
656
+ this.lockPiece();
657
+ }
658
+
659
+ collision() {
660
+ for (let y = 0; y < this.currentPiece.shape.length; y++) {
661
+ for (let x = 0; x < this.currentPiece.shape[y].length; x++) {
662
+ if (this.currentPiece.shape[y][x]) {
663
+ const boardX = this.currentPiece.x + x;
664
+ const boardY = this.currentPiece.y + y;
665
+
666
+ if (boardX < 0 || boardX >= this.boardWidth ||
667
+ boardY >= this.boardHeight ||
668
+ (boardY >= 0 && this.board[boardY][boardX])) {
669
+ return true;
670
+ }
671
+ }
672
+ }
673
+ }
674
+ return false;
675
+ }
676
+
677
+ lockPiece() {
678
+ for (let y = 0; y < this.currentPiece.shape.length; y++) {
679
+ for (let x = 0; x < this.currentPiece.shape[y].length; x++) {
680
+ if (this.currentPiece.shape[y][x]) {
681
+ const boardY = this.currentPiece.y + y;
682
+ const boardX = this.currentPiece.x + x;
683
+
684
+ if (boardY >= 0) {
685
+ this.board[boardY][boardX] = this.currentPiece.color;
686
+ }
687
+ }
688
+ }
689
+ }
690
+
691
+ this.clearLines();
692
+ this.spawnPiece();
693
+ }
694
+
695
+ clearLines() {
696
+ let linesCleared = 0;
697
+
698
+ for (let y = this.boardHeight - 1; y >= 0; y--) {
699
+ if (this.board[y].every(cell => cell !== 0)) {
700
+ this.board.splice(y, 1);
701
+ this.board.unshift(Array(this.boardWidth).fill(0));
702
+ linesCleared++;
703
+ y++;
704
+ }
705
+ }
706
+
707
+ if (linesCleared > 0) {
708
+ this.lines += linesCleared;
709
+ this.score += linesCleared * 100 * this.level;
710
+
711
+ if (this.lines >= this.level * 10) {
712
+ this.level++;
713
+ this.dropSpeed = Math.max(100, this.dropSpeed - 100);
714
+ if (this.gameRunning && !this.gamePaused) {
715
+ this.startDrop();
716
+ }
717
+ }
718
+
719
+ this.updateScore();
720
+ this.createParticles();
721
+ }
722
+ }
723
+
724
+ createParticles() {
725
+ const colors = ['var(--tetris-blue)', 'var(--tetris-purple)', 'var(--tetris-yellow)',
726
+ 'var(--tetris-green)', 'var(--tetris-red)', 'var(--tetris-orange)'];
727
+
728
+ for (let i = 0; i < 10; i++) {
729
+ const particle = document.createElement('div');
730
+ particle.className = 'particle';
731
+ particle.style.left = Math.random() * window.innerWidth + 'px';
732
+ particle.style.top = window.innerHeight / 2 + 'px';
733
+ particle.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
734
+ particle.style.width = Math.random() * 10 + 5 + 'px';
735
+ particle.style.height = particle.style.width;
736
+
737
+ document.body.appendChild(particle);
738
+
739
+ setTimeout(() => particle.remove(), 1000);
740
+ }
741
+ }
742
+
743
+ updateScore() {
744
+ this.scoreElement.textContent = this.score;
745
+ this.levelElement.textContent = this.level;
746
+ this.linesElement.textContent = this.lines;
747
+ }
748
+
749
+ render() {
750
+ const cells = this.grid.querySelectorAll('.cell');
751
+
752
+ cells.forEach(cell => {
753
+ cell.className = 'cell';
754
+ });
755
+
756
+ // Render locked pieces
757
+ for (let y = 0; y < this.boardHeight; y++) {
758
+ for (let x = 0; x < this.boardWidth; x++) {
759
+ if (this.board[y][x]) {
760
+ const index = y * this.boardWidth + x;
761
+ cells[index].classList.add('filled', `cell.${this.board[y][x]}`);
762
+ }
763
+ }
764
+ }
765
+
766
+ // Render current piece
767
+ if (this.currentPiece) {
768
+ for (let y = 0; y < this.currentPiece.shape.length; y++) {
769
+ for (let x = 0; x < this.currentPiece.shape[y].length; x++) {
770
+ if (this.currentPiece.shape[y][x]) {
771
+ const boardX = this.currentPiece.x + x;
772
+ const boardY = this.currentPiece.y + y;
773
+
774
+ if (boardY >= 0 && boardY < this.boardHeight &&
775
+ boardX >= 0 && boardX < this.boardWidth) {
776
+ const index = boardY * this.boardWidth + boardX;
777
+ cells[index].classList.add('filled', `cell.${this.currentPiece.color}`);
778
+ }
779
+ }
780
+ }
781
+ }
782
+ }
783
+ }
784
+
785
+ endGame() {
786
+ this.gameRunning = false;
787
+ clearInterval(this.dropInterval);
788
+ this.finalScoreElement.textContent = this.score;
789
+ this.gameOverElement.style.display = 'block';
790
+ }
791
+ }
792
+
793
+ // Initialize the game when the page loads
794
+ document.addEventListener('DOMContentLoaded', () => {
795
+ new Tetris();
796
+ });
797
+ </script>
798
+ </body>
799
+ </html>