samirerty commited on
Commit
93ea218
·
verified ·
1 Parent(s): 73fdb4f

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +575 -570
index.html CHANGED
@@ -1,597 +1,602 @@
1
  <!DOCTYPE html>
2
  <html lang="fa" dir="rtl">
3
-
4
  <head>
5
- <meta charset="UTF-8">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>بازی حافظه سکسی (Sexi Memory)</title>
8
- <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
9
- <style>
10
- :root {
11
- --primary-color: #ff0040; /* Hot Pink/Red */
12
- --secondary-color: #2a0a15; /* Dark Red/Burgundy */
13
- --accent-color: #ff6b81;
14
- --bg-gradient: linear-gradient(135deg, #000000, #2a0a15, #4a1220);
15
- --card-bg: #1a0510;
16
- --text-color: #ffffff;
17
- --glow: 0 0 20px rgba(255, 0, 64, 0.7);
18
- --font-main: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
19
- }
20
-
21
- * {
22
- box-sizing: border-box;
23
- margin: 0;
24
- padding: 0;
25
- font-family: var(--font-main);
26
- }
27
-
28
- body {
29
- background: var(--bg-gradient);
30
- color: var(--text-color);
31
- min-height: 100vh;
32
- display: flex;
33
- flex-direction: column;
34
- align-items: center;
35
- justify-content: center;
36
- overflow-x: hidden;
37
- background-attachment: fixed;
38
- }
39
-
40
- /* Background Animation Effect */
41
- body::before {
42
- content: '';
43
- position: fixed;
44
- top: 0;
45
- left: 0;
46
- width: 100%;
47
- height: 100%;
48
- background-image: radial-gradient(var(--primary-color) 1px, transparent 1px);
49
- background-size: 30px 30px;
50
- opacity: 0.05;
51
- z-index: -1;
52
- }
53
-
54
- /* Header Section */
55
- header {
56
- text-align: center;
57
- margin-bottom: 30px;
58
- animation: fadeInDown 1s ease;
59
- position: relative;
60
- }
61
-
62
- h1 {
63
- font-size: 4.5rem;
64
- font-weight: 900;
65
- text-transform: uppercase;
66
- letter-spacing: 5px;
67
- color: var(--primary-color);
68
- text-shadow: var(--glow);
69
- margin-bottom: 10px;
70
- text-transform: uppercase;
71
- }
72
-
73
- h1 i {
74
- animation: pulse 2s infinite;
75
- }
76
-
77
- .subtitle {
78
- font-size: 1.2rem;
79
- color: var(--accent-color);
80
- letter-spacing: 2px;
81
- text-transform: uppercase;
82
- }
83
-
84
- /* Score Board */
85
- .scoreboard {
86
- display: flex;
87
- gap: 40px;
88
- margin-bottom: 30px;
89
- background: rgba(0, 0, 0, 0.6);
90
- padding: 20px 50px;
91
- border-radius: 60px;
92
- backdrop-filter: blur(10px);
93
- border: 2px solid var(--primary-color);
94
- box-shadow: var(--glow);
95
- transition: transform 0.3s ease;
96
- }
97
-
98
- .scoreboard:hover {
99
- transform: scale(1.05);
100
- }
101
-
102
- .player-score {
103
- text-align: center;
104
- min-width: 120px;
105
- }
106
-
107
- .player-name {
108
- font-size: 1.3rem;
109
- font-weight: bold;
110
- color: var(--primary-color);
111
- text-transform: uppercase;
112
- margin-bottom: 5px;
113
- }
114
-
115
- .active-player {
116
- color: #fff !important;
117
- text-shadow: 0 0 10px var(--primary-color);
118
- }
119
-
120
- .score-value {
121
- font-size: 3rem;
122
- font-weight: 800;
123
- line-height: 1;
124
- color: #fff;
125
- }
126
-
127
- /* Game Grid */
128
- .game-container {
129
- perspective: 1000px;
130
- margin-bottom: 30px;
131
- padding: 20px;
132
- background: rgba(255, 0, 64, 0.05);
133
- border-radius: 20px;
134
- border: 1px solid rgba(255, 0, 64, 0.2);
135
- }
136
-
137
- .grid {
138
- display: grid;
139
- grid-template-columns: repeat(4, 1fr);
140
- gap: 15px;
141
- width: 95%;
142
- max-width: 700px;
143
- margin: 0 auto;
144
- }
145
-
146
- /* Card Styles */
147
- .card {
148
- width: 100%;
149
- aspect-ratio: 3/4; /* Portrait aspect ratio */
150
- position: relative;
151
- cursor: pointer;
152
- transform-style: preserve-3d;
153
- transition: transform 0.7s cubic-bezier(0.175, 0.885, 0.32, 1.275);
154
- border-radius: 10px;
155
- }
156
-
157
- .card.flipped {
158
- transform: rotateY(180deg);
159
- }
160
-
161
- .card.matched {
162
- animation: pulse 1.5s infinite alternate;
163
- box-shadow: 0 0 20px var(--primary-color);
164
- }
165
-
166
- .card-face {
167
- position: absolute;
168
- width: 100%;
169
- height: 100%;
170
- backface-visibility: hidden;
171
- border-radius: 10px;
172
- display: flex;
173
- align-items: center;
174
- justify-content: center;
175
- overflow: hidden;
176
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
177
- border: 2px solid var(--primary-color);
178
- }
179
-
180
- .card-front {
181
- background: var(--secondary-color);
182
- background-image: url("data:image/svg+xml,%3Csvg width='20' height='20' viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23ff0040' fill-opacity='0.3' fill-rule='evenodd'%3E%3Cpath d='M10 0l2.5 7.5L20 10l-7.5 2.5L10 20l-2.5-7.5L0 10l7.5-2.5L10 0z'/%3E%3C/g%3E%3C/svg%3E");
183
- transform: rotateY(0deg);
184
- }
185
-
186
- .card-front i {
187
- font-size: 3rem;
188
- color: rgba(255, 0, 64, 0.8);
189
- transition: transform 0.5s;
190
- }
191
-
192
- .card:hover .card-front i {
193
- transform: scale(1.2) rotate(10deg);
194
- }
195
-
196
- .card-back {
197
- background: #fff;
198
- transform: rotateY(180deg);
199
- padding: 5px;
200
- }
201
-
202
- .card-back img {
203
- width: 100%;
204
- height: 100%;
205
- object-fit: cover;
206
- border-radius: 6px;
207
- box-shadow: 0 0 15px rgba(255, 0, 64, 0.6);
208
- }
209
-
210
- /* Controls */
211
- .controls {
212
- display: flex;
213
- gap: 20px;
214
- margin-top: 20px;
215
- }
216
-
217
- button {
218
- padding: 15px 40px;
219
- font-size: 1.2rem;
220
- border: 2px solid var(--primary-color);
221
- border-radius: 50px;
222
- cursor: pointer;
223
- transition: all 0.3s ease;
224
- font-weight: bold;
225
- text-transform: uppercase;
226
- letter-spacing: 2px;
227
- outline: none;
228
- background: transparent;
229
- color: var(--primary-color);
230
- position: relative;
231
- overflow: hidden;
232
- }
233
-
234
- button:hover {
235
- background: var(--primary-color);
236
- color: white;
237
- box-shadow: var(--glow);
238
- transform: translateY(-3px) scale(1.05);
239
- }
240
-
241
- button:active {
242
- transform: translateY(1px);
243
- }
244
-
245
- /* Modal */
246
- .modal {
247
- position: fixed;
248
- top: 0;
249
- left: 0;
250
- width: 100%;
251
- height: 100%;
252
- background: rgba(0, 0, 0, 0.9);
253
- display: flex;
254
- align-items: center;
255
- justify-content: center;
256
- z-index: 100;
257
- opacity: 0;
258
- pointer-events: none;
259
- transition: opacity 0.5s ease;
260
- backdrop-filter: blur(5px);
261
- }
262
-
263
- .modal.active {
264
- opacity: 1;
265
- pointer-events: all;
266
- }
267
-
268
- .modal-content {
269
- background: #fff;
270
- color: #333;
271
- padding: 50px;
272
- border-radius: 20px;
273
- text-align: center;
274
- max-width: 500px;
275
- width: 90%;
276
- box-shadow: 0 0 50px var(--primary-color);
277
- animation: zoomIn 0.6s cubic-bezier(0.68, -0.55, 0.27, 1.55);
278
- border-top: 5px solid var(--primary-color);
279
- }
280
-
281
- .winner-text {
282
- font-size: 3rem;
283
- color: var(--secondary-color);
284
- margin-bottom: 20px;
285
- font-weight: 900;
286
- }
287
-
288
- .final-score {
289
- font-size: 1.5rem;
290
- margin-bottom: 30px;
291
- color: #555;
292
- line-height: 1.6;
293
- }
294
-
295
- .winner-badge {
296
- font-size: 4rem;
297
- margin-bottom: 20px;
298
- display: block;
299
- }
300
-
301
- /* Animations */
302
- @keyframes fadeInDown {
303
- from { opacity: 0; transform: translateY(-30px); }
304
- to { opacity: 1; transform: translateY(0); }
305
- }
306
-
307
- @keyframes pulse {
308
- from { box-shadow: 0 0 10px var(--primary-color); transform: rotateY(180deg) scale(1); }
309
- to { box-shadow: 0 0 30px var(--accent-color); transform: rotateY(180deg) scale(1.05); }
310
- }
311
-
312
- @keyframes zoomIn {
313
- from { opacity: 0; transform: scale(0.5) translateY(50px); }
314
- to { opacity: 1; transform: scale(1) translateY(0); }
315
- }
316
-
317
- /* Responsive */
318
- @media (max-width: 600px) {
319
- .grid {
320
- grid-template-columns: repeat(4, 1fr);
321
- gap: 10px;
322
- }
323
-
324
- .card {
325
- aspect-ratio: 1/1; /* Square on mobile */
326
- }
327
-
328
- h1 { font-size: 2.5rem; }
329
-
330
- .scoreboard { padding: 10px 20px; gap: 20px; width: 90%; }
331
- .score-value { font-size: 2rem; }
332
- .player-name { font-size: 1rem; }
333
-
334
- .modal-content { padding: 30px; }
335
- .winner-text { font-size: 2rem; }
336
- }
337
- </style>
338
- </head>
339
 
340
- <body>
 
 
 
 
341
 
342
- <header>
343
- <h1><i class="fas fa-heart"></i> سکسی <i class="fas fa-fire"></i></h1>
344
- <div class="subtitle">بازی حافظه و هیجان</div>
345
- </header>
 
 
 
 
 
 
 
 
 
346
 
347
- <div class="scoreboard">
348
- <div class="player-score" id="p1-box">
349
- <div class="player-name active-player" id="name-p1">بازیکن ۱</div>
350
- <div class="score-value" id="score-p1">0</div>
351
- </div>
352
- <div class="player-score" id="p2-box">
353
- <div class="player-name" id="name-p2">بازیکن ۲</div>
354
- <div class="score-value" id="score-p2">0</div>
355
- </div>
356
- </div>
 
 
 
357
 
358
- <div class="game-container">
359
- <div class="grid" id="game-grid">
360
- <!-- Cards will be generated here -->
361
- </div>
362
- </div>
363
-
364
- <div class="controls">
365
- <button class="btn-restart" onclick="resetGame()">
366
- <i class="fas fa-redo"></i> شروع مجدد بازی
367
- </button>
368
- </div>
369
-
370
- <!-- Winner Modal -->
371
- <div class="modal" id="winnerModal">
372
- <div class="modal-content">
373
- <span class="winner-badge" id="winnerBadge">🏆</span>
374
- <div class="winner-text" id="winnerText">بازیکن ۱ برنده شد!</div>
375
- <div class="final-score" id="finalScoreText">
376
- <p>امتیاز بازیکن ۱: <span id="finalScoreP1">0</span></p>
377
- <p>امتیاز بازیکن ۲: <span id="finalScoreP2">0</span></p>
378
- </div>
379
- <button class="btn-restart" onclick="resetGame()">بازی بعدی</button>
380
- </div>
381
- </div>
382
-
383
- <script>
384
- // Game Configuration
385
- // Note: Using safe, high-quality fashion/beach stock images to represent the theme
386
- // In a real production app, you would host these locally or use licensed assets.
387
- const cardImages = [
388
- 'https://picsum.photos/id/237/300/400', // Fashion model 1
389
- 'https://picsum.photos/id/238/300/400', // Fashion model 2
390
- 'https://picsum.photos/id/239/300/400', // Fashion model 3
391
- 'https://picsum.photos/id/240/300/400', // Fashion model 4
392
- 'https://picsum.photos/id/241/300/400', // Fashion model 5
393
- 'https://picsum.photos/id/242/300/400', // Fashion model 6
394
- 'https://picsum.photos/id/243/300/400', // Fashion model 7
395
- 'https://picsum.photos/id/244/300/400' // Fashion model 8
396
- ];
397
-
398
- // Duplicate images to create pairs
399
- let finalIcons = [...cardImages, ...cardImages];
400
-
401
- let cards = [];
402
- let flippedCards = [];
403
- let matchedPairs = 0;
404
- let currentPlayer = 1;
405
- let scores = { 1: 0, 2: 0 };
406
- let isProcessing = false;
407
-
408
- const gridElement = document.getElementById('game-grid');
409
- const scoreP1Element = document.getElementById('score-p1');
410
- const scoreP2Element = document.getElementById('score-p2');
411
- const modalElement = document.getElementById('winnerModal');
412
- const winnerTextElement = document.getElementById('winnerText');
413
- const finalScoreTextElement = document.getElementById('finalScoreText');
414
- const finalScoreP1 = document.getElementById('finalScoreP1');
415
- const finalScoreP2 = document.getElementById('finalScoreP2');
416
- const p1Box = document.getElementById('p1-box');
417
- const p2Box = document.getElementById('p2-box');
418
- const nameP1 = document.getElementById('name-p1');
419
- const nameP2 = document.getElementById('name-p2');
420
-
421
- // Initialize Game
422
- function initGame() {
423
- // Reset State
424
- flippedCards = [];
425
- matchedPairs = 0;
426
- currentPlayer = 1;
427
- scores = { 1: 0, 2: 0 };
428
- isProcessing = false;
429
-
430
- updateScoreboard();
431
- modalElement.classList.remove('active');
432
- updateActivePlayerUI();
433
-
434
- // Shuffle Cards
435
- const shuffledIcons = [...finalIcons].sort(() => Math.random() - 0.5);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
436
 
437
- // Clear Grid
438
- gridElement.innerHTML = '';
439
-
440
- // Create Cards
441
- shuffledIcons.forEach((imgSrc, index) => {
442
- const card = document.createElement('div');
443
- card.classList.add('card');
444
- card.dataset.index = index;
445
-
446
- const frontFace = document.createElement('div');
447
- frontFace.classList.add('card-face', 'card-front');
448
- frontFace.innerHTML = '<i class="fas fa-fire"></i>'; // Design for back of card
449
-
450
- const backFace = document.createElement('div');
451
- backFace.classList.add('card-face', 'card-back');
452
- const img = document.createElement('img');
453
- img.src = imgSrc;
454
- img.alt = "Card Image";
455
- img.loading = "lazy"; // Performance optimization
456
- backFace.appendChild(img);
457
-
458
- card.appendChild(frontFace);
459
- card.appendChild(backFace);
460
-
461
- card.addEventListener('click', () => flipCard(card));
462
- gridElement.appendChild(card);
463
- });
464
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
465
 
466
- function flipCard(card) {
467
- // Validation: Don't flip if already processing, already flipped, or matched
468
- if (isProcessing || card.classList.contains('flipped') || card.classList.contains('matched')) {
469
- return;
 
 
 
 
470
  }
471
 
472
- card.classList.add('flipped');
473
- flippedCards.push(card);
 
474
 
475
- if (flippedCards.length === 2) {
476
- checkForMatch();
 
 
 
 
 
 
 
 
477
  }
478
- }
479
 
480
- function checkForMatch() {
481
- isProcessing = true;
482
- const [card1, card2] = flippedCards;
 
 
 
 
 
 
 
 
 
 
 
 
483
 
484
- if (card1.querySelector('img').src === card2.querySelector('img').src) {
485
- // Match Found
486
- handleMatch(card1, card2);
487
- } else {
488
- // No Match
489
- setTimeout(() => {
490
- card1.classList.remove('flipped');
491
- card2.classList.remove('flipped');
492
- flippedCards = [];
493
- isProcessing = false;
494
- switchPlayer();
495
- }, 1200); // Slightly longer delay for visual clarity
496
  }
497
- }
498
 
499
- function handleMatch(card1, card2) {
500
- // Increment Score
501
- scores[currentPlayer]++;
502
- updateScoreboard();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
503
 
504
- // Visual Feedback
505
- card1.classList.add('matched');
506
- card2.classList.add('matched');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
507
 
508
- flippedCards = [];
509
- matchedPairs++;
510
- isProcessing = false;
511
-
512
- // Check for Game Over
513
- if (matchedPairs === finalIcons.length / 2) {
514
- setTimeout(showGameOver, 800);
515
- }
516
- }
517
-
518
- function switchPlayer() {
519
- currentPlayer = currentPlayer === 1 ? 2 : 1;
520
- updateActivePlayerUI();
521
- }
522
-
523
- function updateActivePlayerUI() {
524
- if (currentPlayer === 1) {
525
- p1Box.style.borderColor = 'var(--primary-color)';
526
- p1Box.style.boxShadow = 'var(--glow)';
527
- p1Box.style.background = 'rgba(255, 0, 64, 0.1)';
528
 
529
- p2Box.style.borderColor = 'rgba(255,255,255,0.2)';
530
- p2Box.style.boxShadow = 'none';
531
- p2Box.style.background = 'rgba(0,0,0,0.6)';
532
-
533
- nameP1.classList.add('active-player');
534
- nameP2.classList.remove('active-player');
535
- } else {
536
- p2Box.style.borderColor = 'var(--primary-color)';
537
- p2Box.style.boxShadow = 'var(--glow)';
538
- p2Box.style.background = 'rgba(255, 0, 64, 0.1)';
539
 
540
- p1Box.style.borderColor = 'rgba(255,255,255,0.2)';
541
- p1Box.style.boxShadow = 'none';
542
- p1Box.style.background = 'rgba(0,0,0,0.6)';
 
 
 
 
543
 
544
- nameP2.classList.add('active-player');
545
- nameP1.classList.remove('active-player');
546
  }
547
- }
548
 
549
- function updateScoreboard() {
550
- scoreP1Element.innerText = scores[1];
551
- scoreP2Element.innerText = scores[2];
552
- }
 
 
 
 
 
 
 
 
 
553
 
554
- function showGameOver() {
555
- let winner = '';
556
- let winnerBadge = '';
557
-
558
- if (scores[1] > scores[2]) {
559
- winner = 'بازیکن ۱ برنده شد! 🌹';
560
- winnerBadge = '👑';
561
- } else if (scores[2] > scores[1]) {
562
- winner = 'بازیکن ۲ برنده شد! 💋';
563
- winnerBadge = '👑';
564
- } else {
565
- winner = 'متساوی شدید! 🤝';
566
- winnerBadge = '🤝';
567
- finalScoreTextElement.innerHTML = `<p>امتیاز نهایی: ${scores[1]}</p>`;
568
- }
569
-
570
- finalScoreP1.innerText = scores[1];
571
- finalScoreP2.innerText = scores[2];
572
-
573
- winnerTextElement.innerText = winner;
574
- document.getElementById('winnerBadge').innerText = winnerBadge;
575
-
576
- modalElement.classList.add('active');
577
-
578
- // Reset UI for next game
579
- setTimeout(() => {
580
- p1Box.style = '';
581
- p2Box.style = '';
582
- nameP1.classList.remove('active-player');
583
- nameP2.classList.remove('active-player');
584
- }, 100);
585
- }
586
-
587
- function resetGame() {
588
- initGame();
589
- }
590
-
591
- // Start the game on load
592
- window.onload = initGame;
593
-
594
- </script>
595
- </body>
596
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
597
  </html>
 
1
  <!DOCTYPE html>
2
  <html lang="fa" dir="rtl">
 
3
  <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6
+ <title>بازی ماشینی سرعتی (Top Down)</title>
7
+ <style>
8
+ @import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;700;900&display=swap');
9
+
10
+ :root {
11
+ --primary-color: #00f2ff;
12
+ --accent-color: #ff0055;
13
+ --road-color: #2a2a2a;
14
+ --grass-color: #1a4a1a;
15
+ --ui-bg: rgba(0, 0, 0, 0.85);
16
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
+ * {
19
+ box-sizing: border-box;
20
+ user-select: none;
21
+ -webkit-tap-highlight-color: transparent;
22
+ }
23
 
24
+ body {
25
+ margin: 0;
26
+ padding: 0;
27
+ background-color: #0f0f0f;
28
+ color: white;
29
+ font-family: 'Vazirmatn', sans-serif;
30
+ overflow: hidden;
31
+ display: flex;
32
+ flex-direction: column;
33
+ align-items: center;
34
+ justify-content: center;
35
+ height: 100vh;
36
+ }
37
 
38
+ /* Header & Credit */
39
+ header {
40
+ position: absolute;
41
+ top: 0;
42
+ left: 0;
43
+ width: 100%;
44
+ padding: 15px;
45
+ display: flex;
46
+ justify-content: space-between;
47
+ align-items: center;
48
+ z-index: 100;
49
+ pointer-events: none;
50
+ }
51
 
52
+ .game-title {
53
+ font-size: 1.5rem;
54
+ font-weight: 900;
55
+ text-transform: uppercase;
56
+ color: var(--primary-color);
57
+ text-shadow: 0 0 10px var(--primary-color);
58
+ }
59
+
60
+ .credit-link {
61
+ pointer-events: auto;
62
+ font-size: 0.8rem;
63
+ color: #aaa;
64
+ text-decoration: none;
65
+ background: rgba(255,255,255,0.1);
66
+ padding: 5px 10px;
67
+ border-radius: 15px;
68
+ transition: all 0.3s ease;
69
+ }
70
+
71
+ .credit-link:hover {
72
+ background: var(--primary-color);
73
+ color: #000;
74
+ box-shadow: 0 0 15px var(--primary-color);
75
+ }
76
+
77
+ /* Game Container */
78
+ #game-container {
79
+ position: relative;
80
+ width: 100%;
81
+ max-width: 450px;
82
+ height: 100vh;
83
+ max-height: 800px;
84
+ background-color: var(--road-color);
85
+ overflow: hidden;
86
+ box-shadow: 0 0 50px rgba(0,0,0,0.5);
87
+ border-left: 5px solid #111;
88
+ border-right: 5px solid #111;
89
+ }
90
+
91
+ /* Road Markings */
92
+ .road-line {
93
+ position: absolute;
94
+ width: 10px;
95
+ height: 100px;
96
+ background: rgba(255, 255, 255, 0.5);
97
+ left: 50%;
98
+ transform: translateX(-50%);
99
+ animation: moveRoad 1s linear infinite;
100
+ }
101
+
102
+ @keyframes moveRoad {
103
+ 0% { top: -100px; }
104
+ 100% { top: 100%; }
105
+ }
106
+
107
+ /* Player Car */
108
+ #player-car {
109
+ position: absolute;
110
+ bottom: 100px;
111
+ left: 50%;
112
+ width: 50px;
113
+ height: 90px;
114
+ background: linear-gradient(180deg, #ffcc00, #ff9900);
115
+ border-radius: 10px;
116
+ box-shadow: 0 10px 20px rgba(0,0,0,0.5);
117
+ z-index: 10;
118
+ transition: left 0.1s ease-out;
119
+ transform: translateX(-50%);
120
+ }
121
+
122
+ /* Car Details (Windshield, Lights) */
123
+ #player-car::before {
124
+ content: '';
125
+ position: absolute;
126
+ top: 20%;
127
+ left: 10%;
128
+ width: 80%;
129
+ height: 20%;
130
+ background: #333;
131
+ border-radius: 2px;
132
+ }
133
+ #player-car::after {
134
+ content: '';
135
+ position: absolute;
136
+ top: 0;
137
+ left: 5%;
138
+ width: 90%;
139
+ height: 10px;
140
+ background: #ff3333;
141
+ box-shadow: 0 0 10px #ff0000;
142
+ border-radius: 5px 5px 0 0;
143
+ }
144
+
145
+ /* Enemy Cars */
146
+ .enemy {
147
+ position: absolute;
148
+ width: 50px;
149
+ height: 90px;
150
+ border-radius: 10px;
151
+ box-shadow: 0 5px 15px rgba(0,0,0,0.5);
152
+ z-index: 9;
153
+ top: -100px;
154
+ }
155
 
