DzianisSISDZ commited on
Commit
2318ba3
·
verified ·
1 Parent(s): 5df6583

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +969 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: My Game
3
- emoji: 😻
4
- colorFrom: pink
5
- colorTo: yellow
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: my-game
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,969 @@
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>Stealth Ninja</title>
7
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
8
+ <style>
9
+ * {
10
+ margin: 0;
11
+ padding: 0;
12
+ box-sizing: border-box;
13
+ font-family: 'Arial', sans-serif;
14
+ }
15
+
16
+ body {
17
+ background-color: #121212;
18
+ color: #fff;
19
+ overflow: hidden;
20
+ height: 100vh;
21
+ }
22
+
23
+ /* Menu Styles */
24
+ .menu-container {
25
+ position: fixed;
26
+ top: 0;
27
+ left: 0;
28
+ width: 100%;
29
+ height: 100%;
30
+ display: flex;
31
+ flex-direction: column;
32
+ justify-content: center;
33
+ align-items: center;
34
+ background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
35
+ z-index: 100;
36
+ transition: all 0.5s ease;
37
+ }
38
+
39
+ .menu-container.hidden {
40
+ opacity: 0;
41
+ pointer-events: none;
42
+ }
43
+
44
+ .game-title {
45
+ font-size: 4rem;
46
+ margin-bottom: 2rem;
47
+ background: linear-gradient(90deg, #f64f59, #c471ed, #12c2e9);
48
+ -webkit-background-clip: text;
49
+ background-clip: text;
50
+ color: transparent;
51
+ text-shadow: 0 0 20px rgba(198, 114, 237, 0.3);
52
+ }
53
+
54
+ .difficulty-options {
55
+ display: flex;
56
+ gap: 1.5rem;
57
+ margin-bottom: 3rem;
58
+ }
59
+
60
+ .difficulty-btn {
61
+ padding: 0.8rem 1.5rem;
62
+ border: none;
63
+ border-radius: 50px;
64
+ font-size: 1.2rem;
65
+ font-weight: bold;
66
+ cursor: pointer;
67
+ transition: all 0.3s ease;
68
+ text-transform: uppercase;
69
+ letter-spacing: 1px;
70
+ position: relative;
71
+ overflow: hidden;
72
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
73
+ }
74
+
75
+ .difficulty-btn::before {
76
+ content: '';
77
+ position: absolute;
78
+ top: 0;
79
+ left: 0;
80
+ width: 100%;
81
+ height: 100%;
82
+ background: rgba(255, 255, 255, 0.1);
83
+ transform: translateX(-100%) skewX(-15deg);
84
+ transition: transform 0.4s ease;
85
+ }
86
+
87
+ .difficulty-btn:hover::before {
88
+ transform: translateX(100%) skewX(-15deg);
89
+ }
90
+
91
+ .easy {
92
+ background-color: #4caf50;
93
+ color: white;
94
+ }
95
+
96
+ .medium {
97
+ background-color: #ff9800;
98
+ color: white;
99
+ }
100
+
101
+ .hard {
102
+ background-color: #f44336;
103
+ color: white;
104
+ }
105
+
106
+ .start-btn {
107
+ padding: 1rem 2.5rem;
108
+ background: linear-gradient(90deg, #12c2e9, #c471ed);
109
+ border: none;
110
+ border-radius: 50px;
111
+ font-size: 1.5rem;
112
+ color: white;
113
+ cursor: pointer;
114
+ transition: all 0.3s ease;
115
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
116
+ position: relative;
117
+ overflow: hidden;
118
+ z-index: 1;
119
+ }
120
+
121
+ .start-btn:hover {
122
+ transform: translateY(-5px);
123
+ box-shadow: 0 15px 25px rgba(0, 0, 0, 0.3);
124
+ }
125
+
126
+ .start-btn::before {
127
+ content: '';
128
+ position: absolute;
129
+ top: 0;
130
+ left: 0;
131
+ width: 100%;
132
+ height: 100%;
133
+ background: linear-gradient(90deg, #c471ed, #12c2e9);
134
+ z-index: -1;
135
+ opacity: 0;
136
+ transition: opacity 0.3s ease;
137
+ }
138
+
139
+ .start-btn:hover::before {
140
+ opacity: 1;
141
+ }
142
+
143
+ /* Game Container */
144
+ .game-container {
145
+ width: 100%;
146
+ height: 100%;
147
+ position: relative;
148
+ display: none;
149
+ background-color: #1a1a2e;
150
+ overflow: hidden;
151
+ }
152
+
153
+ /* Game UI */
154
+ .game-ui {
155
+ position: absolute;
156
+ top: 1rem;
157
+ left: 1rem;
158
+ z-index: 10;
159
+ display: flex;
160
+ gap: 1rem;
161
+ }
162
+
163
+ .alert-box {
164
+ position: absolute;
165
+ top: 1rem;
166
+ left: 50%;
167
+ transform: translateX(-50%);
168
+ background-color: rgba(244, 67, 54, 0.8);
169
+ padding: 0.5rem 1rem;
170
+ border-radius: 5px;
171
+ font-size: 1rem;
172
+ font-weight: bold;
173
+ opacity: 0;
174
+ transition: opacity 0.3s ease;
175
+ z-index: 20;
176
+ }
177
+
178
+ .alert-box.show {
179
+ opacity: 1;
180
+ }
181
+
182
+ .stealth-meter {
183
+ display: flex;
184
+ align-items: center;
185
+ gap: 0.5rem;
186
+ background-color: rgba(0, 0, 0, 0.5);
187
+ padding: 0.5rem 1rem;
188
+ border-radius: 50px;
189
+ }
190
+
191
+ .stealth-icon {
192
+ color: #4caf50;
193
+ }
194
+
195
+ .stealth-bar {
196
+ width: 100px;
197
+ height: 10px;
198
+ background-color: rgba(255, 255, 255, 0.1);
199
+ border-radius: 5px;
200
+ overflow: hidden;
201
+ }
202
+
203
+ .stealth-fill {
204
+ height: 100%;
205
+ width: 100%;
206
+ background: linear-gradient(90deg, #4caf50, #8bc34a);
207
+ transition: width 0.3s ease;
208
+ }
209
+
210
+ /* Game Elements */
211
+ .hideable {
212
+ position: absolute;
213
+ width: 40px;
214
+ height: 40px;
215
+ border-radius: 50%;
216
+ background: linear-gradient(135deg, #333, #111);
217
+ display: flex;
218
+ justify-content: center;
219
+ align-items: center;
220
+ color: white;
221
+ z-index: 5;
222
+ user-select: none;
223
+ }
224
+
225
+ .ninja {
226
+ width: 30px;
227
+ height: 30px;
228
+ background: linear-gradient(135deg, #666, #333);
229
+ border-radius: 50%;
230
+ position: absolute;
231
+ z-index: 5;
232
+ transition: transform 0.3s ease;
233
+ display: flex;
234
+ justify-content: center;
235
+ align-items: center;
236
+ color: white;
237
+ }
238
+
239
+ .ninja i {
240
+ font-size: 14px;
241
+ }
242
+
243
+ .ninja.rolling {
244
+ animation: roll 0.5s linear;
245
+ transform: scale(0.8);
246
+ }
247
+
248
+ @keyframes roll {
249
+ 0% { transform: rotate(0deg) scale(0.8); }
250
+ 100% { transform: rotate(360deg) scale(0.8); }
251
+ }
252
+
253
+ .ninja.hidden {
254
+ opacity: 0.5;
255
+ transform: scale(0.7);
256
+ background: linear-gradient(135deg, #444, #222);
257
+ }
258
+
259
+ .guard {
260
+ width: 30px;
261
+ height: 30px;
262
+ background: linear-gradient(135deg, #a83232, #6b1c1c);
263
+ border-radius: 50%;
264
+ position: absolute;
265
+ z-index: 4;
266
+ display: flex;
267
+ justify-content: center;
268
+ align-items: center;
269
+ color: white;
270
+ }
271
+
272
+ .guard i {
273
+ font-size: 14px;
274
+ }
275
+
276
+ .vision-cone {
277
+ position: absolute;
278
+ width: 150px;
279
+ height: 150px;
280
+ background: linear-gradient(90deg, rgba(255, 0, 0, 0.1), rgba(255, 0, 0, 0.3));
281
+ clip-path: polygon(0 0, 100% 50%, 0 100%);
282
+ transform-origin: left center;
283
+ z-index: 3;
284
+ border-radius: 0 75px 75px 0;
285
+ }
286
+
287
+ .wall {
288
+ position: absolute;
289
+ background: linear-gradient(135deg, #3a3a3a, #2a2a2a);
290
+ z-index: 2;
291
+ border: 1px solid #555;
292
+ }
293
+
294
+ .exit {
295
+ position: absolute;
296
+ width: 40px;
297
+ height: 40px;
298
+ background-color: rgba(76, 175, 80, 0.3);
299
+ border: 2px dashed #4caf50;
300
+ border-radius: 5px;
301
+ display: flex;
302
+ justify-content: center;
303
+ align-items: center;
304
+ color: #4caf50;
305
+ z-index: 1;
306
+ }
307
+
308
+ .game-over, .game-won {
309
+ position: absolute;
310
+ top: 0;
311
+ left: 0;
312
+ width: 100%;
313
+ height: 100%;
314
+ background-color: rgba(0, 0, 0, 0.8);
315
+ display: flex;
316
+ flex-direction: column;
317
+ justify-content: center;
318
+ align-items: center;
319
+ z-index: 100;
320
+ color: white;
321
+ font-size: 2rem;
322
+ display: none;
323
+ }
324
+
325
+ .restart-btn {
326
+ margin-top: 2rem;
327
+ padding: 1rem 2rem;
328
+ background: linear-gradient(90deg, #c471ed, #12c2e9);
329
+ border: none;
330
+ border-radius: 5px;
331
+ font-size: 1.2rem;
332
+ color: white;
333
+ cursor: pointer;
334
+ }
335
+
336
+ .controls {
337
+ position: absolute;
338
+ bottom: 1rem;
339
+ left: 50%;
340
+ transform: translateX(-50%);
341
+ background-color: rgba(0, 0, 0, 0.5);
342
+ padding: 0.5rem 1rem;
343
+ border-radius: 5px;
344
+ font-size: 0.8rem;
345
+ text-align: center;
346
+ }
347
+
348
+ .level-indicator {
349
+ position: absolute;
350
+ top: 1rem;
351
+ right: 1rem;
352
+ background-color: rgba(0, 0, 0, 0.5);
353
+ padding: 0.5rem 1rem;
354
+ border-radius: 50px;
355
+ font-size: 0.8rem;
356
+ }
357
+ </style>
358
+ </head>
359
+ <body>
360
+ <!-- Menu Screen -->
361
+ <div class="menu-container">
362
+ <h1 class="game-title">Stealth Ninja</h1>
363
+ <div class="difficulty-options">
364
+ <button class="difficulty-btn easy" data-difficulty="easy">
365
+ <i class="fas fa-leaf"></i> Easy
366
+ </button>
367
+ <button class="difficulty-btn medium" data-difficulty="medium">
368
+ <i class="fas fa-balance-scale"></i> Medium
369
+ </button>
370
+ <button class="difficulty-btn hard" data-difficulty="hard">
371
+ <i class="fas fa-fire"></i> Hard
372
+ </button>
373
+ </div>
374
+ <button class="start-btn">Start Mission</button>
375
+ </div>
376
+
377
+ <!-- Game Screen -->
378
+ <div class="game-container">
379
+ <div class="game-ui">
380
+ <div class="stealth-meter">
381
+ <i class="fas fa-user-ninja stealth-icon"></i>
382
+ <div class="stealth-bar">
383
+ <div class="stealth-fill"></div>
384
+ </div>
385
+ </div>
386
+ </div>
387
+
388
+ <div class="alert-box">Guard Alerted!</div>
389
+
390
+ <div class="level-indicator">Level: <span class="level-value">1</span></div>
391
+
392
+ <div class="controls">
393
+ WASD to move | SPACE to roll | SHIFT to hide | Avoid red vision cones
394
+ </div>
395
+
396
+ <div class="game-over">
397
+ <h2>Mission Failed</h2>
398
+ <p>You were detected!</p>
399
+ <button class="restart-btn">Try Again</button>
400
+ </div>
401
+
402
+ <div class="game-won">
403
+ <h2>Mission Complete</h2>
404
+ <p>You escaped undetected!</p>
405
+ <button class="restart-btn">Play Again</button>
406
+ </div>
407
+ </div>
408
+
409
+ <script>
410
+ // Game State
411
+ const gameState = {
412
+ difficulty: 'medium',
413
+ level: 1,
414
+ isGameActive: false,
415
+ ninja: {
416
+ x: 50,
417
+ y: 50,
418
+ speed: 2,
419
+ isHidden: false,
420
+ isRolling: false,
421
+ stealth: 100,
422
+ lastRollTime: 0,
423
+ rollCooldown: 1000
424
+ },
425
+ guards: [],
426
+ walls: [],
427
+ hideSpots: [],
428
+ exit: null,
429
+ keysPressed: {
430
+ w: false,
431
+ a: false,
432
+ s: false,
433
+ d: false,
434
+ shift: false,
435
+ space: false
436
+ },
437
+ lastTime: 0,
438
+ detectionLevel: 0,
439
+ maxDetection: 100
440
+ };
441
+
442
+ // DOM Elements
443
+ const menuContainer = document.querySelector('.menu-container');
444
+ const gameContainer = document.querySelector('.game-container');
445
+ const startBtn = document.querySelector('.start-btn');
446
+ const difficultyBtns = document.querySelectorAll('.difficulty-btn');
447
+ const stealthFill = document.querySelector('.stealth-fill');
448
+ const alertBox = document.querySelector('.alert-box');
449
+ const gameOverScreen = document.querySelector('.game-over');
450
+ const gameWonScreen = document.querySelector('.game-won');
451
+ const restartBtns = document.querySelectorAll('.restart-btn');
452
+ const levelValue = document.querySelector('.level-value');
453
+
454
+ // Initialize Game
455
+ function initGame() {
456
+ gameState.isGameActive = true;
457
+ gameContainer.style.display = 'block';
458
+ gameState.ninja.stealth = 100;
459
+ gameState.detectionLevel = 0;
460
+ updateStealthBar();
461
+
462
+ // Clear previous elements
463
+ document.querySelectorAll('.hideable, .ninja, .guard, .vision-cone, .wall, .exit').forEach(el => el.remove());
464
+ gameState.guards = [];
465
+ gameState.walls = [];
466
+ gameState.hideSpots = [];
467
+
468
+ createNinja();
469
+ generateLevel(gameState.level);
470
+ }
471
+
472
+ // Create Ninja Element
473
+ function createNinja() {
474
+ const ninja = document.createElement('div');
475
+ ninja.className = 'ninja';
476
+ ninja.innerHTML = '<i class="fas fa-user-ninja"></i>';
477
+ ninja.style.left = `${gameState.ninja.x}px`;
478
+ ninja.style.top = `${gameState.ninja.y}px`;
479
+ gameContainer.appendChild(ninja);
480
+ }
481
+
482
+ // Generate Level
483
+ function generateLevel(level) {
484
+ levelValue.textContent = level;
485
+
486
+ // Adjust difficulty based on level
487
+ const difficultyMultiplier = 1 + (level - 1) * 0.2;
488
+
489
+ // Create exit point
490
+ createExit(800, 450);
491
+
492
+ // Create walls
493
+ createWalls(level);
494
+
495
+ // Create hide spots
496
+ createHideSpots(level);
497
+
498
+ // Create guards based on difficulty
499
+ const guardCount = Math.min(3 + Math.floor(level / 2), 8);
500
+ for (let i = 0; i < guardCount; i++) {
501
+ createGuard(level, difficultyMultiplier);
502
+ }
503
+ }
504
+
505
+ function createExit(x, y) {
506
+ const exit = document.createElement('div');
507
+ exit.className = 'exit';
508
+ exit.innerHTML = '<i class="fas fa-door-open"></i>';
509
+ exit.style.left = `${x}px`;
510
+ exit.style.top = `${y}px`;
511
+ gameContainer.appendChild(exit);
512
+ gameState.exit = { x, y, element: exit };
513
+ }
514
+
515
+ function createWalls(level) {
516
+ // Border walls
517
+ addWall(0, 0, window.innerWidth, 20);
518
+ addWall(0, 0, 20, window.innerHeight);
519
+ addWall(0, window.innerHeight - 20, window.innerWidth, 20);
520
+ addWall(window.innerWidth - 20, 0, 20, window.innerHeight);
521
+
522
+ // Random walls based on level
523
+ const wallCount = 5 + level;
524
+ for (let i = 0; i < wallCount; i++) {
525
+ const width = 50 + Math.random() * 150;
526
+ const height = 30 + Math.random() * 100;
527
+ const x = 50 + Math.random() * (window.innerWidth - width - 100);
528
+ const y = 50 + Math.random() * (window.innerHeight - height - 100);
529
+ addWall(x, y, width, height);
530
+ }
531
+ }
532
+
533
+ function addWall(x, y, width, height) {
534
+ const wall = document.createElement('div');
535
+ wall.className = 'wall';
536
+ wall.style.left = `${x}px`;
537
+ wall.style.top = `${y}px`;
538
+ wall.style.width = `${width}px`;
539
+ wall.style.height = `${height}px`;
540
+ gameContainer.appendChild(wall);
541
+ gameState.walls.push({ x, y, width, height, element: wall });
542
+ }
543
+
544
+ function createHideSpots(level) {
545
+ const spotsCount = 3 + level;
546
+ for (let i = 0; i < spotsCount; i++) {
547
+ const x = 50 + Math.random() * (window.innerWidth - 100);
548
+ const y = 50 + Math.random() * (window.innerHeight - 100);
549
+
550
+ // Make sure it's not on a wall
551
+ if (!isPositionOnWall(x, y)) {
552
+ const spot = document.createElement('div');
553
+ spot.className = 'hideable';
554
+ spot.innerHTML = '<i class="fas fa-mountain"></i>';
555
+ spot.style.left = `${x}px`;
556
+ spot.style.top = `${y}px`;
557
+ gameContainer.appendChild(spot);
558
+ gameState.hideSpots.push({ x, y, element: spot });
559
+ }
560
+ }
561
+ }
562
+
563
+ function createGuard(level, difficultyMultiplier) {
564
+ let x, y;
565
+ do {
566
+ x = 100 + Math.random() * (window.innerWidth - 200);
567
+ y = 100 + Math.random() * (window.innerHeight - 200);
568
+ } while (isPositionOnWall(x, y) || isTooCloseToNinja(x, y));
569
+
570
+ const speed = 0.5 + Math.random() * 0.5 * difficultyMultiplier;
571
+ const visionRange = 100 + Math.random() * 50;
572
+ const visionAngle = 60;
573
+ const patrolDistance = 100 + Math.random() * 100;
574
+
575
+ const guard = {
576
+ x, y,
577
+ speed,
578
+ direction: Math.random() * Math.PI * 2,
579
+ visionRange,
580
+ visionAngle,
581
+ patrolDistance,
582
+ initialX: x,
583
+ initialY: y,
584
+ path: [], // For more complex patrol paths
585
+ isAlerted: false,
586
+ alertTimer: 0
587
+ };
588
+
589
+ // Create guard element
590
+ const guardEl = document.createElement('div');
591
+ guardEl.className = 'guard';
592
+ guardEl.innerHTML = '<i class="fas fa-eye"></i>';
593
+ guardEl.style.left = `${x}px`;
594
+ guardEl.style.top = `${y}px`;
595
+ gameContainer.appendChild(guardEl);
596
+ guard.element = guardEl;
597
+
598
+ // Create vision cone
599
+ const cone = document.createElement('div');
600
+ cone.className = 'vision-cone';
601
+ cone.style.left = `${x + 15}px`;
602
+ cone.style.top = `${y - 50}px`;
603
+ cone.style.width = `${visionRange}px`;
604
+ cone.style.height = `${visionRange * 2}px`;
605
+ gameContainer.appendChild(cone);
606
+ guard.visionCone = cone;
607
+
608
+ gameState.guards.push(guard);
609
+ }
610
+
611
+ // Check if position is on a wall
612
+ function isPositionOnWall(x, y) {
613
+ return gameState.walls.some(wall =>
614
+ x >= wall.x && x <= wall.x + wall.width &&
615
+ y >= wall.y && y <= wall.y + wall.height
616
+ );
617
+ }
618
+
619
+ // Check if guard is too close to ninja spawn
620
+ function isTooCloseToNinja(x, y) {
621
+ const dx = x - gameState.ninja.x;
622
+ const dy = y - gameState.ninja.y;
623
+ return Math.sqrt(dx * dx + dy * dy) < 200;
624
+ }
625
+
626
+ // Update Stealth Meter
627
+ function updateStealthBar() {
628
+ const stealthPercentage = gameState.ninja.stealth;
629
+ stealthFill.style.width = `${stealthPercentage}%`;
630
+
631
+ if (stealthPercentage > 70) {
632
+ stealthFill.style.background = 'linear-gradient(90deg, #4caf50, #8bc34a)';
633
+ } else if (stealthPercentage > 30) {
634
+ stealthFill.style.background = 'linear-gradient(90deg, #ff9800, #ffc107)';
635
+ } else {
636
+ stealthFill.style.background = 'linear-gradient(90deg, #f44336, #ff5722)';
637
+ }
638
+ }
639
+
640
+ // Game Loop
641
+ function gameLoop(timestamp) {
642
+ if (!gameState.isGameActive) return;
643
+
644
+ const deltaTime = timestamp - gameState.lastTime;
645
+ gameState.lastTime = timestamp;
646
+
647
+ updateNinja(deltaTime);
648
+ updateGuards(deltaTime);
649
+ checkDetection();
650
+ checkExit();
651
+
652
+ requestAnimationFrame(gameLoop);
653
+ }
654
+
655
+ // Update Ninja Position
656
+ function updateNinja(deltaTime) {
657
+ const ninja = gameState.ninja;
658
+ const ninjaEl = document.querySelector('.ninja');
659
+
660
+ // Reset rolling state if animation finished
661
+ if (ninja.isRolling && Date.now() - ninja.lastRollTime > 500) {
662
+ ninja.isRolling = false;
663
+ ninjaEl.classList.remove('rolling');
664
+ }
665
+
666
+ // Calculate movement
667
+ let dx = 0, dy = 0;
668
+ if (gameState.keysPressed.w) dy -= ninja.speed;
669
+ if (gameState.keysPressed.s) dy += ninja.speed;
670
+ if (gameState.keysPressed.a) dx -= ninja.speed;
671
+ if (gameState.keysPressed.d) dx += ninja.speed;
672
+
673
+ // Rolling modifier
674
+ if (ninja.isRolling) {
675
+ dx *= 2;
676
+ dy *= 2;
677
+ }
678
+
679
+ // Apply movement if not completely stopped
680
+ if (dx !== 0 || dy !== 0) {
681
+ ninja.x += dx;
682
+ ninja.y += dy;
683
+
684
+ // Stealth drain when moving
685
+ if (!ninja.isHidden && !ninja.isRolling) {
686
+ ninja.stealth = Math.max(0, ninja.stealth - 0.05);
687
+ updateStealthBar();
688
+ }
689
+ } else {
690
+ // Stealth recovery when standing still
691
+ if (!ninja.isRolling) {
692
+ ninja.stealth = Math.min(100, ninja.stealth + 0.1);
693
+ updateStealthBar();
694
+ }
695
+ }
696
+
697
+ // Check wall collisions
698
+ ninja.x = Math.max(20, Math.min(window.innerWidth - 40, ninja.x));
699
+ ninja.y = Math.max(20, Math.min(window.innerHeight - 40, ninja.y));
700
+
701
+ // Update DOM element
702
+ ninjaEl.style.left = `${ninja.x}px`;
703
+ ninjaEl.style.top = `${ninja.y}px`;
704
+
705
+ // Check hide state
706
+ const isNearHideSpot = gameState.hideSpots.some(spot => {
707
+ const dx = spot.x - ninja.x;
708
+ const dy = spot.y - ninja.y;
709
+ return Math.sqrt(dx * dx + dy * dy) < 30 && gameState.keysPressed.shift;
710
+ });
711
+
712
+ // Check wall hiding
713
+ const isNearWall = gameState.walls.some(wall => {
714
+ return (Math.abs(ninja.x - wall.x) < 15 ||
715
+ Math.abs(ninja.x - (wall.x + wall.width)) < 15) &&
716
+ ninja.y > wall.y && ninja.y < wall.y + wall.height &&
717
+ gameState.keysPressed.shift;
718
+ });
719
+
720
+ const shouldBeHidden = isNearHideSpot || isNearWall;
721
+
722
+ if (shouldBeHidden && !ninja.isHidden) {
723
+ ninja.isHidden = true;
724
+ ninjaEl.classList.add('hidden');
725
+ ninja.stealth = Math.min(100, ninja.stealth + 10);
726
+ updateStealthBar();
727
+ } else if (!shouldBeHidden && ninja.isHidden) {
728
+ ninja.isHidden = false;
729
+ ninjaEl.classList.remove('hidden');
730
+ }
731
+
732
+ // Roll cooldown
733
+ if (ninja.isRolling && Date.now() - ninja.lastRollTime > ninja.rollCooldown) {
734
+ ninja.isRolling = false;
735
+ }
736
+ }
737
+
738
+ // Update Guards
739
+ function updateGuards(deltaTime) {
740
+ gameState.guards.forEach(guard => {
741
+ // Simple patrol behavior
742
+ const angle = Date.now() * 0.0005;
743
+ guard.direction = angle;
744
+
745
+ // Move guard in patrol pattern
746
+ guard.x = guard.initialX + Math.cos(angle) * guard.patrolDistance;
747
+ guard.y = guard.initialY + Math.sin(angle) * guard.patrolDistance;
748
+
749
+ // Update guard position
750
+ guard.element.style.left = `${guard.x}px`;
751
+ guard.element.style.top = `${guard.y}px`;
752
+
753
+ // Update vision cone
754
+ guard.visionCone.style.left = `${guard.x + 15}px`;
755
+ guard.visionCone.style.top = `${guard.y - guard.visionRange * 0.5}px`;
756
+ guard.visionCone.style.transform = `rotate(${guard.direction}rad)`;
757
+
758
+ // Alert behavior
759
+ if (guard.isAlerted) {
760
+ guard.alertTimer += deltaTime;
761
+ if (guard.alertTimer > 3000) {
762
+ guard.isAlerted = false;
763
+ guard.alertTimer = 0;
764
+ }
765
+ }
766
+ });
767
+ }
768
+
769
+ // Check Detection
770
+ function checkDetection() {
771
+ if (gameState.ninja.isHidden) return;
772
+
773
+ const ninja = gameState.ninja;
774
+ let isDetected = false;
775
+
776
+ gameState.guards.forEach(guard => {
777
+ // Calculate distance from guard to ninja
778
+ const dx = ninja.x - guard.x;
779
+ const dy = ninja.y - guard.y;
780
+ const distance = Math.sqrt(dx * dx + dy * dy);
781
+
782
+ if (distance < guard.visionRange) {
783
+ // Calculate angle between guard's direction and ninja
784
+ const angleToNinja = Math.atan2(dy, dx);
785
+ let angleDiff = Math.abs(guard.direction - angleToNinja);
786
+
787
+ // Normalize angle difference
788
+ while (angleDiff > Math.PI) angleDiff -= Math.PI * 2;
789
+ angleDiff = Math.abs(angleDiff);
790
+
791
+ // Check if ninja is in vision cone
792
+ if (angleDiff < guard.visionAngle * Math.PI / 360) {
793
+ // Check line of sight (no walls in between)
794
+ const hasLineOfSight = !gameState.walls.some(wall => {
795
+ return lineIntersectsRectangle(
796
+ guard.x, guard.y, ninja.x, ninja.y,
797
+ wall.x, wall.y, wall.width, wall.height
798
+ );
799
+ });
800
+
801
+ if (hasLineOfSight) {
802
+ // Detection based on stealth level
803
+ const detectionChance = (1 - gameState.ninja.stealth / 100) * 0.8;
804
+ if (Math.random() < detectionChance || distance < 30) {
805
+ isDetected = true;
806
+ guard.isAlerted = true;
807
+ guard.alertTimer = 0;
808
+
809
+ // Increase detection level
810
+ if (gameState.detectionLevel < gameState.maxDetection) {
811
+ gameState.detectionLevel += 2;
812
+ }
813
+ }
814
+ }
815
+ }
816
+ }
817
+ });
818
+
819
+ // Show/hide alert
820
+ if (isDetected) {
821
+ if (!alertBox.classList.contains('show')) {
822
+ alertBox.classList.add('show');
823
+ setTimeout(() => alertBox.classList.remove('show'), 2000);
824
+ }
825
+ }
826
+
827
+ // Game over if fully detected
828
+ if (gameState.detectionLevel >= gameState.maxDetection) {
829
+ gameOver();
830
+ }
831
+ }
832
+
833
+ // Check Exit
834
+ function checkExit() {
835
+ const ninja = gameState.ninja;
836
+ const exit = gameState.exit;
837
+
838
+ const dx = exit.x - ninja.x;
839
+ const dy = exit.y - ninja.y;
840
+ const distance = Math.sqrt(dx * dx + dy * dy);
841
+
842
+ if (distance < 30) {
843
+ levelComplete();
844
+ }
845
+ }
846
+
847
+ // Helper function for line-rectangle intersection
848
+ function lineIntersectsRectangle(x1, y1, x2, y2, rx, ry, rw, rh) {
849
+ // Check if line is inside rectangle
850
+ if ((x1 >= rx && x1 <= rx + rw && y1 >= ry && y1 <= ry + rh) ||
851
+ (x2 >= rx && x2 <= rx + rw && y2 >= ry && y2 <= ry + rh)) {
852
+ return true;
853
+ }
854
+
855
+ // Check line against each edge of rectangle
856
+ return (
857
+ lineIntersectsLine(x1, y1, x2, y2, rx, ry, rx + rw, ry) || // top
858
+ lineIntersectsLine(x1, y1, x2, y2, rx + rw, ry, rx + rw, ry + rh) || // right
859
+ lineIntersectsLine(x1, y1, x2, y2, rx, ry + rh, rx + rw, ry + rh) || // bottom
860
+ lineIntersectsLine(x1, y1, x2, y2, rx, ry, rx, ry + rh) // left
861
+ );
862
+ }
863
+
864
+ function lineIntersectsLine(x1, y1, x2, y2, x3, y3, x4, y4) {
865
+ const uA = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) /
866
+ ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));
867
+ const uB = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) /
868
+ ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));
869
+
870
+ return uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1;
871
+ }
872
+
873
+ // Game Events
874
+ function gameOver() {
875
+ gameState.isGameActive = false;
876
+ gameOverScreen.style.display = 'flex';
877
+
878
+ // Remove all vision cones
879
+ document.querySelectorAll('.vision-cone').forEach(el => el.remove());
880
+ }
881
+
882
+ function levelComplete() {
883
+ gameState.isGameActive = false;
884
+ gameWonScreen.style.display = 'flex';
885
+
886
+ // Remove all vision cones
887
+ document.querySelectorAll('.vision-cone').forEach(el => el.remove());
888
+
889
+ // Increase level
890
+ gameState.level++;
891
+ }
892
+
893
+ // Event Listeners
894
+ difficultyBtns.forEach(btn => {
895
+ btn.addEventListener('click', () => {
896
+ gameState.difficulty = btn.dataset.difficulty;
897
+
898
+ // Update active button
899
+ difficultyBtns.forEach(b => b.classList.remove('active'));
900
+ btn.classList.add('active');
901
+ });
902
+ });
903
+
904
+ startBtn.addEventListener('click', () => {
905
+ menuContainer.classList.add('hidden');
906
+ setTimeout(() => {
907
+ menuContainer.style.display = 'none';
908
+ initGame();
909
+ gameState.lastTime = performance.now();
910
+ requestAnimationFrame(gameLoop);
911
+ }, 500);
912
+ });
913
+
914
+ restartBtns.forEach(btn => {
915
+ btn.addEventListener('click', () => {
916
+ gameOverScreen.style.display = 'none';
917
+ gameWonScreen.style.display = 'none';
918
+
919
+ // Move ninja back to start
920
+ gameState.ninja.x = 50;
921
+ gameState.ninja.y = 50;
922
+ gameState.ninja.isHidden = false;
923
+ gameState.ninja.isRolling = false;
924
+
925
+ const ninjaEl = document.querySelector('.ninja');
926
+ if (ninjaEl) {
927
+ ninjaEl.classList.remove('hidden', 'rolling');
928
+ }
929
+
930
+ initGame();
931
+ gameState.lastTime = performance.now();
932
+ requestAnimationFrame(gameLoop);
933
+ });
934
+ });
935
+
936
+ // Keyboard Controls
937
+ document.addEventListener('keydown', (e) => {
938
+ if (!gameState.isGameActive) return;
939
+
940
+ switch (e.key.toLowerCase()) {
941
+ case 'w': gameState.keysPressed.w = true; break;
942
+ case 'a': gameState.keysPressed.a = true; break;
943
+ case 's': gameState.keysPressed.s = true; break;
944
+ case 'd': gameState.keysPressed.d = true; break;
945
+ case 'shift': gameState.keysPressed.shift = true; break;
946
+ case ' ':
947
+ if (!gameState.ninja.isRolling && Date.now() - gameState.ninja.lastRollTime > gameState.ninja.rollCooldown) {
948
+ gameState.ninja.isRolling = true;
949
+ gameState.ninja.lastRollTime = Date.now();
950
+ document.querySelector('.ninja').classList.add('rolling');
951
+ }
952
+ gameState.keysPressed.space = true;
953
+ break;
954
+ }
955
+ });
956
+
957
+ document.addEventListener('keyup', (e) => {
958
+ switch (e.key.toLowerCase()) {
959
+ case 'w': gameState.keysPressed.w = false; break;
960
+ case 'a': gameState.keysPressed.a = false; break;
961
+ case 's': gameState.keysPressed.s = false; break;
962
+ case 'd': gameState.keysPressed.d = false; break;
963
+ case 'shift': gameState.keysPressed.shift = false; break;
964
+ case ' ': gameState.keysPressed.space = false; break;
965
+ }
966
+ });
967
+ </script>
968
+ <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 <a href="https://enzostvs-deepsite.hf.space" style="color: #fff;" target="_blank" >DeepSite</a> <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;"></p></body>
969
+ </html>