Phoenixoni commited on
Commit
717a85c
·
verified ·
1 Parent(s): ae71461

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +961 -19
  3. prompts.txt +2 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Tower
3
- emoji: 🌍
4
- colorFrom: blue
5
- colorTo: purple
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: tower
3
+ emoji: 🐳
4
+ colorFrom: red
5
+ colorTo: red
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,961 @@
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>Fantasy Tower Defense</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
+ @keyframes moveEnemy {
11
+ to {
12
+ background-position: -512px 0;
13
+ }
14
+ }
15
+
16
+ .enemy {
17
+ width: 32px;
18
+ height: 32px;
19
+ background-image: url('https://i.imgur.com/Jj7Zq9G.png');
20
+ animation: moveEnemy 0.8s steps(16) infinite;
21
+ position: absolute;
22
+ z-index: 10;
23
+ transition: left 0.1s linear, top 0.1s linear;
24
+ }
25
+
26
+ .tower {
27
+ width: 48px;
28
+ height: 48px;
29
+ background-image: url('https://i.imgur.com/Q9ZvZLQ.png');
30
+ background-position: 0 0;
31
+ position: absolute;
32
+ z-index: 5;
33
+ }
34
+
35
+ .projectile {
36
+ width: 16px;
37
+ height: 16px;
38
+ background-color: #f00;
39
+ border-radius: 50%;
40
+ position: absolute;
41
+ z-index: 8;
42
+ }
43
+
44
+ .path {
45
+ background-color: #8B4513;
46
+ background-image: url('https://i.imgur.com/5XQ3y9j.png');
47
+ background-size: cover;
48
+ }
49
+
50
+ .grass {
51
+ background-color: #7CFC00;
52
+ background-image: url('https://i.imgur.com/4ZQ3y9j.png');
53
+ background-size: cover;
54
+ }
55
+
56
+ .buildable {
57
+ background-color: #3a7d44;
58
+ background-image: url('https://i.imgur.com/6XQ3y9j.png');
59
+ background-size: cover;
60
+ cursor: pointer;
61
+ }
62
+
63
+ .buildable:hover {
64
+ filter: brightness(1.2);
65
+ box-shadow: inset 0 0 10px rgba(255, 255, 255, 0.5);
66
+ }
67
+
68
+ .game-grid {
69
+ display: grid;
70
+ grid-template-columns: repeat(20, 32px);
71
+ grid-template-rows: repeat(15, 32px);
72
+ gap: 1px;
73
+ background-color: #333;
74
+ }
75
+
76
+ .tower-range {
77
+ position: absolute;
78
+ border-radius: 50%;
79
+ background-color: rgba(0, 100, 255, 0.2);
80
+ transform: translate(-50%, -50%);
81
+ pointer-events: none;
82
+ z-index: 2;
83
+ }
84
+
85
+ .health-bar {
86
+ height: 4px;
87
+ background-color: red;
88
+ position: absolute;
89
+ top: -6px;
90
+ left: 0;
91
+ width: 100%;
92
+ }
93
+
94
+ .upgrade-btn {
95
+ transition: all 0.2s;
96
+ }
97
+
98
+ .upgrade-btn:hover {
99
+ transform: scale(1.05);
100
+ box-shadow: 0 0 10px gold;
101
+ }
102
+
103
+ #game-container {
104
+ perspective: 1000px;
105
+ }
106
+
107
+ #game-board {
108
+ transform-style: preserve-3d;
109
+ box-shadow: 0 0 30px rgba(0, 0, 0, 0.5);
110
+ }
111
+
112
+ .start-point {
113
+ background-color: #ff0000;
114
+ background-image: url('https://i.imgur.com/7XQ3y9j.png');
115
+ background-size: cover;
116
+ }
117
+
118
+ .end-point {
119
+ background-color: #0000ff;
120
+ background-image: url('https://i.imgur.com/8XQ3y9j.png');
121
+ background-size: cover;
122
+ }
123
+ </style>
124
+ </head>
125
+ <body class="bg-gray-900 text-white font-mono">
126
+ <div class="container mx-auto px-4 py-8">
127
+ <h1 class="text-4xl font-bold text-center mb-6 text-transparent bg-clip-text bg-gradient-to-r from-yellow-400 to-red-500">
128
+ <i class="fas fa-fort-awesome-alt mr-2"></i> Fantasy Tower Defense
129
+ </h1>
130
+
131
+ <div class="flex flex-col lg:flex-row gap-6">
132
+ <!-- Game Board -->
133
+ <div id="game-container" class="flex-1">
134
+ <div id="game-board" class="game-grid relative overflow-hidden border-4 border-yellow-700 rounded-lg bg-gray-800">
135
+ <!-- Grid will be generated by JavaScript -->
136
+ </div>
137
+ </div>
138
+
139
+ <!-- Game Controls -->
140
+ <div class="w-full lg:w-64 bg-gray-800 p-4 rounded-lg border-2 border-gray-700">
141
+ <div class="flex justify-between items-center mb-4">
142
+ <div>
143
+ <div class="text-xl font-bold text-yellow-400">Wave: <span id="wave">1</span></div>
144
+ <div class="text-sm text-gray-300">Enemies: <span id="enemies-left">0</span></div>
145
+ </div>
146
+ <div class="text-right">
147
+ <div class="text-xl font-bold text-green-400">$<span id="money">150</span></div>
148
+ <div class="text-sm text-gray-300">Lives: <span id="lives">20</span></div>
149
+ </div>
150
+ </div>
151
+
152
+ <div class="mb-4">
153
+ <div class="h-2 bg-gray-700 rounded-full">
154
+ <div id="wave-progress" class="h-2 bg-blue-500 rounded-full" style="width: 0%"></div>
155
+ </div>
156
+ <div class="flex justify-between text-xs mt-1">
157
+ <span>Wave Progress</span>
158
+ <span id="wave-timer">30s</span>
159
+ </div>
160
+ </div>
161
+
162
+ <button id="start-wave" class="w-full bg-green-600 hover:bg-green-700 text-white py-2 px-4 rounded-lg font-bold mb-4 transition-all">
163
+ <i class="fas fa-play mr-2"></i> Start Wave
164
+ </button>
165
+
166
+ <div class="mb-4">
167
+ <h3 class="font-bold text-lg border-b border-gray-700 pb-2 mb-2">Towers</h3>
168
+ <div class="grid grid-cols-2 gap-2">
169
+ <button class="tower-btn bg-blue-800 hover:bg-blue-700 p-2 rounded-lg" data-type="arrow" data-cost="100">
170
+ <div class="text-center">
171
+ <i class="fas fa-arrow-up text-xl mb-1"></i>
172
+ <div>Arrow Tower</div>
173
+ <div class="text-xs">$100</div>
174
+ </div>
175
+ </button>
176
+ <button class="tower-btn bg-red-800 hover:bg-red-700 p-2 rounded-lg" data-type="cannon" data-cost="150">
177
+ <div class="text-center">
178
+ <i class="fas fa-bomb text-xl mb-1"></i>
179
+ <div>Cannon Tower</div>
180
+ <div class="text-xs">$150</div>
181
+ </div>
182
+ </button>
183
+ <button class="tower-btn bg-purple-800 hover:bg-purple-700 p-2 rounded-lg" data-type="magic" data-cost="200">
184
+ <div class="text-center">
185
+ <i class="fas fa-magic text-xl mb-1"></i>
186
+ <div>Magic Tower</div>
187
+ <div class="text-xs">$200</div>
188
+ </div>
189
+ </button>
190
+ <button class="tower-btn bg-yellow-800 hover:bg-yellow-700 p-2 rounded-lg" data-type="gold" data-cost="300">
191
+ <div class="text-center">
192
+ <i class="fas fa-coins text-xl mb-1"></i>
193
+ <div>Gold Tower</div>
194
+ <div class="text-xs">$300</div>
195
+ </div>
196
+ </button>
197
+ </div>
198
+ </div>
199
+
200
+ <div id="tower-info" class="hidden bg-gray-700 p-3 rounded-lg border border-gray-600">
201
+ <h4 class="font-bold mb-2 flex justify-between">
202
+ <span id="tower-name">Tower</span>
203
+ <button id="sell-tower" class="text-xs bg-red-600 hover:bg-red-700 px-2 py-1 rounded">Sell ($<span id="sell-price">0</span>)</button>
204
+ </h4>
205
+ <div class="text-sm mb-2">
206
+ <div>Level: <span id="tower-level">1</span></div>
207
+ <div>Damage: <span id="tower-damage">10</span></div>
208
+ <div>Range: <span id="tower-range">3</span></div>
209
+ <div>Speed: <span id="tower-speed">1.5</span>s</div>
210
+ </div>
211
+ <button id="upgrade-tower" class="upgrade-btn w-full bg-yellow-600 hover:bg-yellow-700 text-white py-1 px-3 rounded text-sm">
212
+ Upgrade ($<span id="upgrade-cost">50</span>)
213
+ </button>
214
+ </div>
215
+
216
+ <div class="mt-4 text-sm text-gray-400">
217
+ <p><i class="fas fa-info-circle mr-1"></i> Click on green buildable tiles to place towers</p>
218
+ <p><i class="fas fa-info-circle mr-1"></i> Click on a tower to upgrade it</p>
219
+ </div>
220
+ </div>
221
+ </div>
222
+ </div>
223
+
224
+ <script>
225
+ // Game State
226
+ const gameState = {
227
+ money: 150,
228
+ lives: 20,
229
+ wave: 1,
230
+ waveActive: false,
231
+ waveTimer: 30,
232
+ selectedTowerType: null,
233
+ selectedTower: null,
234
+ towers: [],
235
+ enemies: [],
236
+ projectiles: [],
237
+ path: [],
238
+ waypoints: [],
239
+ buildableTiles: []
240
+ };
241
+
242
+ // Tower Types
243
+ const towerTypes = {
244
+ arrow: {
245
+ name: "Arrow Tower",
246
+ damage: 10,
247
+ range: 3,
248
+ speed: 1.5,
249
+ cost: 100,
250
+ color: "blue",
251
+ upgradeCost: 50,
252
+ damageIncrement: 5,
253
+ rangeIncrement: 0.5,
254
+ speedIncrement: -0.2
255
+ },
256
+ cannon: {
257
+ name: "Cannon Tower",
258
+ damage: 25,
259
+ range: 2.5,
260
+ speed: 2.5,
261
+ cost: 150,
262
+ color: "red",
263
+ upgradeCost: 75,
264
+ damageIncrement: 10,
265
+ rangeIncrement: 0.3,
266
+ speedIncrement: -0.3
267
+ },
268
+ magic: {
269
+ name: "Magic Tower",
270
+ damage: 15,
271
+ range: 3.5,
272
+ speed: 1.8,
273
+ cost: 200,
274
+ color: "purple",
275
+ upgradeCost: 100,
276
+ damageIncrement: 7,
277
+ rangeIncrement: 0.4,
278
+ speedIncrement: -0.15
279
+ },
280
+ gold: {
281
+ name: "Gold Tower",
282
+ damage: 8,
283
+ range: 2,
284
+ speed: 1,
285
+ cost: 300,
286
+ color: "yellow",
287
+ upgradeCost: 150,
288
+ damageIncrement: 4,
289
+ rangeIncrement: 0.2,
290
+ speedIncrement: -0.05,
291
+ moneyPerShot: 1
292
+ }
293
+ };
294
+
295
+ // Enemy Types
296
+ const enemyTypes = [
297
+ { name: "Goblin", health: 50, speed: 1, reward: 10, spriteY: 0 },
298
+ { name: "Orc", health: 100, speed: 0.8, reward: 20, spriteY: -32 },
299
+ { name: "Troll", health: 200, speed: 0.6, reward: 40, spriteY: -64 },
300
+ { name: "Dragon", health: 500, speed: 0.5, reward: 100, spriteY: -96 }
301
+ ];
302
+
303
+ // Initialize Game Board
304
+ const gameBoard = document.getElementById('game-board');
305
+ const gridWidth = 20;
306
+ const gridHeight = 15;
307
+ const cellSize = 32;
308
+
309
+ // Generate path and buildable areas
310
+ function generatePath() {
311
+ const path = [];
312
+ const waypoints = [];
313
+ const buildableTiles = [];
314
+
315
+ // Start at top middle (red)
316
+ let x = 9, y = 0;
317
+ path.push({x, y});
318
+ waypoints.push({x, y});
319
+
320
+ // Go down
321
+ for (y = 1; y < 5; y++) {
322
+ path.push({x, y});
323
+ }
324
+ waypoints.push({x, y-1});
325
+
326
+ // Go right
327
+ for (x = 10; x < 15; x++) {
328
+ path.push({x, y-1});
329
+ }
330
+ waypoints.push({x-1, y-1});
331
+
332
+ // Go down
333
+ for (y = 5; y < 10; y++) {
334
+ path.push({x-1, y});
335
+ }
336
+ waypoints.push({x-1, y-1});
337
+
338
+ // Go left
339
+ for (x = 14; x > 5; x--) {
340
+ path.push({x, y-1});
341
+ }
342
+ waypoints.push({x+1, y-1});
343
+
344
+ // Go down to exit (blue)
345
+ for (y = 10; y < 15; y++) {
346
+ path.push({x+1, y});
347
+ }
348
+ waypoints.push({x+1, y-1});
349
+
350
+ // Generate buildable areas (not on path)
351
+ for (let y = 0; y < gridHeight; y++) {
352
+ for (let x = 0; x < gridWidth; x++) {
353
+ const isPath = path.some(point => point.x === x && point.y === y);
354
+ if (!isPath) {
355
+ // Check if tile is adjacent to path (for better gameplay)
356
+ const adjacentToPath =
357
+ path.some(point =>
358
+ (point.x === x && Math.abs(point.y - y) === 1) ||
359
+ (point.y === y && Math.abs(point.x - x) === 1)
360
+ );
361
+
362
+ if (adjacentToPath) {
363
+ buildableTiles.push({x, y});
364
+ }
365
+ }
366
+ }
367
+ }
368
+
369
+ gameState.path = path;
370
+ gameState.waypoints = waypoints;
371
+ gameState.buildableTiles = buildableTiles;
372
+
373
+ renderGrid();
374
+ }
375
+
376
+ // Render grid
377
+ function renderGrid() {
378
+ gameBoard.innerHTML = '';
379
+
380
+ // Create grid cells
381
+ for (let y = 0; y < gridHeight; y++) {
382
+ for (let x = 0; x < gridWidth; x++) {
383
+ const cell = document.createElement('div');
384
+ cell.className = 'w-8 h-8';
385
+ cell.dataset.x = x;
386
+ cell.dataset.y = y;
387
+
388
+ // Check if this cell is part of the path
389
+ const isPath = gameState.path.some(point => point.x === x && point.y === y);
390
+ const isBuildable = gameState.buildableTiles.some(point => point.x === x && point.y === y);
391
+
392
+ if (isPath) {
393
+ // Check if start or end point
394
+ if (x === 9 && y === 0) {
395
+ cell.classList.add('start-point');
396
+ } else if (x === 6 && y === 14) {
397
+ cell.classList.add('end-point');
398
+ } else {
399
+ cell.classList.add('path');
400
+ }
401
+ } else if (isBuildable) {
402
+ cell.classList.add('buildable');
403
+ cell.addEventListener('click', () => placeTower(x, y));
404
+ } else {
405
+ cell.classList.add('grass');
406
+ }
407
+
408
+ gameBoard.appendChild(cell);
409
+ }
410
+ }
411
+ }
412
+
413
+ // Place tower
414
+ function placeTower(x, y) {
415
+ if (gameState.selectedTowerType && !gameState.waveActive) {
416
+ const towerType = towerTypes[gameState.selectedTowerType];
417
+
418
+ if (gameState.money >= towerType.cost) {
419
+ gameState.money -= towerType.cost;
420
+ updateMoney();
421
+
422
+ const tower = {
423
+ type: gameState.selectedTowerType,
424
+ x: x,
425
+ y: y,
426
+ level: 1,
427
+ damage: towerType.damage,
428
+ range: towerType.range,
429
+ speed: towerType.speed,
430
+ lastShot: 0,
431
+ element: null,
432
+ rangeElement: null
433
+ };
434
+
435
+ gameState.towers.push(tower);
436
+ renderTower(tower);
437
+
438
+ // Deselect tower type after placement
439
+ gameState.selectedTowerType = null;
440
+ document.querySelectorAll('.tower-btn').forEach(btn => {
441
+ btn.classList.remove('ring-2', 'ring-yellow-400');
442
+ });
443
+ } else {
444
+ showMessage("Not enough money!");
445
+ }
446
+ }
447
+ }
448
+
449
+ // Render tower
450
+ function renderTower(tower) {
451
+ const towerElement = document.createElement('div');
452
+ towerElement.className = 'tower';
453
+ towerElement.style.left = `${tower.x * cellSize}px`;
454
+ towerElement.style.top = `${tower.y * cellSize}px`;
455
+
456
+ // Add color based on tower type
457
+ towerElement.style.filter = `hue-rotate(${getTowerHue(tower.type)}deg)`;
458
+
459
+ towerElement.addEventListener('click', (e) => {
460
+ e.stopPropagation();
461
+ selectTower(tower);
462
+ });
463
+
464
+ // Create range indicator
465
+ const rangeElement = document.createElement('div');
466
+ rangeElement.className = 'tower-range';
467
+ rangeElement.style.width = `${tower.range * cellSize * 2}px`;
468
+ rangeElement.style.height = `${tower.range * cellSize * 2}px`;
469
+ rangeElement.style.left = `${(tower.x + 0.5) * cellSize}px`;
470
+ rangeElement.style.top = `${(tower.y + 0.5) * cellSize}px`;
471
+ rangeElement.style.display = 'none';
472
+
473
+ gameBoard.appendChild(towerElement);
474
+ gameBoard.appendChild(rangeElement);
475
+
476
+ tower.element = towerElement;
477
+ tower.rangeElement = rangeElement;
478
+ }
479
+
480
+ function getTowerHue(type) {
481
+ switch(type) {
482
+ case 'arrow': return 200; // blue
483
+ case 'cannon': return 0; // red
484
+ case 'magic': return 270; // purple
485
+ case 'gold': return 50; // yellow
486
+ default: return 0;
487
+ }
488
+ }
489
+
490
+ // Select tower
491
+ function selectTower(tower) {
492
+ if (gameState.waveActive) return;
493
+
494
+ // Deselect previous tower
495
+ if (gameState.selectedTower) {
496
+ gameState.selectedTower.rangeElement.style.display = 'none';
497
+ }
498
+
499
+ gameState.selectedTower = tower;
500
+ tower.rangeElement.style.display = 'block';
501
+
502
+ // Update tower info panel
503
+ const towerType = towerTypes[tower.type];
504
+ document.getElementById('tower-info').classList.remove('hidden');
505
+ document.getElementById('tower-name').textContent = towerType.name;
506
+ document.getElementById('tower-level').textContent = tower.level;
507
+ document.getElementById('tower-damage').textContent = tower.damage;
508
+ document.getElementById('tower-range').textContent = tower.range;
509
+ document.getElementById('tower-speed').textContent = tower.speed;
510
+
511
+ // Calculate upgrade cost
512
+ const upgradeCost = towerType.upgradeCost * tower.level;
513
+ document.getElementById('upgrade-cost').textContent = upgradeCost;
514
+
515
+ // Calculate sell price (50% of total invested)
516
+ const totalInvested = towerType.cost + (tower.level - 1) * upgradeCost;
517
+ const sellPrice = Math.floor(totalInvested * 0.7);
518
+ document.getElementById('sell-price').textContent = sellPrice;
519
+ }
520
+
521
+ // Upgrade tower
522
+ document.getElementById('upgrade-tower').addEventListener('click', function() {
523
+ if (!gameState.selectedTower) return;
524
+
525
+ const tower = gameState.selectedTower;
526
+ const towerType = towerTypes[tower.type];
527
+ const upgradeCost = towerType.upgradeCost * tower.level;
528
+
529
+ if (gameState.money >= upgradeCost) {
530
+ gameState.money -= upgradeCost;
531
+ updateMoney();
532
+
533
+ tower.level++;
534
+ tower.damage += towerType.damageIncrement;
535
+ tower.range += towerType.rangeIncrement;
536
+ tower.speed += towerType.speedIncrement;
537
+
538
+ // Update tower info
539
+ document.getElementById('tower-level').textContent = tower.level;
540
+ document.getElementById('tower-damage').textContent = tower.damage;
541
+ document.getElementById('tower-range').textContent = tower.range;
542
+ document.getElementById('tower-speed').textContent = tower.speed;
543
+
544
+ // Update range indicator
545
+ tower.rangeElement.style.width = `${tower.range * cellSize * 2}px`;
546
+ tower.rangeElement.style.height = `${tower.range * cellSize * 2}px`;
547
+
548
+ // Update upgrade cost for next level
549
+ const newUpgradeCost = towerType.upgradeCost * tower.level;
550
+ document.getElementById('upgrade-cost').textContent = newUpgradeCost;
551
+
552
+ // Update sell price
553
+ const totalInvested = towerType.cost + (tower.level - 1) * upgradeCost;
554
+ const sellPrice = Math.floor(totalInvested * 0.7);
555
+ document.getElementById('sell-price').textContent = sellPrice;
556
+
557
+ showMessage(`Tower upgraded to level ${tower.level}!`);
558
+ } else {
559
+ showMessage("Not enough money for upgrade!");
560
+ }
561
+ });
562
+
563
+ // Sell tower
564
+ document.getElementById('sell-tower').addEventListener('click', function() {
565
+ if (!gameState.selectedTower) return;
566
+
567
+ const tower = gameState.selectedTower;
568
+ const towerType = towerTypes[tower.type];
569
+ const totalInvested = towerType.cost + (tower.level - 1) * towerType.upgradeCost * tower.level;
570
+ const sellPrice = Math.floor(totalInvested * 0.7);
571
+
572
+ gameState.money += sellPrice;
573
+ updateMoney();
574
+
575
+ // Remove tower elements
576
+ gameBoard.removeChild(tower.element);
577
+ gameBoard.removeChild(tower.rangeElement);
578
+
579
+ // Remove from towers array
580
+ gameState.towers = gameState.towers.filter(t => t !== tower);
581
+
582
+ // Hide tower info
583
+ document.getElementById('tower-info').classList.add('hidden');
584
+ gameState.selectedTower = null;
585
+
586
+ showMessage(`Tower sold for $${sellPrice}!`);
587
+ });
588
+
589
+ // Tower buttons
590
+ document.querySelectorAll('.tower-btn').forEach(btn => {
591
+ btn.addEventListener('click', function() {
592
+ if (gameState.waveActive) return;
593
+
594
+ gameState.selectedTowerType = this.dataset.type;
595
+
596
+ // Update UI
597
+ document.querySelectorAll('.tower-btn').forEach(b => {
598
+ b.classList.remove('ring-2', 'ring-yellow-400');
599
+ });
600
+ this.classList.add('ring-2', 'ring-yellow-400');
601
+
602
+ // Hide tower info if showing
603
+ document.getElementById('tower-info').classList.add('hidden');
604
+ if (gameState.selectedTower) {
605
+ gameState.selectedTower.rangeElement.style.display = 'none';
606
+ gameState.selectedTower = null;
607
+ }
608
+ });
609
+ });
610
+
611
+ // Start wave
612
+ document.getElementById('start-wave').addEventListener('click', startWave);
613
+
614
+ function startWave() {
615
+ if (gameState.waveActive) return;
616
+
617
+ gameState.waveActive = true;
618
+ document.getElementById('start-wave').disabled = true;
619
+
620
+ // Calculate number of enemies based on wave
621
+ const baseEnemies = 5;
622
+ const waveMultiplier = 1 + (gameState.wave - 1) * 0.3;
623
+ const totalEnemies = Math.floor(baseEnemies * waveMultiplier);
624
+
625
+ // Spawn enemies
626
+ let spawned = 0;
627
+ const spawnInterval = setInterval(() => {
628
+ if (spawned >= totalEnemies) {
629
+ clearInterval(spawnInterval);
630
+ return;
631
+ }
632
+
633
+ // Random enemy type (higher waves get stronger enemies)
634
+ let enemyTypeIndex = 0;
635
+ const random = Math.random();
636
+ if (gameState.wave > 10 && random < 0.1) {
637
+ enemyTypeIndex = 3; // Dragon
638
+ } else if (gameState.wave > 5 && random < 0.3) {
639
+ enemyTypeIndex = 2; // Troll
640
+ } else if (gameState.wave > 3 && random < 0.6) {
641
+ enemyTypeIndex = 1; // Orc
642
+ }
643
+
644
+ spawnEnemy(enemyTypes[enemyTypeIndex]);
645
+ spawned++;
646
+
647
+ // Update enemies left
648
+ document.getElementById('enemies-left').textContent = gameState.enemies.length;
649
+ }, 1000);
650
+
651
+ // Wave timer
652
+ let timeLeft = 30;
653
+ const waveTimer = setInterval(() => {
654
+ timeLeft--;
655
+ document.getElementById('wave-timer').textContent = `${timeLeft}s`;
656
+ document.getElementById('wave-progress').style.width = `${(1 - timeLeft/30) * 100}%`;
657
+
658
+ if (timeLeft <= 0 || gameState.enemies.length === 0) {
659
+ clearInterval(waveTimer);
660
+
661
+ // Check if all enemies are dead
662
+ if (gameState.enemies.length === 0) {
663
+ endWave(true);
664
+ }
665
+ }
666
+ }, 1000);
667
+ }
668
+
669
+ function endWave(success) {
670
+ gameState.waveActive = false;
671
+ document.getElementById('start-wave').disabled = false;
672
+
673
+ if (success) {
674
+ // Wave completed successfully
675
+ gameState.money += 100 + (gameState.wave * 20);
676
+ gameState.wave++;
677
+ updateMoney();
678
+ updateWave();
679
+
680
+ showMessage(`Wave ${gameState.wave-1} completed! Bonus: $${100 + (gameState.wave-1) * 20}`);
681
+ }
682
+
683
+ // Reset wave timer UI
684
+ document.getElementById('wave-timer').textContent = '30s';
685
+ document.getElementById('wave-progress').style.width = '0%';
686
+ }
687
+
688
+ function spawnEnemy(type) {
689
+ const enemy = {
690
+ type: type.name,
691
+ health: type.health,
692
+ maxHealth: type.health,
693
+ speed: type.speed,
694
+ reward: type.reward,
695
+ x: gameState.path[0].x,
696
+ y: gameState.path[0].y,
697
+ pathIndex: 0,
698
+ element: null,
699
+ healthBar: null
700
+ };
701
+
702
+ gameState.enemies.push(enemy);
703
+ renderEnemy(enemy);
704
+ }
705
+
706
+ function renderEnemy(enemy) {
707
+ const enemyElement = document.createElement('div');
708
+ enemyElement.className = 'enemy';
709
+ enemyElement.style.left = `${enemy.x * cellSize}px`;
710
+ enemyElement.style.top = `${enemy.y * cellSize}px`;
711
+ enemyElement.style.backgroundPositionY = `${enemyTypes.find(e => e.name === enemy.type).spriteY}px`;
712
+
713
+ // Health bar
714
+ const healthBar = document.createElement('div');
715
+ healthBar.className = 'health-bar';
716
+ enemyElement.appendChild(healthBar);
717
+
718
+ gameBoard.appendChild(enemyElement);
719
+ enemy.element = enemyElement;
720
+ enemy.healthBar = healthBar;
721
+ }
722
+
723
+ // Game loop
724
+ function gameLoop(timestamp) {
725
+ // Move enemies
726
+ gameState.enemies.forEach(enemy => {
727
+ if (enemy.pathIndex < gameState.path.length - 1) {
728
+ const nextPoint = gameState.path[enemy.pathIndex + 1];
729
+ const dx = nextPoint.x - enemy.x;
730
+ const dy = nextPoint.y - enemy.y;
731
+
732
+ // Normalize direction
733
+ const distance = Math.sqrt(dx * dx + dy * dy);
734
+ const speed = 0.02 * enemy.speed;
735
+
736
+ if (distance < speed) {
737
+ // Reached next point
738
+ enemy.x = nextPoint.x;
739
+ enemy.y = nextPoint.y;
740
+ enemy.pathIndex++;
741
+
742
+ // Check if reached end
743
+ if (enemy.pathIndex === gameState.path.length - 1) {
744
+ // Enemy reached the end
745
+ gameState.lives--;
746
+ updateLives();
747
+
748
+ // Remove enemy
749
+ gameBoard.removeChild(enemy.element);
750
+ gameState.enemies = gameState.enemies.filter(e => e !== enemy);
751
+
752
+ if (gameState.lives <= 0) {
753
+ gameOver();
754
+ }
755
+
756
+ return;
757
+ }
758
+ } else {
759
+ // Move towards next point
760
+ enemy.x += (dx / distance) * speed;
761
+ enemy.y += (dy / distance) * speed;
762
+ }
763
+
764
+ // Update position
765
+ enemy.element.style.left = `${enemy.x * cellSize}px`;
766
+ enemy.element.style.top = `${enemy.y * cellSize}px`;
767
+ }
768
+ });
769
+
770
+ // Tower attacks
771
+ gameState.towers.forEach(tower => {
772
+ if (timestamp - tower.lastShot > tower.speed * 1000) {
773
+ // Find closest enemy in range
774
+ let closestEnemy = null;
775
+ let minDistance = Infinity;
776
+
777
+ gameState.enemies.forEach(enemy => {
778
+ const dx = enemy.x - (tower.x + 0.5);
779
+ const dy = enemy.y - (tower.y + 0.5);
780
+ const distance = Math.sqrt(dx * dx + dy * dy);
781
+
782
+ if (distance <= tower.range && distance < minDistance) {
783
+ closestEnemy = enemy;
784
+ minDistance = distance;
785
+ }
786
+ });
787
+
788
+ if (closestEnemy) {
789
+ // Shoot at enemy
790
+ shoot(tower, closestEnemy, timestamp);
791
+ tower.lastShot = timestamp;
792
+ }
793
+ }
794
+ });
795
+
796
+ // Move projectiles
797
+ gameState.projectiles.forEach((proj, index) => {
798
+ const dx = proj.targetX - proj.x;
799
+ const dy = proj.targetY - proj.y;
800
+ const distance = Math.sqrt(dx * dx + dy * dy);
801
+
802
+ if (distance < 0.2) {
803
+ // Hit target
804
+ proj.target.health -= proj.damage;
805
+
806
+ // Update health bar
807
+ if (proj.target.healthBar) {
808
+ const healthPercent = (proj.target.health / proj.target.maxHealth) * 100;
809
+ proj.target.healthBar.style.width = `${healthPercent}%`;
810
+
811
+ if (healthPercent > 50) {
812
+ proj.target.healthBar.style.backgroundColor = 'green';
813
+ } else if (healthPercent > 25) {
814
+ proj.target.healthBar.style.backgroundColor = 'orange';
815
+ } else {
816
+ proj.target.healthBar.style.backgroundColor = 'red';
817
+ }
818
+ }
819
+
820
+ // Check if enemy died
821
+ if (proj.target.health <= 0) {
822
+ gameState.money += proj.target.reward;
823
+ updateMoney();
824
+
825
+ gameBoard.removeChild(proj.target.element);
826
+ gameState.enemies = gameState.enemies.filter(e => e !== proj.target);
827
+
828
+ // Check if wave completed
829
+ if (gameState.waveActive && gameState.enemies.length === 0) {
830
+ endWave(true);
831
+ }
832
+ }
833
+
834
+ // Remove projectile
835
+ gameBoard.removeChild(proj.element);
836
+ gameState.projectiles.splice(index, 1);
837
+ } else {
838
+ // Move projectile
839
+ const speed = 0.2;
840
+ proj.x += (dx / distance) * speed;
841
+ proj.y += (dy / distance) * speed;
842
+
843
+ proj.element.style.left = `${proj.x * cellSize}px`;
844
+ proj.element.style.top = `${proj.y * cellSize}px`;
845
+ }
846
+ });
847
+
848
+ requestAnimationFrame(gameLoop);
849
+ }
850
+
851
+ function shoot(tower, enemy, timestamp) {
852
+ const towerType = towerTypes[tower.type];
853
+
854
+ // Create projectile
855
+ const projectile = {
856
+ x: tower.x + 0.5,
857
+ y: tower.y + 0.5,
858
+ targetX: enemy.x + 0.5,
859
+ targetY: enemy.y + 0.5,
860
+ damage: tower.damage,
861
+ target: enemy,
862
+ element: null
863
+ };
864
+
865
+ // Special effects for tower types
866
+ if (tower.type === 'gold') {
867
+ // Gold tower earns money per shot
868
+ gameState.money += towerType.moneyPerShot;
869
+ updateMoney();
870
+ }
871
+
872
+ // Create projectile element
873
+ const projElement = document.createElement('div');
874
+ projElement.className = 'projectile';
875
+
876
+ // Color based on tower type
877
+ switch(tower.type) {
878
+ case 'arrow': projElement.style.backgroundColor = '#3498db'; break;
879
+ case 'cannon': projElement.style.backgroundColor = '#e74c3c'; break;
880
+ case 'magic': projElement.style.backgroundColor = '#9b59b6'; break;
881
+ case 'gold': projElement.style.backgroundColor = '#f1c40f'; break;
882
+ }
883
+
884
+ projElement.style.left = `${projectile.x * cellSize}px`;
885
+ projElement.style.top = `${projectile.y * cellSize}px`;
886
+ gameBoard.appendChild(projElement);
887
+
888
+ projectile.element = projElement;
889
+ gameState.projectiles.push(projectile);
890
+ }
891
+
892
+ function gameOver() {
893
+ showMessage("Game Over! Refresh to play again.");
894
+ gameState.waveActive = false;
895
+ document.getElementById('start-wave').disabled = true;
896
+ }
897
+
898
+ // UI Updates
899
+ function updateMoney() {
900
+ document.getElementById('money').textContent = gameState.money;
901
+ }
902
+
903
+ function updateLives() {
904
+ document.getElementById('lives').textContent = gameState.lives;
905
+
906
+ // Flash lives when low
907
+ if (gameState.lives <= 5) {
908
+ const livesEl = document.getElementById('lives');
909
+ livesEl.classList.add('text-red-500', 'animate-pulse');
910
+ } else {
911
+ document.getElementById('lives').classList.remove('text-red-500', 'animate-pulse');
912
+ }
913
+ }
914
+
915
+ function updateWave() {
916
+ document.getElementById('wave').textContent = gameState.wave;
917
+ }
918
+
919
+ function showMessage(msg) {
920
+ const message = document.createElement('div');
921
+ message.className = 'fixed top-4 left-1/2 transform -translate-x-1/2 bg-gray-800 text-white px-4 py-2 rounded-lg shadow-lg z-50 animate-bounce';
922
+ message.textContent = msg;
923
+ document.body.appendChild(message);
924
+
925
+ setTimeout(() => {
926
+ message.classList.remove('animate-bounce');
927
+ message.classList.add('opacity-0', 'transition-opacity', 'duration-500');
928
+ setTimeout(() => document.body.removeChild(message), 500);
929
+ }, 2000);
930
+ }
931
+
932
+ // Initialize game
933
+ generatePath();
934
+ updateMoney();
935
+ updateLives();
936
+ updateWave();
937
+
938
+ // Start game loop
939
+ requestAnimationFrame(gameLoop);
940
+
941
+ // Helpers
942
+ document.addEventListener('click', function(e) {
943
+ // Click outside to deselect tower
944
+ if (!e.target.closest('#game-board') && !e.target.closest('.tower-btn') && !e.target.closest('#tower-info')) {
945
+ if (gameState.selectedTower) {
946
+ gameState.selectedTower.rangeElement.style.display = 'none';
947
+ gameState.selectedTower = null;
948
+ document.getElementById('tower-info').classList.add('hidden');
949
+ }
950
+
951
+ if (gameState.selectedTowerType) {
952
+ gameState.selectedTowerType = null;
953
+ document.querySelectorAll('.tower-btn').forEach(btn => {
954
+ btn.classList.remove('ring-2', 'ring-yellow-400');
955
+ });
956
+ }
957
+ }
958
+ });
959
+ </script>
960
+ <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=Phoenixoni/tower" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
961
+ </html>
prompts.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ Сделай игру типа tower defense
2
+ Убери энциклопедию с низу. сделай путь для врагов и места куда устанавливать башни. и почини кнопку старт, т.к. игра не запускается.