156
+ .enemy::before {
157
+ content: '';
158
+ position: absolute;
159
+ bottom: 20%;
160
+ left: 10%;
161
+ width: 80%;
162
+ height: 20%;
163
+ background: #222;
164
+ border-radius: 2px;
165
+ }
166
+
167
+ /* UI Overlays */
168
+ .overlay {
169
+ position: absolute;
170
+ top: 0;
171
+ left: 0;
172
+ width: 100%;
173
+ height: 100%;
174
+ background: var(--ui-bg);
175
+ display: flex;
176
+ flex-direction: column;
177
+ align-items: center;
178
+ justify-content: center;
179
+ z-index: 50;
180
+ backdrop-filter: blur(5px);
181
+ transition: opacity 0.3s;
182
+ }
183
+
184
+ .hidden {
185
+ opacity: 0;
186
+ pointer-events: none;
187
+ }
188
+
189
+ h1 {
190
+ font-size: 3rem;
191
+ margin-bottom: 10px;
192
+ color: var(--primary-color);
193
+ text-shadow: 2px 2px 0px var(--accent-color);
194
+ text-align: center;
195
+ }
196
+
197
+ p {
198
+ font-size: 1.2rem;
199
+ margin-bottom: 30px;
200
+ color: #ddd;
201
+ text-align: center;
202
+ max-width: 80%;
203
+ }
204
+
205
+ .btn {
206
+ background: var(--accent-color);
207
+ color: white;
208
+ padding: 15px 40px;
209
+ font-size: 1.5rem;
210
+ font-family: 'Vazirmatn', sans-serif;
211
+ border: none;
212
+ border-radius: 50px;
213
+ cursor: pointer;
214
+ box-shadow: 0 0 20px var(--accent-color);
215
+ transition: transform 0.2s, box-shadow 0.2s;
216
+ font-weight: 700;
217
+ }
218
+
219
+ .btn:hover {
220
+ transform: scale(1.05);
221
+ box-shadow: 0 0 30px var(--accent-color);
222
+ }
223
+
224
+ .btn:active {
225
+ transform: scale(0.95);
226
+ }
227
+
228
+ /* HUD (Heads Up Display) */
229
+ #hud {
230
+ position: absolute;
231
+ top: 20px;
232
+ left: 20px;
233
+ right: 20px;
234
+ display: flex;
235
+ justify-content: space-between;
236
+ pointer-events: none;
237
+ z-index: 20;
238
+ }
239
 
