adnannovus commited on
Commit
830dc9a
·
verified ·
1 Parent(s): f463f33
Files changed (1) hide show
  1. index.html +443 -19
index.html CHANGED
@@ -1,19 +1,443 @@
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>Tower Defense</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ display: flex;
16
+ justify-content: center;
17
+ align-items: center;
18
+ min-height: 100vh;
19
+ background: #1a1a1a;
20
+ font-family: Arial, sans-serif;
21
+ color: white;
22
+ }
23
+
24
+ #gameContainer {
25
+ position: relative;
26
+ width: 800px;
27
+ height: 600px;
28
+ background: #2a2a2a;
29
+ border-radius: 10px;
30
+ overflow: hidden;
31
+ }
32
+
33
+ #gameCanvas {
34
+ position: absolute;
35
+ left: 0;
36
+ top: 0;
37
+ }
38
+
39
+ .ui-panel {
40
+ position: absolute;
41
+ right: 0;
42
+ top: 0;
43
+ width: 200px;
44
+ height: 100%;
45
+ background: rgba(0, 0, 0, 0.8);
46
+ padding: 10px;
47
+ }
48
+
49
+ .tower-btn {
50
+ display: block;
51
+ width: 100%;
52
+ padding: 10px;
53
+ margin: 5px 0;
54
+ background: #4a4a4a;
55
+ border: none;
56
+ border-radius: 5px;
57
+ color: white;
58
+ cursor: pointer;
59
+ transition: background 0.3s;
60
+ }
61
+
62
+ .tower-btn:hover {
63
+ background: #5a5a5a;
64
+ }
65
+
66
+ #stats {
67
+ position: absolute;
68
+ left: 10px;
69
+ top: 10px;
70
+ font-size: 16px;
71
+ text-shadow: 2px 2px 2px rgba(0,0,0,0.5);
72
+ z-index: 1;
73
+ }
74
+
75
+ #waveMessage {
76
+ position: absolute;
77
+ left: 50%;
78
+ top: 50%;
79
+ transform: translate(-50%, -50%);
80
+ font-size: 24px;
81
+ color: white;
82
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.7);
83
+ display: none;
84
+ z-index: 2;
85
+ }
86
+
87
+ @keyframes fadeInOut {
88
+ 0% { opacity: 0; transform: translate(-50%, -50%) scale(0.5); }
89
+ 10% { opacity: 1; transform: translate(-50%, -50%) scale(1.1); }
90
+ 20% { transform: translate(-50%, -50%) scale(1); }
91
+ 80% { opacity: 1; }
92
+ 100% { opacity: 0; }
93
+ }
94
+ </style>
95
+ </head>
96
+ <body>
97
+ <div id="gameContainer">
98
+ <canvas id="gameCanvas"></canvas>
99
+ <div id="stats">
100
+ Lives: <span id="lives">20</span>
101
+ Gold: <span id="gold">200</span>
102
+ Wave: <span id="wave">1</span>
103
+ </div>
104
+ <div id="waveMessage"></div>
105
+ <div class="ui-panel">
106
+ <button class="tower-btn" data-type="basic">Basic Tower ($100)</button>
107
+ <button class="tower-btn" data-type="sniper">Sniper Tower ($200)</button>
108
+ <button class="tower-btn" data-type="splash">Splash Tower ($300)</button>
109
+ </div>
110
+ </div>
111
+
112
+ <script>
113
+ const canvas = document.getElementById('gameCanvas');
114
+ const ctx = canvas.getContext('2d');
115
+ const waveMessage = document.getElementById('waveMessage');
116
+
117
+ canvas.width = 600;
118
+ canvas.height = 600;
119
+
120
+ let gameState = {
121
+ lives: 20,
122
+ gold: 200,
123
+ wave: 0,
124
+ towers: [],
125
+ enemies: [],
126
+ path: [],
127
+ projectiles: [],
128
+ selectedTower: null,
129
+ waveInProgress: false,
130
+ enemiesSpawned: 0,
131
+ totalEnemiesInWave: 10,
132
+ spawnInterval: null,
133
+ timeBetweenWaves: 5000
134
+ };
135
+
136
+ const towerTypes = {
137
+ basic: {
138
+ cost: 100,
139
+ range: 120,
140
+ damage: 30,
141
+ fireRate: 2,
142
+ color: '#4a90e2',
143
+ projectileColor: '#4a90e2',
144
+ projectileSize: 5
145
+ },
146
+ sniper: {
147
+ cost: 200,
148
+ range: 250,
149
+ damage: 100,
150
+ fireRate: 1,
151
+ color: '#e24a4a',
152
+ projectileColor: '#e24a4a',
153
+ projectileSize: 7
154
+ },
155
+ splash: {
156
+ cost: 300,
157
+ range: 100,
158
+ damage: 45,
159
+ fireRate: 3,
160
+ color: '#4ae24a',
161
+ projectileColor: '#4ae24a',
162
+ projectileSize: 6
163
+ }
164
+ };
165
+
166
+ function generatePath() {
167
+ const path = [];
168
+ let x = 0;
169
+ let y = Math.random() * (canvas.height - 200) + 100;
170
+ let direction = 1;
171
+
172
+ while (x < canvas.width - 50) {
173
+ path.push({ x, y });
174
+ x += 20;
175
+ y += Math.random() * 40 * direction;
176
+ direction = -direction;
177
+ y = Math.max(50, Math.min(canvas.height - 50, y));
178
+ }
179
+
180
+ return path;
181
+ }
182
+
183
+ function showWaveMessage(message, duration = 3000) {
184
+ waveMessage.textContent = message;
185
+ waveMessage.style.display = 'block';
186
+ waveMessage.style.animation = 'fadeInOut 3s ease-in-out';
187
+
188
+ setTimeout(() => {
189
+ waveMessage.style.display = 'none';
190
+ }, duration);
191
+ }
192
+
193
+ class Enemy {
194
+ constructor() {
195
+ this.pathIndex = 0;
196
+ this.x = gameState.path[0].x;
197
+ this.y = gameState.path[0].y;
198
+ this.health = 100;
199
+ this.maxHealth = 100;
200
+ this.speed = 1;
201
+ this.value = 20;
202
+ }
203
+
204
+ update() {
205
+ if (this.pathIndex < gameState.path.length - 1) {
206
+ const target = gameState.path[this.pathIndex + 1];
207
+ const dx = target.x - this.x;
208
+ const dy = target.y - this.y;
209
+ const distance = Math.sqrt(dx * dx + dy * dy);
210
+
211
+ if (distance < this.speed) {
212
+ this.pathIndex++;
213
+ } else {
214
+ this.x += (dx / distance) * this.speed;
215
+ this.y += (dy / distance) * this.speed;
216
+ }
217
+ } else {
218
+ gameState.lives--;
219
+ return true;
220
+ }
221
+
222
+ if (this.health <= 0) {
223
+ gameState.gold += this.value;
224
+ return true;
225
+ }
226
+ return false;
227
+ }
228
+
229
+ draw() {
230
+ ctx.fillStyle = '#ff0000';
231
+ ctx.beginPath();
232
+ ctx.arc(this.x, this.y, 10, 0, Math.PI * 2);
233
+ ctx.fill();
234
+
235
+ ctx.fillStyle = '#000000';
236
+ ctx.fillRect(this.x - 15, this.y - 20, 30, 5);
237
+ ctx.fillStyle = '#00ff00';
238
+ ctx.fillRect(this.x - 15, this.y - 20, (this.health / this.maxHealth) * 30, 5);
239
+ }
240
+ }
241
+
242
+ class Projectile {
243
+ constructor(x, y, target, damage, color, size, speed = 8) {
244
+ this.x = x;
245
+ this.y = y;
246
+ this.target = target;
247
+ this.damage = damage;
248
+ this.color = color;
249
+ this.size = size;
250
+ this.speed = speed;
251
+ }
252
+
253
+ update() {
254
+ if (!this.target) return true;
255
+
256
+ const dx = this.target.x - this.x;
257
+ const dy = this.target.y - this.y;
258
+ const distance = Math.sqrt(dx * dx + dy * dy);
259
+
260
+ if (distance < this.speed) {
261
+ this.target.health -= this.damage;
262
+ return true;
263
+ }
264
+
265
+ this.x += (dx / distance) * this.speed;
266
+ this.y += (dy / distance) * this.speed;
267
+ return false;
268
+ }
269
+
270
+ draw() {
271
+ ctx.fillStyle = this.color;
272
+ ctx.beginPath();
273
+ ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
274
+ ctx.fill();
275
+ }
276
+ }
277
+
278
+ class Tower {
279
+ constructor(x, y, type) {
280
+ this.x = x;
281
+ this.y = y;
282
+ this.type = type;
283
+ this.lastShot = 0;
284
+ this.level = 1;
285
+ Object.assign(this, towerTypes[type]);
286
+ }
287
+
288
+ update(time) {
289
+ if (time - this.lastShot > 1000 / this.fireRate) {
290
+ for (let enemy of gameState.enemies) {
291
+ const dx = enemy.x - this.x;
292
+ const dy = enemy.y - this.y;
293
+ const distance = Math.sqrt(dx * dx + dy * dy);
294
+
295
+ if (distance <= this.range) {
296
+ gameState.projectiles.push(
297
+ new Projectile(
298
+ this.x,
299
+ this.y,
300
+ enemy,
301
+ this.damage * this.level,
302
+ this.projectileColor,
303
+ this.projectileSize
304
+ )
305
+ );
306
+ this.lastShot = time;
307
+ break;
308
+ }
309
+ }
310
+ }
311
+ }
312
+
313
+ draw() {
314
+ ctx.fillStyle = this.color;
315
+ ctx.beginPath();
316
+ ctx.arc(this.x, this.y, 20, 0, Math.PI * 2);
317
+ ctx.fill();
318
+
319
+ if (this === gameState.selectedTower) {
320
+ ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)';
321
+ ctx.beginPath();
322
+ ctx.arc(this.x, this.y, this.range, 0, Math.PI * 2);
323
+ ctx.stroke();
324
+ }
325
+ }
326
+ }
327
+
328
+ function drawPath() {
329
+ ctx.strokeStyle = '#666666';
330
+ ctx.lineWidth = 30;
331
+ ctx.lineCap = 'round';
332
+ ctx.lineJoin = 'round';
333
+
334
+ ctx.beginPath();
335
+ ctx.moveTo(gameState.path[0].x, gameState.path[0].y);
336
+ for (let i = 1; i < gameState.path.length; i++) {
337
+ ctx.lineTo(gameState.path[i].x, gameState.path[i].y);
338
+ }
339
+ ctx.stroke();
340
+ }
341
+
342
+ function startNewWave() {
343
+ gameState.wave++;
344
+ gameState.waveInProgress = true;
345
+ gameState.enemiesSpawned = 0;
346
+ gameState.totalEnemiesInWave = Math.floor(10 + gameState.wave * 2);
347
+ gameState.path = generatePath();
348
+ gameState.towers = [];
349
+ gameState.projectiles = [];
350
+ gameState.enemies = [];
351
+
352
+ showWaveMessage(`Wave ${gameState.wave} Starting!`);
353
+
354
+ if(gameState.spawnInterval) clearInterval(gameState.spawnInterval);
355
+
356
+ setTimeout(() => {
357
+ gameState.spawnInterval = setInterval(() => {
358
+ if(gameState.enemiesSpawned < gameState.totalEnemiesInWave) {
359
+ const enemy = new Enemy();
360
+ enemy.health = 100 + (gameState.wave - 1) * 20;
361
+ enemy.maxHealth = enemy.health;
362
+ enemy.value = 20 + Math.floor(gameState.wave / 2) * 10;
363
+ gameState.enemies.push(enemy);
364
+ gameState.enemiesSpawned++;
365
+ } else {
366
+ clearInterval(gameState.spawnInterval);
367
+ }
368
+ }, 1000);
369
+ }, 2000);
370
+ }
371
+
372
+ function checkWaveStatus() {
373
+ if (!gameState.waveInProgress) return;
374
+
375
+ if (gameState.enemiesSpawned >= gameState.totalEnemiesInWave &&
376
+ gameState.enemies.length === 0) {
377
+ gameState.waveInProgress = false;
378
+ const bonus = 100 + gameState.wave * 20;
379
+ gameState.gold += bonus;
380
+
381
+ setTimeout(startNewWave, gameState.timeBetweenWaves);
382
+ }
383
+ }
384
+
385
+ function gameLoop(timestamp) {
386
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
387
+
388
+ drawPath();
389
+
390
+ gameState.enemies = gameState.enemies.filter(enemy => !enemy.update());
391
+ gameState.enemies.forEach(enemy => enemy.draw());
392
+
393
+ gameState.towers.forEach(tower => {
394
+ tower.update(timestamp);
395
+ tower.draw();
396
+ });
397
+
398
+ gameState.projectiles = gameState.projectiles.filter(proj => !proj.update());
399
+ gameState.projectiles.forEach(proj => proj.draw());
400
+
401
+ checkWaveStatus();
402
+
403
+ document.getElementById('lives').textContent = gameState.lives;
404
+ document.getElementById('gold').textContent = gameState.gold;
405
+ document.getElementById('wave').textContent = gameState.wave;
406
+
407
+ if (gameState.lives <= 0) {
408
+ alert('Game Over!');
409
+ return;
410
+ }
411
+
412
+ requestAnimationFrame(gameLoop);
413
+ }
414
+
415
+ canvas.addEventListener('click', (e) => {
416
+ const rect = canvas.getBoundingClientRect();
417
+ const x = e.clientX - rect.left;
418
+ const y = e.clientY - rect.top;
419
+
420
+ if (gameState.selectedTower) {
421
+ const tower = new Tower(x, y, gameState.selectedTower);
422
+ if (gameState.gold >= tower.cost) {
423
+ gameState.towers.push(tower);
424
+ gameState.gold -= tower.cost;
425
+ gameState.selectedTower = null;
426
+ }
427
+ }
428
+ });
429
+
430
+ document.querySelectorAll('.tower-btn').forEach(btn => {
431
+ btn.addEventListener('click', () => {
432
+ const type = btn.dataset.type;
433
+ if (gameState.gold >= towerTypes[type].cost) {
434
+ gameState.selectedTower = type;
435
+ }
436
+ });
437
+ });
438
+
439
+ startNewWave();
440
+ requestAnimationFrame(gameLoop);
441
+ </script>
442
+ </body>
443
+ </html>