Amano13 commited on
Commit
7be8661
Β·
verified Β·
1 Parent(s): 618508f

Create a retro-modern space invaders clone

Browse files
Files changed (2) hide show
  1. README.md +8 -5
  2. index.html +536 -18
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Pixel Cosmos Invaders
3
- emoji: πŸ†
4
- colorFrom: green
5
- colorTo: gray
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: Pixel Cosmos Invaders πŸš€
3
+ colorFrom: purple
4
+ colorTo: blue
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://deepsite.hf.co).
index.html CHANGED
@@ -1,19 +1,537 @@
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>Pixel Cosmos Invaders</title>
7
+ <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ <script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.globe.min.js"></script>
12
+ <style>
13
+ @import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');
14
+ @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&display=swap');
15
+
16
+ * {
17
+ margin: 0;
18
+ padding: 0;
19
+ box-sizing: border-box;
20
+ }
21
+
22
+ body {
23
+ font-family: 'Orbitron', sans-serif;
24
+ overflow: hidden;
25
+ background: #0a0a0a;
26
+ }
27
+
28
+ .game-container {
29
+ position: relative;
30
+ width: 100vw;
31
+ height: 100vh;
32
+ display: flex;
33
+ flex-direction: column;
34
+ align-items: center;
35
+ justify-content: center;
36
+ }
37
+
38
+ .vanta-background {
39
+ position: absolute;
40
+ top: 0;
41
+ left: 0;
42
+ width: 100%;
43
+ height: 100%;
44
+ z-index: -1;
45
+ }
46
+
47
+ .game-title {
48
+ font-family: 'Press Start 2P', cursive;
49
+ font-size: 3rem;
50
+ background: linear-gradient(45deg, #ff00cc, #3333ff);
51
+ -webkit-background-clip: text;
52
+ -webkit-text-fill-color: transparent;
53
+ text-shadow: 0 0 30px rgba(255, 0, 204, 0.5);
54
+ margin-bottom: 2rem;
55
+ animation: glow 2s ease-in-out infinite alternate;
56
+ }
57
+
58
+ @keyframes glow {
59
+ from {
60
+ text-shadow: 0 0 20px rgba(255, 0, 204, 0.5);
61
+ }
62
+ to {
63
+ text-shadow: 0 0 30px rgba(51, 51, 255, 0.8), 0 0 40px rgba(51, 51, 255, 0.6);
64
+ }
65
+ }
66
+
67
+ .game-canvas {
68
+ background: rgba(10, 10, 30, 0.8);
69
+ border: 3px solid #ff00cc;
70
+ border-radius: 10px;
71
+ box-shadow: 0 0 50px rgba(255, 0, 204, 0.3),
72
+ inset 0 0 50px rgba(51, 51, 255, 0.2);
73
+ }
74
+
75
+ .controls {
76
+ display: flex;
77
+ gap: 2rem;
78
+ margin-top: 2rem;
79
+ }
80
+
81
+ .btn {
82
+ font-family: 'Press Start 2P', cursive;
83
+ padding: 1rem 2rem;
84
+ background: linear-gradient(45deg, #ff00cc, #3333ff);
85
+ border: none;
86
+ border-radius: 8px;
87
+ color: white;
88
+ cursor: pointer;
89
+ transition: all 0.3s ease;
90
+ text-transform: uppercase;
91
+ font-size: 0.8rem;
92
+ box-shadow: 0 0 20px rgba(255, 0, 204, 0.4);
93
+ }
94
+
95
+ .btn:hover {
96
+ transform: translateY(-2px);
97
+ box-shadow: 0 0 30px rgba(51, 51, 255, 0.6);
98
+ }
99
+
100
+ .stats {
101
+ display: flex;
102
+ gap: 3rem;
103
+ margin-top: 1.5rem;
104
+ color: #00ffcc;
105
+ font-size: 1.2rem;
106
+ }
107
+
108
+ .stat-item {
109
+ display: flex;
110
+ align-items: center;
111
+ gap: 0.5rem;
112
+ }
113
+
114
+ .mobile-controls {
115
+ display: none;
116
+ margin-top: 2rem;
117
+ gap: 1rem;
118
+ }
119
+
120
+ .mobile-btn {
121
+ width: 80px;
122
+ height: 80px;
123
+ border-radius: 50%;
124
+ background: linear-gradient(45deg, #ff00cc, #3333ff);
125
+ border: none;
126
+ color: white;
127
+ font-size: 2rem;
128
+ display: flex;
129
+ align-items: center;
130
+ justify-content: center;
131
+ box-shadow: 0 0 20px rgba(255, 0, 204, 0.4);
132
+ }
133
+
134
+ @media (max-width: 768px) {
135
+ .game-title {
136
+ font-size: 1.5rem;
137
+ }
138
+
139
+ .controls {
140
+ flex-direction: column;
141
+ gap: 1rem;
142
+ }
143
+
144
+ .mobile-controls {
145
+ display: flex;
146
+ }
147
+
148
+ .stats {
149
+ flex-direction: column;
150
+ gap: 1rem;
151
+ font-size: 1rem;
152
+ }
153
+ }
154
+ </style>
155
+ </head>
156
+ <body>
157
+ <div class="game-container">
158
+ <div class="vanta-background" id="vanta-bg"></div>
159
+
160
+ <h1 class="game-title">PIXEL COSMOS INVADERS</h1>
161
+
162
+ <canvas id="gameCanvas" class="game-canvas" width="800" height="600"></canvas>
163
+
164
+ <div class="controls">
165
+ <button class="btn" onclick="startGame()">
166
+ <i data-feather="play"></i> START GAME
167
+ </button>
168
+ <button class="btn" onclick="pauseGame()">
169
+ <i data-feather="pause"></i> PAUSE
170
+ </button>
171
+ <button class="btn" onclick="resetGame()">
172
+ <i data-feather="refresh-cw"></i> RESTART
173
+ </button>
174
+ </div>
175
+
176
+ <div class="mobile-controls">
177
+ <button class="mobile-btn" onmousedown="moveLeft()" ontouchstart="moveLeft()">
178
+ <i data-feather="chevron-left"></i>
179
+ </button>
180
+ <button class="mobile-btn" onmousedown="shoot()" ontouchstart="shoot()">
181
+ <i data-feather="zap"></i>
182
+ </button>
183
+ <button class="mobile-btn" onmousedown="moveRight()" ontouchstart="moveRight()">
184
+ <i data-feather="chevron-right"></i>
185
+ </button>
186
+ </div>
187
+
188
+ <div class="stats">
189
+ <div class="stat-item">
190
+ <i data-feather="target"></i>
191
+ <span>SCORE: <span id="score">0</span></span>
192
+ </div>
193
+ <div class="stat-item">
194
+ <i data-feather="heart"></i>
195
+ <span>LIVES: <span id="lives">3</span></span>
196
+ </div>
197
+ <div class="stat-item">
198
+ <i data-feather="award"></i>
199
+ <span>LEVEL: <span id="level">1</span></span>
200
+ </div>
201
+ </div>
202
+ </div>
203
+
204
+ <script>
205
+ // Vanta.js background
206
+ VANTA.GLOBE({
207
+ el: "#vanta-bg",
208
+ mouseControls: true,
209
+ touchControls: true,
210
+ gyroControls: false,
211
+ minHeight: 200.00,
212
+ minWidth: 200.00,
213
+ scale: 1.00,
214
+ scaleMobile: 1.00,
215
+ color: 0xff00cc,
216
+ backgroundColor: 0x0a0a0a,
217
+ size: 0.8
218
+ });
219
+
220
+ // Game variables
221
+ const canvas = document.getElementById('gameCanvas');
222
+ const ctx = canvas.getContext('2d');
223
+ let gameRunning = false;
224
+ let score = 0;
225
+ let lives = 3;
226
+ let level = 1;
227
+
228
+ // Player
229
+ const player = {
230
+ x: canvas.width / 2 - 25,
231
+ y: canvas.height - 50,
232
+ width: 50,
233
+ height: 30,
234
+ speed: 8,
235
+ movingLeft: false,
236
+ movingRight: false
237
+ };
238
+
239
+ // Bullets
240
+ const bullets = [];
241
+ const bulletSpeed = 10;
242
+
243
+ // Enemies
244
+ const enemies = [];
245
+ const enemyRows = 5;
246
+ const enemyCols = 10;
247
+ let enemySpeed = 1;
248
+ let enemyDirection = 1;
249
+
250
+ // Initialize enemies
251
+ function initEnemies() {
252
+ enemies.length = 0;
253
+ for (let row = 0; row < enemyRows; row++) {
254
+ for (let col = 0; col < enemyCols; col++) {
255
+ enemies.push({
256
+ x: col * 60 + 50,
257
+ y: row * 50 + 50,
258
+ width: 40,
259
+ height: 30,
260
+ alive: true
261
+ });
262
+ }
263
+ }
264
+ }
265
+
266
+ // Draw player
267
+ function drawPlayer() {
268
+ ctx.fillStyle = '#3333ff';
269
+ ctx.beginPath();
270
+ ctx.moveTo(player.x, player.y + player.height);
271
+ ctx.lineTo(player.x + player.width / 2, player.y);
272
+ ctx.lineTo(player.x + player.width, player.y + player.height);
273
+ ctx.closePath();
274
+ ctx.fill();
275
+
276
+ // Glow effect
277
+ ctx.shadowColor = '#3333ff';
278
+ ctx.shadowBlur = 20;
279
+ ctx.fill();
280
+ ctx.shadowBlur = 0;
281
+ }
282
+
283
+ // Draw bullets
284
+ function drawBullets() {
285
+ ctx.fillStyle = '#ff00cc';
286
+ bullets.forEach(bullet => {
287
+ ctx.beginPath();
288
+ ctx.arc(bullet.x, bullet.y, 5, 0, Math.PI * 2);
289
+ ctx.fill();
290
+ ctx.shadowColor = '#ff00cc';
291
+ ctx.shadowBlur = 15;
292
+ ctx.fill();
293
+ ctx.shadowBlur = 0;
294
+ });
295
+ }
296
+
297
+ // Draw enemies
298
+ function drawEnemies() {
299
+ ctx.fillStyle = '#00ffcc';
300
+ enemies.forEach(enemy => {
301
+ if (enemy.alive) {
302
+ ctx.beginPath();
303
+ ctx.arc(enemy.x + enemy.width / 2, enemy.y + enemy.height / 2, 15, 0, Math.PI * 2);
304
+ ctx.fill();
305
+ ctx.shadowColor = '#00ffcc';
306
+ ctx.shadowBlur = 15;
307
+ ctx.fill();
308
+ ctx.shadowBlur = 0;
309
+
310
+ // Alien details
311
+ ctx.fillStyle = '#ff00cc';
312
+ ctx.beginPath();
313
+ ctx.arc(enemy.x + enemy.width / 2 - 8, enemy.y + enemy.height / 2 - 5, 3, 0, Math.PI * 2);
314
+ ctx.arc(enemy.x + enemy.width / 2 + 8, enemy.y + enemy.height / 2 - 5, 3, 0, Math.PI * 2);
315
+ ctx.fill();
316
+ }
317
+ });
318
+ }
319
+
320
+ // Update game state
321
+ function update() {
322
+ // Move player
323
+ if (player.movingLeft && player.x > 0) {
324
+ player.x -= player.speed;
325
+ }
326
+ if (player.movingRight && player.x < canvas.width - player.width) {
327
+ player.x += player.speed;
328
+ }
329
+
330
+ // Move bullets
331
+ for (let i = bullets.length - 1; i >= 0; i--) {
332
+ bullets[i].y -= bulletSpeed;
333
+
334
+ // Remove bullets that go off screen
335
+ if (bullets[i].y < 0) {
336
+ bullets.splice(i, 1);
337
+ }
338
+ }
339
+
340
+ // Move enemies
341
+ let edgeReached = false;
342
+ enemies.forEach(enemy => {
343
+ if (enemy.alive) {
344
+ enemy.x += enemySpeed * enemyDirection;
345
+ if (enemy.x <= 0 || enemy.x + enemy.width >= canvas.width) {
346
+ edgeReached = true;
347
+ }
348
+ }
349
+ });
350
+
351
+ // Change direction if edge reached
352
+ if (edgeReached) {
353
+ enemyDirection *= -1;
354
+ enemies.forEach(enemy => {
355
+ if (enemy.alive) {
356
+ enemy.y += 20;
357
+ }
358
+ });
359
+ }
360
+
361
+ // Check collisions
362
+ checkCollisions();
363
+
364
+ // Check level completion
365
+ if (enemies.every(enemy => !enemy.alive)) {
366
+ level++;
367
+ document.getElementById('level').textContent = level;
368
+ enemySpeed += 0.5;
369
+ initEnemies();
370
+ }
371
+ }
372
+
373
+ // Check collisions
374
+ function checkCollisions() {
375
+ // Bullet-enemy collisions
376
+ bullets.forEach((bullet, bulletIndex) => {
377
+ enemies.forEach((enemy, enemyIndex) => {
378
+ if (enemy.alive &&
379
+ bullet.x > enemy.x &&
380
+ bullet.x < enemy.x + enemy.width &&
381
+ bullet.y > enemy.y &&
382
+ bullet.y < enemy.y + enemy.height) {
383
+
384
+ enemy.alive = false;
385
+ bullets.splice(bulletIndex, 1);
386
+ score += 100;
387
+ document.getElementById('score').textContent = score;
388
+ }
389
+ });
390
+ });
391
+
392
+ // Enemy-player collisions
393
+ enemies.forEach(enemy => {
394
+ if (enemy.alive &&
395
+ enemy.y + enemy.height >= player.y &&
396
+ enemy.x < player.x + player.width &&
397
+ enemy.x + enemy.width > player.x) {
398
+
399
+ lives--;
400
+ document.getElementById('lives').textContent = lives;
401
+ enemy.alive = false;
402
+
403
+ if (lives <= 0) {
404
+ gameOver();
405
+ }
406
+ }
407
+ });
408
+ }
409
+
410
+ // Draw everything
411
+ function draw() {
412
+ // Clear canvas
413
+ ctx.fillStyle = 'rgba(10, 10, 30, 0.3)';
414
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
415
+
416
+ drawPlayer();
417
+ drawBullets();
418
+ drawEnemies();
419
+ }
420
+
421
+ // Game loop
422
+ function gameLoop() {
423
+ if (gameRunning) {
424
+ update();
425
+ draw();
426
+ requestAnimationFrame(gameLoop);
427
+ }
428
+ }
429
+
430
+ // Start game
431
+ function startGame() {
432
+ if (!gameRunning) {
433
+ gameRunning = true;
434
+ gameLoop();
435
+ }
436
+ }
437
+
438
+ // Pause game
439
+ function pauseGame() {
440
+ gameRunning = !gameRunning;
441
+ if (gameRunning) {
442
+ gameLoop();
443
+ }
444
+ }
445
+
446
+ // Reset game
447
+ function resetGame() {
448
+ gameRunning = false;
449
+ score = 0;
450
+ lives = 3;
451
+ level = 1;
452
+ bullets.length = 0;
453
+ document.getElementById('score').textContent = score;
454
+ document.getElementById('lives').textContent = lives;
455
+ document.getElementById('level').textContent = level;
456
+ initEnemies();
457
+ player.x = canvas.width / 2 - 25;
458
+ player.y = canvas.height - 50;
459
+ }
460
+
461
+ // Game over
462
+ function gameOver() {
463
+ gameRunning = false;
464
+ ctx.fillStyle = 'rgba(0, 0, 0, 0.8)';
465
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
466
+
467
+ ctx.fillStyle = '#ff00cc';
468
+ ctx.font = '48px "Press Start 2P"';
469
+ ctx.textAlign = 'center';
470
+ ctx.fillText('GAME OVER', canvas.width / 2, canvas.height / 2);
471
+ ctx.font = '24px "Press Start 2P"';
472
+ ctx.fillText(`FINAL SCORE: ${score}`, canvas.width / 2, canvas.height / 2 + 50);
473
+ }
474
+
475
+ // Shoot bullet
476
+ function shoot() {
477
+ if (gameRunning) {
478
+ bullets.push({
479
+ x: player.x + player.width / 2,
480
+ y: player.y
481
+ });
482
+ }
483
+ }
484
+
485
+ // Mobile controls
486
+ function moveLeft() {
487
+ player.movingLeft = true;
488
+ }
489
+
490
+ function moveRight() {
491
+ player.movingRight = true;
492
+ }
493
+
494
+ // Keyboard controls
495
+ document.addEventListener('keydown', (e) => {
496
+ if (e.key === 'ArrowLeft') player.movingLeft = true;
497
+ if (e.key === 'ArrowRight') player.movingRight = true;
498
+ if (e.key === ' ') shoot();
499
+ });
500
+
501
+ document.addEventListener('keyup', (e) => {
502
+ if (e.key === 'ArrowLeft') player.movingLeft = false;
503
+ if (e.key === 'ArrowRight') player.movingRight = false;
504
+ });
505
+
506
+ // Touch end events for mobile
507
+ document.addEventListener('touchend', () => {
508
+ player.movingLeft = false;
509
+ player.movingRight = false;
510
+ });
511
+
512
+ document.addEventListener('mouseup', () => {
513
+ player.movingLeft = false;
514
+ player.movingRight = false;
515
+ });
516
+
517
+ // Initialize game
518
+ initEnemies();
519
+ feather.replace();
520
+
521
+ // Responsive canvas
522
+ function resizeCanvas() {
523
+ const container = canvas.parentElement;
524
+ const containerWidth = container.clientWidth;
525
+ const containerHeight = container.clientHeight;
526
+
527
+ const scale = Math.min(containerWidth / 800, containerHeight / 700);
528
+
529
+ canvas.style.width = (800 * scale) + 'px';
530
+ canvas.style.height = (600 * scale) + 'px';
531
+ }
532
+
533
+ window.addEventListener('resize', resizeCanvas);
534
+ resizeCanvas();
535
+ </script>
536
+ </body>
537
  </html>