240
+ .stat-box {
241
+ background: rgba(0,0,0,0.6);
242
+ padding: 10px 20px;
243
+ border-radius: 20px;
244
+ border: 1px solid rgba(255,255,255,0.2);
245
+ font-size: 1.5rem;
246
+ font-weight: bold;
247
+ color: white;
248
  }
249
 
250
+ #score-display span, #speed-display span {
251
+ color: var(--primary-color);
252
+ }
253
 
254
+ /* Mobile Controls */
255
+ #mobile-controls {
256
+ position: absolute;
257
+ bottom: 20px;
258
+ width: 100%;
259
+ display: flex;
260
+ justify-content: space-between;
261
+ padding: 0 20px;
262
+ z-index: 40;
263
+ pointer-events: none; /* Let clicks pass through empty space */
264
  }
 
265
 
266
+ .control-btn {
267
+ width: 80px;
268
+ height: 80px;
269
+ background: rgba(255, 255, 255, 0.15);
270
+ border: 2px solid rgba(255, 255, 255, 0.3);
271
+ border-radius: 50%;
272
+ display: flex;
273
+ align-items: center;
274
+ justify-content: center;
275
+ font-size: 2rem;
276
+ color: white;
277
+ pointer-events: auto;
278
+ transition: background 0.2s;
279
+ touch-action: manipulation;
280
+ }
281
 
