dannyboy84 commited on
Commit
6a073e2
Β·
verified Β·
1 Parent(s): 9a0ea9d

needs to be exactly like the mechanics and graphics and gameplay as wormate.io, save it as wormate.io

Browse files
Files changed (8) hide show
  1. README.md +8 -5
  2. components/game-footer.js +100 -0
  3. components/game-nav.js +96 -0
  4. components/wormate-nav.js +78 -0
  5. index.html +30 -19
  6. script.js +160 -0
  7. style.css +83 -18
  8. wormate.js +242 -0
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Wormate Io Clone
3
- emoji: πŸŒ–
4
- colorFrom: pink
5
- colorTo: green
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: Wormate.io Clone πŸ›
3
+ colorFrom: green
4
+ colorTo: pink
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://huggingface.co/deepsite).
components/game-footer.js ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class GameFooter extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ footer {
7
+ background: linear-gradient(145deg, #166534, #14532d);
8
+ color: white;
9
+ padding: 2rem 1rem;
10
+ margin-top: 3rem;
11
+ }
12
+
13
+ .footer-container {
14
+ max-width: 1200px;
15
+ margin: 0 auto;
16
+ display: grid;
17
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
18
+ gap: 2rem;
19
+ }
20
+
21
+ .footer-section h3 {
22
+ font-size: 1.2rem;
23
+ margin-bottom: 1rem;
24
+ display: flex;
25
+ align-items: center;
26
+ }
27
+
28
+ .footer-section h3 i {
29
+ margin-right: 0.5rem;
30
+ }
31
+
32
+ .footer-section p {
33
+ margin-bottom: 0.5rem;
34
+ opacity: 0.8;
35
+ }
36
+
37
+ .social-links {
38
+ display: flex;
39
+ gap: 1rem;
40
+ margin-top: 1rem;
41
+ }
42
+
43
+ .social-link {
44
+ color: white;
45
+ transition: all 0.3s;
46
+ }
47
+
48
+ .social-link:hover {
49
+ transform: translateY(-3px);
50
+ }
51
+
52
+ .copyright {
53
+ text-align: center;
54
+ margin-top: 2rem;
55
+ padding-top: 1rem;
56
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
57
+ opacity: 0.7;
58
+ }
59
+
60
+ @media (max-width: 640px) {
61
+ .footer-container {
62
+ grid-template-columns: 1fr;
63
+ }
64
+ }
65
+ </style>
66
+
67
+ <footer>
68
+ <div class="footer-container">
69
+ <div class="footer-section">
70
+ <h3><i data-feather="info"></i> About</h3>
71
+ <p>Wiggly Worm Warriors is a fun game for kids of all ages. Grow your worm by eating colorful dots!</p>
72
+ </div>
73
+
74
+ <div class="footer-section">
75
+ <h3><i data-feather="help-circle"></i> Help</h3>
76
+ <p>Use arrow keys to move</p>
77
+ <p>Eat dots to grow longer</p>
78
+ <p>Avoid walls and yourself</p>
79
+ </div>
80
+
81
+ <div class="footer-section">
82
+ <h3><i data-feather="heart"></i> Made For</h3>
83
+ <p>Special edition for 8-year-old worm lovers!</p>
84
+ <div class="social-links">
85
+ <a href="#"><i data-feather="facebook"></i></a>
86
+ <a href="#"><i data-feather="twitter"></i></a>
87
+ <a href="#"><i data-feather="youtube"></i></a>
88
+ </div>
89
+ </div>
90
+ </div>
91
+
92
+ <div class="copyright">
93
+ &copy; ${new Date().getFullYear()} Wiggly Worm Warriors - All rights reserved
94
+ </div>
95
+ </footer>
96
+ `;
97
+ }
98
+ }
99
+
100
+ customElements.define('game-footer', GameFooter);
components/game-nav.js ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class GameNav extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ nav {
7
+ background: linear-gradient(145deg, #22c55e, #16a34a);
8
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
9
+ }
10
+
11
+ .nav-container {
12
+ display: flex;
13
+ justify-content: space-between;
14
+ align-items: center;
15
+ padding: 1rem 2rem;
16
+ max-width: 1200px;
17
+ margin: 0 auto;
18
+ }
19
+
20
+ .logo {
21
+ display: flex;
22
+ align-items: center;
23
+ font-weight: bold;
24
+ font-size: 1.5rem;
25
+ color: white;
26
+ text-decoration: none;
27
+ }
28
+
29
+ .logo-icon {
30
+ margin-right: 0.5rem;
31
+ }
32
+
33
+ .nav-links {
34
+ display: flex;
35
+ gap: 1.5rem;
36
+ }
37
+
38
+ .nav-link {
39
+ color: white;
40
+ text-decoration: none;
41
+ font-weight: 600;
42
+ transition: all 0.3s;
43
+ display: flex;
44
+ align-items: center;
45
+ }
46
+
47
+ .nav-link:hover {
48
+ transform: translateY(-2px);
49
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
50
+ }
51
+
52
+ .nav-link-icon {
53
+ margin-right: 0.3rem;
54
+ }
55
+
56
+ @media (max-width: 640px) {
57
+ .nav-container {
58
+ flex-direction: column;
59
+ padding: 1rem;
60
+ }
61
+
62
+ .nav-links {
63
+ margin-top: 1rem;
64
+ gap: 1rem;
65
+ }
66
+ }
67
+ </style>
68
+
69
+ <nav>
70
+ <div class="nav-container">
71
+ <a href="#" class="logo">
72
+ <i data-feather="wind" class="logo-icon"></i>
73
+ Wiggly Worms
74
+ </a>
75
+
76
+ <div class="nav-links">
77
+ <a href="#" class="nav-link">
78
+ <i data-feather="home" class="nav-link-icon"></i>
79
+ Home
80
+ </a>
81
+ <a href="#" class="nav-link">
82
+ <i data-feather="award" class="nav-link-icon"></i>
83
+ Scores
84
+ </a>
85
+ <a href="#" class="nav-link">
86
+ <i data-feather="settings" class="nav-link-icon"></i>
87
+ Settings
88
+ </a>
89
+ </div>
90
+ </div>
91
+ </nav>
92
+ `;
93
+ }
94
+ }
95
+
96
+ customElements.define('game-nav', GameNav);
components/wormate-nav.js ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class WormateNav extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ nav {
7
+ background: #1a1a2e;
8
+ color: white;
9
+ padding: 1rem;
10
+ position: fixed;
11
+ top: 0;
12
+ left: 0;
13
+ right: 0;
14
+ z-index: 100;
15
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
16
+ }
17
+
18
+ .nav-container {
19
+ display: flex;
20
+ justify-content: space-between;
21
+ align-items: center;
22
+ max-width: 1200px;
23
+ margin: 0 auto;
24
+ }
25
+
26
+ .logo {
27
+ font-family: 'Press Start 2P', cursive;
28
+ font-size: 1.2rem;
29
+ color: #ff6b6b;
30
+ text-decoration: none;
31
+ }
32
+
33
+ .nav-links {
34
+ display: flex;
35
+ gap: 1.5rem;
36
+ }
37
+
38
+ .nav-link {
39
+ color: white;
40
+ text-decoration: none;
41
+ font-family: 'Press Start 2P', cursive;
42
+ font-size: 0.8rem;
43
+ transition: all 0.3s;
44
+ }
45
+
46
+ .nav-link:hover {
47
+ color: #ff6b6b;
48
+ }
49
+
50
+ @media (max-width: 768px) {
51
+ .nav-container {
52
+ flex-direction: column;
53
+ gap: 1rem;
54
+ }
55
+
56
+ .nav-links {
57
+ gap: 1rem;
58
+ }
59
+ }
60
+ </style>
61
+
62
+ <nav>
63
+ <div class="nav-container">
64
+ <a href="#" class="logo">WORMATE.IO</a>
65
+
66
+ <div class="nav-links">
67
+ <a href="#" class="nav-link">HOME</a>
68
+ <a href="#" class="nav-link">PLAY</a>
69
+ <a href="#" class="nav-link">SKINS</a>
70
+ <a href="#" class="nav-link">LEADERBOARD</a>
71
+ </div>
72
+ </div>
73
+ </nav>
74
+ `;
75
+ }
76
+ }
77
+
78
+ customElements.define('wormate-nav', WormateNav);
index.html CHANGED
@@ -1,19 +1,30 @@
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
+
2
+ <!DOCTYPE html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Wormate.io Clone</title>
8
+ <link rel="stylesheet" href="style.css">
9
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.7.2/socket.io.js"></script>
10
+ <script src="components/wormate-nav.js"></script>
11
+ <style>
12
+ @import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');
13
+ </style>
14
+ </head>
15
+ <body>
16
+ <wormate-nav></wormate-nav>
17
+
18
+ <div id="game-container">
19
+ <canvas id="gameCanvas"></canvas>
20
+ <div id="game-ui">
21
+ <div id="score-display">Score: 0</div>
22
+ <div id="leaderboard"></div>
23
+ <button id="play-btn" class="wormate-btn">PLAY</button>
24
+ </div>
25
+ </div>
26
+
27
+ <script src="wormate.js"></script>
28
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
29
+ </body>
30
+ </html>
script.js ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ document.addEventListener('DOMContentLoaded', () => {
2
+ const canvas = document.getElementById('gameCanvas');
3
+ const ctx = canvas.getContext('2d');
4
+
5
+ // Set canvas size
6
+ canvas.width = canvas.parentElement.clientWidth;
7
+ canvas.height = canvas.parentElement.clientHeight;
8
+
9
+ // Game variables
10
+ const gridSize = 20;
11
+ const tileCount = canvas.width / gridSize;
12
+ let speed = 7;
13
+ let score = 0;
14
+
15
+ // Worm
16
+ let worm = [];
17
+ worm[0] = {x: Math.floor(tileCount/2) * gridSize, y: Math.floor(tileCount/2) * gridSize};
18
+
19
+ // Food
20
+ let food = {
21
+ x: Math.floor(Math.random() * tileCount) * gridSize,
22
+ y: Math.floor(Math.random() * tileCount) * gridSize,
23
+ color: getRandomColor()
24
+ };
25
+
26
+ // Direction
27
+ let xVelocity = 0;
28
+ let yVelocity = 0;
29
+
30
+ // Game loop
31
+ function gameLoop() {
32
+ // Clear canvas
33
+ ctx.fillStyle = '#f0fdf4';
34
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
35
+
36
+ // Move worm
37
+ let head = {x: worm[0].x + xVelocity, y: worm[0].y + yVelocity};
38
+ worm.unshift(head);
39
+
40
+ // Check if worm eats food
41
+ if(head.x === food.x && head.y === food.y) {
42
+ score++;
43
+ food = {
44
+ x: Math.floor(Math.random() * tileCount) * gridSize,
45
+ y: Math.floor(Math.random() * tileCount) * gridSize,
46
+ color: getRandomColor()
47
+ };
48
+ } else {
49
+ worm.pop();
50
+ }
51
+
52
+ // Draw worm
53
+ for(let i = 0; i < worm.length; i++) {
54
+ ctx.fillStyle = i === 0 ? '#22c55e' : '#4ade80';
55
+ ctx.beginPath();
56
+ ctx.arc(worm[i].x + gridSize/2, worm[i].y + gridSize/2, gridSize/2, 0, Math.PI*2);
57
+ ctx.fill();
58
+
59
+ // Add eyes to head
60
+ if(i === 0) {
61
+ ctx.fillStyle = 'white';
62
+ ctx.beginPath();
63
+ ctx.arc(worm[i].x + gridSize/3, worm[i].y + gridSize/3, gridSize/8, 0, Math.PI*2);
64
+ ctx.arc(worm[i].x + 2*gridSize/3, worm[i].y + gridSize/3, gridSize/8, 0, Math.PI*2);
65
+ ctx.fill();
66
+
67
+ ctx.fillStyle = 'black';
68
+ ctx.beginPath();
69
+ ctx.arc(worm[i].x + gridSize/3, worm[i].y + gridSize/3, gridSize/12, 0, Math.PI*2);
70
+ ctx.arc(worm[i].x + 2*gridSize/3, worm[i].y + gridSize/3, gridSize/12, 0, Math.PI*2);
71
+ ctx.fill();
72
+ }
73
+ }
74
+
75
+ // Draw food
76
+ ctx.fillStyle = food.color;
77
+ ctx.beginPath();
78
+ ctx.arc(food.x + gridSize/2, food.y + gridSize/2, gridSize/2, 0, Math.PI*2);
79
+ ctx.fill();
80
+
81
+ // Check collision with walls
82
+ if(head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height) {
83
+ gameOver();
84
+ }
85
+
86
+ // Check collision with self
87
+ for(let i = 1; i < worm.length; i++) {
88
+ if(head.x === worm[i].x && head.y === worm[i].y) {
89
+ gameOver();
90
+ }
91
+ }
92
+ }
93
+
94
+ // Game controls
95
+ document.addEventListener('keydown', (e) => {
96
+ // Prevent reverse direction
97
+ switch(e.key) {
98
+ case 'ArrowUp':
99
+ if(yVelocity === 0) {
100
+ xVelocity = 0;
101
+ yVelocity = -gridSize;
102
+ }
103
+ break;
104
+ case 'ArrowDown':
105
+ if(yVelocity === 0) {
106
+ xVelocity = 0;
107
+ yVelocity = gridSize;
108
+ }
109
+ break;
110
+ case 'ArrowLeft':
111
+ if(xVelocity === 0) {
112
+ xVelocity = -gridSize;
113
+ yVelocity = 0;
114
+ }
115
+ break;
116
+ case 'ArrowRight':
117
+ if(xVelocity === 0) {
118
+ xVelocity = gridSize;
119
+ yVelocity = 0;
120
+ }
121
+ break;
122
+ }
123
+ });
124
+
125
+ // Game over function
126
+ function gameOver() {
127
+ clearInterval(gameInterval);
128
+
129
+ // Show game over screen
130
+ const gameOverDiv = document.createElement('div');
131
+ gameOverDiv.className = 'game-over';
132
+ gameOverDiv.innerHTML = `
133
+ <h2 class="text-4xl font-bold text-white mb-4">Game Over!</h2>
134
+ <p class="text-2xl text-white mb-6">Your score: ${score}</p>
135
+ <button onclick="location.reload()" class="game-button text-xl">
136
+ Play Again <i data-feather="refresh-cw" class="ml-2"></i>
137
+ </button>
138
+ `;
139
+ canvas.parentElement.appendChild(gameOverDiv);
140
+ feather.replace();
141
+ }
142
+
143
+ // Random color generator for food
144
+ function getRandomColor() {
145
+ const colors = [
146
+ '#ef4444', '#f97316', '#f59e0b', '#10b981',
147
+ '#3b82f6', '#6366f1', '#8b5cf6', '#ec4899'
148
+ ];
149
+ return colors[Math.floor(Math.random() * colors.length)];
150
+ }
151
+
152
+ // Start game
153
+ let gameInterval = setInterval(gameLoop, 1000/speed);
154
+
155
+ // Responsive canvas
156
+ window.addEventListener('resize', () => {
157
+ canvas.width = canvas.parentElement.clientWidth;
158
+ canvas.height = canvas.parentElement.clientHeight;
159
+ });
160
+ });
style.css CHANGED
@@ -1,28 +1,93 @@
1
  body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
 
 
 
 
4
  }
5
 
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
 
9
  }
10
 
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
  }
17
 
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
  }
25
 
26
- .card p:last-child {
27
- margin-bottom: 0;
 
 
 
28
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  body {
2
+ margin: 0;
3
+ padding: 0;
4
+ overflow: hidden;
5
+ font-family: 'Press Start 2P', cursive;
6
+ background-color: #0f0f1a;
7
+ color: white;
8
  }
9
 
10
+ #game-container {
11
+ position: relative;
12
+ width: 100vw;
13
+ height: 100vh;
14
  }
15
 
16
+ #gameCanvas {
17
+ display: block;
18
+ width: 100%;
19
+ height: 100%;
 
20
  }
21
 
22
+ #game-ui {
23
+ position: absolute;
24
+ top: 0;
25
+ left: 0;
26
+ padding: 1rem;
27
+ pointer-events: none;
28
  }
29
 
30
+ #score-display {
31
+ font-size: 1.2rem;
32
+ margin-bottom: 1rem;
33
+ color: #ff6b6b;
34
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
35
  }
36
+
37
+ #leaderboard {
38
+ background: rgba(26, 26, 46, 0.8);
39
+ padding: 1rem;
40
+ border-radius: 5px;
41
+ max-width: 200px;
42
+ }
43
+
44
+ #leaderboard h3 {
45
+ margin: 0 0 0.5rem 0;
46
+ font-size: 0.8rem;
47
+ color: #ff6b6b;
48
+ }
49
+
50
+ .player-row {
51
+ display: flex;
52
+ justify-content: space-between;
53
+ margin-bottom: 0.3rem;
54
+ font-size: 0.7rem;
55
+ }
56
+
57
+ .player-row.you {
58
+ color: #69f0ae;
59
+ }
60
+
61
+ .wormate-btn {
62
+ position: absolute;
63
+ top: 50%;
64
+ left: 50%;
65
+ transform: translate(-50%, -50%);
66
+ padding: 1rem 2rem;
67
+ font-family: 'Press Start 2P', cursive;
68
+ font-size: 1rem;
69
+ background: #ff6b6b;
70
+ color: white;
71
+ border: none;
72
+ border-radius: 5px;
73
+ cursor: pointer;
74
+ pointer-events: auto;
75
+ transition: all 0.3s;
76
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
77
+ }
78
+
79
+ .wormate-btn:hover {
80
+ background: #ff5252;
81
+ transform: translate(-50%, -50%) scale(1.05);
82
+ }
83
+
84
+ /* Animations */
85
+ @keyframes pulse {
86
+ 0% { transform: scale(1); }
87
+ 50% { transform: scale(1.1); }
88
+ 100% { transform: scale(1); }
89
+ }
90
+
91
+ .pulse {
92
+ animation: pulse 1s infinite;
93
+ }
wormate.js ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Wormate.io clone game logic
2
+ const socket = io('https://wormate.io'); // Connect to wormate.io server
3
+
4
+ const canvas = document.getElementById('gameCanvas');
5
+ const ctx = canvas.getContext('2d');
6
+ const scoreDisplay = document.getElementById('score-display');
7
+ const leaderboard = document.getElementById('leaderboard');
8
+ const playBtn = document.getElementById('play-btn');
9
+
10
+ // Set canvas to full window size
11
+ function resizeCanvas() {
12
+ canvas.width = window.innerWidth;
13
+ canvas.height = window.innerHeight;
14
+ }
15
+ window.addEventListener('resize', resizeCanvas);
16
+ resizeCanvas();
17
+
18
+ // Game state
19
+ let gameStarted = false;
20
+ let playerId = null;
21
+ let players = {};
22
+ let foods = [];
23
+ let powerUps = [];
24
+ let score = 0;
25
+
26
+ // Player controls
27
+ const keys = {
28
+ ArrowUp: false,
29
+ ArrowDown: false,
30
+ ArrowLeft: false,
31
+ ArrowRight: false
32
+ };
33
+
34
+ // Handle keyboard input
35
+ window.addEventListener('keydown', (e) => {
36
+ if (keys.hasOwnProperty(e.key)) {
37
+ keys[e.key] = true;
38
+ e.preventDefault();
39
+ }
40
+ });
41
+
42
+ window.addEventListener('keyup', (e) => {
43
+ if (keys.hasOwnProperty(e.key)) {
44
+ keys[e.key] = false;
45
+ e.preventDefault();
46
+ }
47
+ });
48
+
49
+ // Socket event handlers
50
+ socket.on('connect', () => {
51
+ playerId = socket.id;
52
+ console.log('Connected to server with ID:', playerId);
53
+ });
54
+
55
+ socket.on('gameState', (gameState) => {
56
+ players = gameState.players;
57
+ foods = gameState.foods;
58
+ powerUps = gameState.powerUps;
59
+
60
+ if (players[playerId]) {
61
+ score = players[playerId].score;
62
+ scoreDisplay.textContent = `Score: ${score}`;
63
+ }
64
+
65
+ updateLeaderboard();
66
+ renderGame();
67
+ });
68
+
69
+ socket.on('playerDied', (data) => {
70
+ if (data.playerId === playerId) {
71
+ gameStarted = false;
72
+ playBtn.style.display = 'block';
73
+ alert(`Game Over! Your score: ${score}`);
74
+ }
75
+ });
76
+
77
+ // Game loop
78
+ function gameLoop() {
79
+ if (gameStarted) {
80
+ const direction = getDirection();
81
+ socket.emit('playerInput', direction);
82
+ }
83
+ requestAnimationFrame(gameLoop);
84
+ }
85
+ gameLoop();
86
+
87
+ // Helper functions
88
+ function getDirection() {
89
+ if (keys.ArrowUp) return 'up';
90
+ if (keys.ArrowDown) return 'down';
91
+ if (keys.ArrowLeft) return 'left';
92
+ if (keys.ArrowRight) return 'right';
93
+ return null;
94
+ }
95
+
96
+ function updateLeaderboard() {
97
+ const sortedPlayers = Object.values(players).sort((a, b) => b.score - a.score);
98
+ leaderboard.innerHTML = '<h3>Leaderboard</h3>' +
99
+ sortedPlayers.map(p =>
100
+ `<div class="player-row ${p.id === playerId ? 'you' : ''}">
101
+ <span class="player-name">${p.name}</span>
102
+ <span class="player-score">${p.score}</span>
103
+ </div>`
104
+ ).join('');
105
+ }
106
+
107
+ function renderGame() {
108
+ // Clear canvas
109
+ ctx.fillStyle = '#1a1a2e';
110
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
111
+
112
+ // Draw foods
113
+ foods.forEach(food => {
114
+ ctx.fillStyle = food.color;
115
+ ctx.beginPath();
116
+ ctx.arc(food.x, food.y, food.radius, 0, Math.PI * 2);
117
+ ctx.fill();
118
+ });
119
+
120
+ // Draw power-ups
121
+ powerUps.forEach(powerUp => {
122
+ ctx.save();
123
+ ctx.translate(powerUp.x, powerUp.y);
124
+ ctx.rotate(Date.now() / 200);
125
+ ctx.fillStyle = powerUp.color;
126
+ ctx.fillRect(-powerUp.size/2, -powerUp.size/2, powerUp.size, powerUp.size);
127
+ ctx.restore();
128
+ });
129
+
130
+ // Draw players
131
+ Object.values(players).forEach(player => {
132
+ // Draw worm segments
133
+ player.segments.forEach((segment, i) => {
134
+ const gradient = ctx.createRadialGradient(
135
+ segment.x, segment.y, 0,
136
+ segment.x, segment.y, segment.radius
137
+ );
138
+ gradient.addColorStop(0, player.color);
139
+ gradient.addColorStop(1, darkenColor(player.color, 0.3));
140
+
141
+ ctx.fillStyle = gradient;
142
+ ctx.beginPath();
143
+ ctx.arc(segment.x, segment.y, segment.radius, 0, Math.PI * 2);
144
+ ctx.fill();
145
+
146
+ // Draw eyes on head
147
+ if (i === 0) {
148
+ const angle = Math.atan2(
149
+ player.segments[1].y - segment.y,
150
+ player.segments[1].x - segment.x
151
+ );
152
+
153
+ const eyeRadius = segment.radius * 0.3;
154
+ const eyeOffset = segment.radius * 0.6;
155
+
156
+ // Left eye
157
+ ctx.fillStyle = 'white';
158
+ ctx.beginPath();
159
+ ctx.arc(
160
+ segment.x + Math.cos(angle + Math.PI/2) * eyeOffset,
161
+ segment.y + Math.sin(angle + Math.PI/2) * eyeOffset,
162
+ eyeRadius, 0, Math.PI * 2
163
+ );
164
+ ctx.fill();
165
+
166
+ // Right eye
167
+ ctx.beginPath();
168
+ ctx.arc(
169
+ segment.x + Math.cos(angle - Math.PI/2) * eyeOffset,
170
+ segment.y + Math.sin(angle - Math.PI/2) * eyeOffset,
171
+ eyeRadius, 0, Math.PI * 2
172
+ );
173
+ ctx.fill();
174
+
175
+ // Pupils
176
+ ctx.fillStyle = 'black';
177
+ ctx.beginPath();
178
+ ctx.arc(
179
+ segment.x + Math.cos(angle + Math.PI/2) * eyeOffset + Math.cos(angle) * eyeRadius/2,
180
+ segment.y + Math.sin(angle + Math.PI/2) * eyeOffset + Math.sin(angle) * eyeRadius/2,
181
+ eyeRadius/2, 0, Math.PI * 2
182
+ );
183
+ ctx.fill();
184
+
185
+ ctx.beginPath();
186
+ ctx.arc(
187
+ segment.x + Math.cos(angle - Math.PI/2) * eyeOffset + Math.cos(angle) * eyeRadius/2,
188
+ segment.y + Math.sin(angle - Math.PI/2) * eyeOffset + Math.sin(angle) * eyeRadius/2,
189
+ eyeRadius/2, 0, Math.PI * 2
190
+ );
191
+ ctx.fill();
192
+ }
193
+ });
194
+
195
+ // Draw player name
196
+ if (player.segments.length > 0) {
197
+ const head = player.segments[0];
198
+ ctx.fillStyle = 'white';
199
+ ctx.font = '12px "Press Start 2P", cursive';
200
+ ctx.textAlign = 'center';
201
+ ctx.fillText(player.name, head.x, head.y - head.radius - 10);
202
+ }
203
+ });
204
+ }
205
+
206
+ function darkenColor(color, amount) {
207
+ // Convert hex to RGB
208
+ let r = parseInt(color.substr(1, 2), 16);
209
+ let g = parseInt(color.substr(3, 2), 16);
210
+ let b = parseInt(color.substr(5, 2), 16);
211
+
212
+ // Darken each component
213
+ r = Math.max(0, Math.floor(r * (1 - amount)));
214
+ g = Math.max(0, Math.floor(g * (1 - amount)));
215
+ b = Math.max(0, Math.floor(b * (1 - amount)));
216
+
217
+ // Convert back to hex
218
+ return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`;
219
+ }
220
+
221
+ // Start game
222
+ playBtn.addEventListener('click', () => {
223
+ const playerName = prompt('Enter your name:', 'Player' + Math.floor(Math.random() * 1000));
224
+ if (playerName) {
225
+ socket.emit('joinGame', {
226
+ name: playerName,
227
+ color: getRandomColor()
228
+ });
229
+ gameStarted = true;
230
+ playBtn.style.display = 'none';
231
+ }
232
+ });
233
+
234
+ function getRandomColor() {
235
+ const colors = [
236
+ '#FF5252', '#FF4081', '#E040FB', '#7C4DFF',
237
+ '#536DFE', '#448AFF', '#40C4FF', '#18FFFF',
238
+ '#64FFDA', '#69F0AE', '#B2FF59', '#EEFF41',
239
+ '#FFFF00', '#FFD740', '#FFAB40', '#FF6E40'
240
+ ];
241
+ return colors[Math.floor(Math.random() * colors.length)];
242
+ }