282
+ .control-btn:active {
283
+ background: rgba(255, 255, 255, 0.4);
 
 
 
 
 
 
 
 
 
 
284
  }
 
285
 
286
+ .control-btn.left:active { border-color: var(--primary-color); }
287
+ .control-btn.right:active { border-color: var(--primary-color); }
288
+
289
+ /* Responsive adjustments */
290
+ @media (min-width: 768px) {
291
+ #mobile-controls { display: none; } /* Hide touch controls on desktop */
292
+ h1 { font-size: 4rem; }
293
+ }
294
+ </style>
295
+ </head>
296
+ <body>
297
+
298
+ <header>
299
+ <div class="game-title">بازی ماشینی 🏎️</div>
300
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="credit-link">Built with anycoder</a>
301
+ </header>
302
+
303
+ <div id="game-container">
304
+ <!-- Road Lines Animation -->
305
+ <div class="road-line" style="animation-delay: 0s;"></div>
306
+ <div class="road-line" style="animation-delay: 0.5s;"></div>
307
+
308
+ <!-- HUD -->
309
+ <div id="hud">
310
+ <div class="stat-box" id="score-display">امتیاز: <span id="score">0</span></div>
311
+ <div class="stat-box" id="speed-display">سرعت: <span id="speed">100</span> کیلومتر</div>
312
+ </div>
313
+
314
+ <!-- Player Car -->
315
+ <div id="player-car"></div>
316
+
317
+ <!-- Start Screen -->
318
+ <div id="start-screen" class="overlay">
319
+ <h1>تک سواست</h1>
320
+ <p>از موانع عبور کنید و امتیاز بگیرید.<br>برای حرکت از کلیدهای جهت‌نما یا دکمه‌های صفحه استفاده کنید.</p>
321
+ <button class="btn" onclick="startGame()">شروع بازی</button>
322
+ </div>
323
+
324
+ <!-- Game Over Screen -->
325
+ <div id="game-over-screen" class="overlay hidden">
326
+ <h1 style="color: var(--accent-color);">تصادف کردید!</h1>
327
+ <p>امتیاز نهایی شما: <span id="final-score" style="color: var(--primary-color); font-weight: bold;">0</span></p>
328
+ <button class="btn" onclick="resetGame()">بازی مجدد</button>
329
+ </div>
330
+
331
+ <!-- Mobile Controls -->
332
+ <div id="mobile-controls">
333
+ <div class="control-btn left" id="btn-left">◀</div>
334
+ <div class="control-btn right" id="btn-right">▶</div>
335
+ </div>
336
+ </div>
337
+
338
+ <script>
339
+ // --- Game Configuration & State ---
340
+ const gameContainer = document.getElementById('game-container');
341
+ const playerCar = document.getElementById('player-car');
342
+ const scoreEl = document.getElementById('score');
343
+ const finalScoreEl = document.getElementById('final-score');
344
+ const speedEl = document.getElementById('speed');
345
+ const startScreen = document.getElementById('start-screen');
346
+ const gameOverScreen = document.getElementById('game-over-screen');
347
+
348
+ let gameActive = false;
349
+ let score = 0;
350
+ let gameSpeed = 5;
351
+ let lane = 1; // 0: Left, 1: Center, 2: Right (approximate percentages)
352
+ let playerX = 50; // Percentage
353
+ let enemies = [];
354
+ let roadLines = [];
355
+ let animationId;
356
+ let spawnInterval;
357
+ let speedInterval;
358
+
359
+ // Constants
360
+ const CONTAINER_WIDTH = 450; // Max width in pixels
361
+ const CAR_WIDTH = 50;
362
+ const LANE_WIDTH_PERCENT = 33.33;
363
+ const BASE_SPEED = 5;
364
+ const MAX_SPEED = 20;
365
+
366
+ // --- Input Handling ---
367
 
368
+ // Keyboard
369
+ document.addEventListener('keydown', (e) => {
370
+ if (!gameActive) return;
371
+ if (e.key === 'ArrowLeft' || e.key === 'a') moveCar(-1);
372
+ if (e.key === 'ArrowRight' || e.key === 'd') moveCar(1);
373
+ });
374
+
375
+ // Touch / Mouse for Mobile Controls
376
+ const btnLeft = document.getElementById('btn-left');
377
+ const btnRight = document.getElementById('btn-right');
378
+
379
+ const handleInputStart = (direction) => {
380
+ if (!gameActive) return;
381
+ moveCar(direction);
382
+ };
383
+
384
+ // Add touch listeners
385
+ btnLeft.addEventListener('touchstart', (e) => { e.preventDefault(); handleInputStart(-1); });
386
+ btnRight.addEventListener('touchstart', (e) => { e.preventDefault(); handleInputStart(1); });
387
 
388
+ // Add mouse listeners for testing on desktop with mouse
389
+ btnLeft.addEventListener('mousedown', () => handleInputStart(-1));
390
+ btnRight.addEventListener('mousedown', () => handleInputStart(1));
391
+
392
+ function moveCar(direction) {
393
+ // Lane logic: 15% (Left), 50% (Center), 85% (Right)
394
+ if (direction === -1 && playerX > 15) {
395
+ playerX -= 35;
396
+ } else if (direction === 1 && playerX < 85) {
397
+ playerX += 35;
398
+ }
399
+ playerCar.style.left = `${playerX}%`;
400
+ }
401
+
402
+ // --- Game Logic ---
403
+
404
+ function startGame() {
405
+ startScreen.classList.add('hidden');
406
+ gameOverScreen.classList.add('hidden');
 
407
 
408
+ // Reset State
409
+ gameActive = true;
410
+ score = 0;
411
+ gameSpeed = BASE_SPEED;
412
+ enemies.forEach(enemy => enemy.remove());
413
+ enemies = [];
414
+ playerX = 50;
415
+ playerCar.style.left = '50%';
 
 
416
 
417
+ updateHUD();
418
+
419
+ // Start Loops
420
+ gameLoop();
421
+ spawnEnemies();
422
+ increaseSpeed();
423
+ }
424
 
425
+ function resetGame() {
426
+ startGame();
427
  }
 
428
 
429
+ function gameOver() {
430
+ gameActive = false;
431
+ cancelAnimationFrame(animationId);
432
+ clearInterval(spawnInterval);
433
+ clearInterval(speedInterval);
434
+
435
+ finalScoreEl.innerText = score;
436
+ gameOverScreen.classList.remove('hidden');
437
+
438
+ // Simple crash effect
439
+ playerCar.style.background = 'linear-gradient(180deg, #555, #000)';
440
+ playerCar.style.transform = 'translateX(-50%) rotate(15deg)';
441
+ }
442
 
443
+ function spawnEnemies() {
444
+ spawnInterval = setInterval(() => {
445
+ if (!gameActive) return;
446
+
447
+ const enemy = document.createElement('div');
448
+ enemy.classList.add('enemy');
449
+
450
+ // Random Color for enemies
451
+ const colors = ['#ff0055', '#00f2ff', '#cc00ff', '#00ff66', '#ff9900'];
452
+ const randomColor = colors[Math.floor(Math.random() * colors.length)];
453
+ enemy.style.background = `linear-gradient(180deg, ${randomColor}, #000)`;
454
+
455
+ // Random Lane (15, 50, 85)
456
+ const lanes = [15, 50, 85];
457
+ const randomLane = lanes[Math.floor(Math.random() * lanes.length)];
458
+
459
+ enemy.style.left = `${randomLane}%`;
460
+ enemy.style.top = '-100px';
461
+
462
+ // Store data for movement
463
+ enemy.dataset.speed = gameSpeed * 1.2; // Enemies move slightly faster than road relative to player
464
+ enemy.dataset.lane = randomLane;
465
+
466
+ gameContainer.appendChild(enemy);
467
+ enemies.push(enemy);
468
+
469
+ }, 1000 - (score * 0.005)); // Spawn faster as score increases (min 400ms)
470
+
471
+ // Ensure minimum spawn time
472
+ if (spawnInterval) {
473
+ // This is a bit tricky with setInterval, so we just let it run or clear/restart
474
+ // For simplicity in this demo, we'll keep the interval constant or slightly dynamic
475
+ // Let's just use a timeout recursion for better control
476
+ spawnEnemyRecursive();
477
+ clearInterval(spawnInterval);
478
+ }
479
+ }
 
 
 
 
 
480
 
481
+ function spawnEnemyRecursive() {
482
+ if (!gameActive) return;
483
+
484
+ const enemy = document.createElement('div');
485
+ enemy.classList.add('enemy');
486
+
487
+ const colors = ['#ff0055', '#00f2ff', '#cc00ff', '#00ff66', '#ff9900'];
488
+ const randomColor = colors[Math.floor(Math.random() * colors.length)];
489
+ enemy.style.background = `linear-gradient(180deg, ${randomColor}, #000)`;
490
+
491
+ const lanes = [15, 50, 85];
492
+ const randomLane = lanes[Math.floor(Math.random() * lanes.length)];
493
+
494
+ // Prevent spawning on top of another car
495
+ const tooClose = enemies.some(e => Math.abs(parseInt(e.style.top) - (-100)) < 150 && Math.abs(parseInt(e.style.left) - randomLane) < 5);
496
+
497
+ if (!tooClose) {
498
+ enemy.style.left = `${randomLane}%`;
499
+ enemy.style.top = '-100px';
500
+ enemy.style.zIndex = 9;
501
+ gameContainer.appendChild(enemy);
502
+ enemies.push(enemy);
503
+ }
504
+
505
+ // Difficulty scaling for spawn rate
506
+ let spawnRate = 1000 - (score * 0.01);
507
+ if (spawnRate < 400) spawnRate = 400;
508
+
509
+ setTimeout(spawnEnemyRecursive, spawnRate);
510
+ }
511
+
512
+ function increaseSpeed() {
513
+ speedInterval = setInterval(() => {
514
+ if (!gameActive) return;
515
+ if (gameSpeed < MAX_SPEED) {
516
+ gameSpeed += 0.5;
517
+ updateHUD();
518
+ }
519
+ }, 5000);
520
+ }
521
+
522
+ function gameLoop() {
523
+ if (!gameActive) return;
524
+
525
+ // Move Road Lines (Visual effect)
526
+ const roadLines = document.querySelectorAll('.road-line');
527
+ roadLines.forEach(line => {
528
+ let top = parseFloat(getComputedStyle(line).top);
529
+ if (top > 100) {
530
+ line.style.top = '-100px';
531
+ }
532
+ line.style.top = `${top + gameSpeed * 2}px`;
533
+ });
534
+
535
+ // Move Enemies
536
+ enemies.forEach((enemy, index) => {
537
+ let currentTop = parseFloat(getComputedStyle(enemy).top);
538
+ let speed = gameSpeed * 1.5; // Relative speed
539
+
540
+ // Move enemy down
541
+ let newTop = currentTop + speed;
542
+ enemy.style.top = `${newTop}px`;
543
+
544
+ // Collision Detection
545
+ if (checkCollision(playerCar, enemy)) {
546
+ gameOver();
547
+ return;
548
+ }
549
+
550
+ // Remove if off screen
551
+ if (newTop > gameContainer.offsetHeight) {
552
+ enemy.remove();
553
+ enemies.splice(index, 1);
554
+ score += 10;
555
+ updateHUD();
556
+ }
557
+ });
558
+
559
+ animationId = requestAnimationFrame(gameLoop);
560
+ }
561
+
562
+ function checkCollision(player, enemy) {
563
+ const pRect = player.getBoundingClientRect();
564
+ const eRect = enemy.getBoundingClientRect();
565
+
566
+ // Shrink hitbox slightly for better gameplay feel
567
+ const padding = 5;
568
+
569
+ return !(
570
+ pRect.top + padding > eRect.bottom - padding ||
571
+ pRect.bottom - padding < eRect.top + padding ||
572
+ pRect.right - padding < eRect.left + padding ||
573
+ pRect.left + padding > eRect.right - padding
574
+ );
575
+ }
576
+
577
+ function updateHUD() {
578
+ scoreEl.innerText = score;
579
+ speedEl.innerText = Math.floor(100 + (gameSpeed * 10));
580
+
581
+ // Dynamic color for speed
582
+ if (gameSpeed > 15) speedEl.style.color = '#ff0055';
583
+ else if (gameSpeed > 10) speedEl.style.color = '#ffcc00';
584
+ else speedEl.style.color = '#00f2ff';
585
+ }
586
+
587
+ // Initialize Road Lines
588
+ function initRoadLines() {
589
+ for(let i=0; i<5; i++) {
590
+ const line = document.createElement('div');
591
+ line.classList.add('road-line');
592
+ line.style.top = `${i * 25}%`;
593
+ gameContainer.appendChild(line);
594
+ roadLines.push(line);
595
+ }
596
+ }
597
+
598
+ initRoadLines();
599
+
600
+ </script>
601
+ </body>
602
  </html>