awacke1 commited on
Commit
1574a0c
·
verified ·
1 Parent(s): fd5acb3

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +267 -173
index.html CHANGED
@@ -1,186 +1,280 @@
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>3D Drawing Game (Multiplayer)</title>
7
- <style>
8
- body {
9
- margin: 0;
10
- padding: 0;
11
- display: flex;
12
- flex-direction: column;
13
- justify-content: center;
14
- align-items: center;
15
- height: 100vh;
16
- background-color: #f0f0f0;
17
- font-family: Arial, sans-serif;
18
- }
19
- #gameContainer {
20
- width: 800px;
21
- height: 600px;
22
- border: 2px solid #333;
23
- background-color: #fff;
24
- }
25
- #controls {
26
- margin-top: 10px;
27
- }
28
- button {
29
- margin: 0 5px;
30
- padding: 5px 10px;
31
- }
32
- </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  </head>
34
  <body>
35
- <div id="gameContainer">
36
- <svg id="gameSvg" width="800" height="600"></svg>
37
- </div>
38
- <div id="controls">
39
- <button id="clearBtn">Clear Canvas</button>
40
- <input type="color" id="colorPicker" value="#000000">
41
- </div>
42
-
43
- <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.4.1/socket.io.min.js"></script>
44
- <script>
45
- const socket = io('http://localhost:3000');
46
- const svg = document.getElementById('gameSvg');
47
- const clearBtn = document.getElementById('clearBtn');
48
- const colorPicker = document.getElementById('colorPicker');
49
- let isDrawing = false;
50
- let currentLine = null;
51
- let lines = [];
52
- let rotationX = 0;
53
- let rotationY = 0;
54
- let currentColor = '#000000';
55
 
56
- function project3Dto2D(x, y, z) {
57
- const focalLength = 400;
58
- const scale = focalLength / (focalLength + z);
59
- return {
60
- x: x * scale + 400,
61
- y: y * scale + 300
62
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  }
64
-
65
- function rotatePoint(x, y, z) {
66
- const cosX = Math.cos(rotationX);
67
- const sinX = Math.sin(rotationX);
68
- const cosY = Math.cos(rotationY);
69
- const sinY = Math.sin(rotationY);
70
-
71
- const rotatedY = y * cosX - z * sinX;
72
- const rotatedZ = y * sinX + z * cosX;
73
- const rotatedX = x * cosY + rotatedZ * sinY;
74
-
75
- return { x: rotatedX, y: rotatedY, z: -x * sinY + rotatedZ * cosY };
 
 
 
 
76
  }
77
-
78
- function startDrawing(e) {
79
- isDrawing = true;
80
- const { clientX, clientY } = e;
81
- const start = project3Dto2D(clientX - 400, clientY - 300, 0);
82
- currentLine = { points: [{ x: clientX - 400, y: clientY - 300, z: 0 }], color: currentColor };
83
- const lineElement = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');
84
- lineElement.setAttribute('points', `${start.x},${start.y}`);
85
- lineElement.setAttribute('fill', 'none');
86
- lineElement.setAttribute('stroke', currentColor);
87
- lineElement.setAttribute('stroke-width', '2');
88
- svg.appendChild(lineElement);
89
- currentLine.element = lineElement;
90
-
91
- socket.emit('startLine', { x: clientX - 400, y: clientY - 300, z: 0, color: currentColor });
92
- }
93
-
94
- function draw(e) {
95
- if (!isDrawing) return;
96
- const { clientX, clientY } = e;
97
- const point = { x: clientX - 400, y: clientY - 300, z: 0 };
98
- currentLine.points.push(point);
99
- const projected = project3Dto2D(point.x, point.y, point.z);
100
- const points = currentLine.element.getAttribute('points');
101
- currentLine.element.setAttribute('points', `${points} ${projected.x},${projected.y}`);
102
-
103
- socket.emit('drawLine', { x: clientX - 400, y: clientY - 300, z: 0 });
104
  }
105
-
106
- function stopDrawing() {
107
- if (!isDrawing) return;
108
- isDrawing = false;
109
- lines.push(currentLine);
110
- currentLine = null;
111
-
112
- socket.emit('endLine');
113
  }
114
-
115
- function updateRotation(e) {
116
- rotationY -= e.movementX * 0.01;
117
- rotationX -= e.movementY * 0.01;
118
- redrawLines();
119
-
120
- socket.emit('updateRotation', { rotationX, rotationY });
121
- }
122
-
123
- function redrawLines() {
124
- lines.forEach(line => {
125
- const projectedPoints = line.points.map(point => {
126
- const rotated = rotatePoint(point.x, point.y, point.z);
127
- return project3Dto2D(rotated.x, rotated.y, rotated.z);
128
- });
129
- const pointsString = projectedPoints.map(p => `${p.x},${p.y}`).join(' ');
130
- line.element.setAttribute('points', pointsString);
131
- });
132
- }
133
-
134
- function clearCanvas() {
135
- lines.forEach(line => svg.removeChild(line.element));
136
- lines = [];
137
- socket.emit('clearCanvas');
138
- }
139
-
140
- svg.addEventListener('mousedown', startDrawing);
141
- svg.addEventListener('mousemove', (e) => {
142
- if (e.buttons === 1) {
143
- draw(e);
144
- } else if (e.buttons === 2) {
145
- updateRotation(e);
146
- }
147
- });
148
- svg.addEventListener('mouseup', stopDrawing);
149
- svg.addEventListener('mouseleave', stopDrawing);
150
- svg.addEventListener('contextmenu', (e) => e.preventDefault());
151
-
152
- clearBtn.addEventListener('click', clearCanvas);
153
- colorPicker.addEventListener('change', (e) => {
154
- currentColor = e.target.value;
155
  });
156
-
157
- // Socket.io event listeners
158
- socket.on('startLine', (data) => {
159
- const start = project3Dto2D(data.x, data.y, data.z);
160
- const lineElement = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');
161
- lineElement.setAttribute('points', `${start.x},${start.y}`);
162
- lineElement.setAttribute('fill', 'none');
163
- lineElement.setAttribute('stroke', data.color);
164
- lineElement.setAttribute('stroke-width', '2');
165
- svg.appendChild(lineElement);
166
- lines.push({ points: [data], element: lineElement, color: data.color });
167
- });
168
-
169
- socket.on('drawLine', (data) => {
170
- const line = lines[lines.length - 1];
171
- line.points.push(data);
172
- const projected = project3Dto2D(data.x, data.y, data.z);
173
- const points = line.element.getAttribute('points');
174
- line.element.setAttribute('points', `${points} ${projected.x},${projected.y}`);
175
- });
176
-
177
- socket.on('updateRotation', (data) => {
178
- rotationX = data.rotationX;
179
- rotationY = data.rotationY;
180
- redrawLines();
181
  });
182
-
183
- socket.on('clearCanvas', clearCanvas);
184
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  </body>
186
  </html>
 
1
  <!DOCTYPE html>
2
+ <html>
3
  <head>
4
+ <style>
5
+ body { margin: 0; display: flex; justify-content: center; align-items: center; height: 100vh; background: #1a1a1a; }
6
+ .controls { position: fixed; top: 10px; left: 10px; color: white; }
7
+ button { margin: 5px; padding: 5px 10px; }
8
+ #gameArea { cursor: crosshair; }
9
+ .info-panel {
10
+ position: fixed;
11
+ top: 10px;
12
+ right: 10px;
13
+ color: white;
14
+ background: rgba(0,0,0,0.7);
15
+ padding: 15px;
16
+ border-radius: 5px;
17
+ font-family: Arial, sans-serif;
18
+ }
19
+ .score {
20
+ font-size: 24px;
21
+ font-weight: bold;
22
+ margin-bottom: 10px;
23
+ }
24
+ .points-popup {
25
+ position: absolute;
26
+ color: #4CAF50;
27
+ font-weight: bold;
28
+ font-family: Arial, sans-serif;
29
+ pointer-events: none;
30
+ animation: floatUp 1s ease-out forwards;
31
+ }
32
+ @keyframes floatUp {
33
+ 0% { transform: translateY(0); opacity: 1; }
34
+ 100% { transform: translateY(-50px); opacity: 0; }
35
+ }
36
+ .drawing-guide {
37
+ position: fixed;
38
+ bottom: 10px;
39
+ left: 10px;
40
+ color: white;
41
+ background: rgba(0,0,0,0.7);
42
+ padding: 10px;
43
+ border-radius: 5px;
44
+ }
45
+ </style>
46
  </head>
47
  <body>
48
+ <div class="controls">
49
+ <button onclick="addRobot()">Add Random Robot (+5 pts)</button>
50
+ <button onclick="togglePause()">Pause/Play</button>
51
+ </div>
52
+ <div class="info-panel">
53
+ <div class="score">Score: <span id="scoreDisplay">0</span></div>
54
+ <div>Robots: <span id="robotCount">0</span></div>
55
+ </div>
56
+ <div class="drawing-guide">
57
+ Click and drag to draw new robots (+5 pts). Collisions give +5 pts and growth!
58
+ </div>
59
+ <svg id="gameArea" width="800" height="600" style="background: #000;">
60
+ <rect width="800" height="600" fill="none" stroke="#333" stroke-width="4"/>
61
+ <line id="drawingLine" stroke="white" stroke-width="2" stroke-dasharray="5,5" visibility="hidden"/>
62
+ </svg>
 
 
 
 
 
63
 
64
+ <script>
65
+ const svg = document.getElementById('gameArea');
66
+ const drawingLine = document.getElementById('drawingLine');
67
+ const robots = [];
68
+ let paused = false;
69
+ let isDrawing = false;
70
+ let startX, startY;
71
+ let score = 0;
72
+
73
+ function updateScore(points, x, y) {
74
+ score += points;
75
+ document.getElementById('scoreDisplay').textContent = score;
76
+ document.getElementById('robotCount').textContent = robots.length;
77
+
78
+ // Create and animate points popup
79
+ const popup = document.createElement('div');
80
+ popup.className = 'points-popup';
81
+ popup.textContent = `+${points}`;
82
+ popup.style.left = `${x}px`;
83
+ popup.style.top = `${y}px`;
84
+ document.body.appendChild(popup);
85
+
86
+ // Remove popup after animation
87
+ setTimeout(() => popup.remove(), 1000);
88
+ }
89
+
90
+ class Robot {
91
+ constructor(x, y, speed, direction, length) {
92
+ this.segments = [];
93
+ this.speed = speed || 2 + Math.random() * 2;
94
+ this.direction = direction || Math.random() * Math.PI * 2;
95
+ this.length = length || 5 + Math.floor(Math.random() * 5);
96
+ this.color = `hsl(${Math.random() * 360}, 80%, 50%)`;
97
+ this.x = x || Math.random() * 700 + 50;
98
+ this.y = y || Math.random() * 500 + 50;
99
+
100
+ this.createSegments();
101
+ }
102
+
103
+ createSegments() {
104
+ // Remove old segments if they exist
105
+ this.segments.forEach(seg => seg.element.remove());
106
+ this.segments = [];
107
+
108
+ // Create new segments
109
+ for (let i = 0; i < this.length; i++) {
110
+ const segment = document.createElementNS("http://www.w3.org/2000/svg", "circle");
111
+ segment.setAttribute("r", "8");
112
+ segment.setAttribute("fill", this.color);
113
+ svg.appendChild(segment);
114
+ this.segments.push({
115
+ element: segment,
116
+ x: this.x,
117
+ y: this.y
118
+ });
119
  }
120
+ }
121
+
122
+ grow() {
123
+ this.length += 1;
124
+ this.createSegments();
125
+ }
126
+
127
+ update() {
128
+ // Update head position
129
+ this.x += Math.cos(this.direction) * this.speed;
130
+ this.y += Math.sin(this.direction) * this.speed;
131
+
132
+ // Bounce off walls
133
+ if (this.x < 10 || this.x > 790) {
134
+ this.direction = Math.PI - this.direction;
135
+ this.mutate();
136
  }
137
+ if (this.y < 10 || this.y > 590) {
138
+ this.direction = -this.direction;
139
+ this.mutate();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  }
141
+
142
+ // Update segments
143
+ for (let i = this.segments.length - 1; i > 0; i--) {
144
+ this.segments[i].x = this.segments[i - 1].x;
145
+ this.segments[i].y = this.segments[i - 1].y;
 
 
 
146
  }
147
+ this.segments[0].x = this.x;
148
+ this.segments[0].y = this.y;
149
+
150
+ // Update SVG elements
151
+ this.segments.forEach(segment => {
152
+ segment.element.setAttribute("cx", segment.x);
153
+ segment.element.setAttribute("cy", segment.y);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
  });
155
+ }
156
+
157
+ mutate() {
158
+ // Random mutation when bouncing
159
+ this.speed = Math.max(1, Math.min(6, this.speed + (Math.random() - 0.5)));
160
+ this.color = `hsl(${Math.random() * 360}, 80%, 50%)`;
161
+ this.segments.forEach(segment => {
162
+ segment.element.setAttribute("fill", this.color);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  });
164
+ }
165
+
166
+ checkCollision(other) {
167
+ const dx = this.x - other.x;
168
+ const dy = this.y - other.y;
169
+ const distance = Math.sqrt(dx * dx + dy * dy);
170
+
171
+ if (distance < 16) {
172
+ // Bounce off each other
173
+ const angle = Math.atan2(dy, dx);
174
+ this.direction = angle + Math.PI / 2;
175
+ other.direction = angle - Math.PI / 2;
176
+
177
+ // Grow and mutate both robots
178
+ this.grow();
179
+ other.grow();
180
+ this.mutate();
181
+ other.mutate();
182
+
183
+ // Add points and show popup at collision location
184
+ const svgRect = svg.getBoundingClientRect();
185
+ const popupX = svgRect.left + this.x;
186
+ const popupY = svgRect.top + this.y;
187
+ updateScore(5, popupX, popupY);
188
+ }
189
+ }
190
+ }
191
+
192
+ // Mouse event handlers
193
+ svg.addEventListener('mousedown', (e) => {
194
+ const rect = svg.getBoundingClientRect();
195
+ startX = e.clientX - rect.left;
196
+ startY = e.clientY - rect.top;
197
+ isDrawing = true;
198
+
199
+ drawingLine.setAttribute('x1', startX);
200
+ drawingLine.setAttribute('y1', startY);
201
+ drawingLine.setAttribute('x2', startX);
202
+ drawingLine.setAttribute('y2', startY);
203
+ drawingLine.setAttribute('visibility', 'visible');
204
+ });
205
+
206
+ svg.addEventListener('mousemove', (e) => {
207
+ if (isDrawing) {
208
+ const rect = svg.getBoundingClientRect();
209
+ const currentX = e.clientX - rect.left;
210
+ const currentY = e.clientY - rect.top;
211
+
212
+ drawingLine.setAttribute('x2', currentX);
213
+ drawingLine.setAttribute('y2', currentY);
214
+ }
215
+ });
216
+
217
+ svg.addEventListener('mouseup', (e) => {
218
+ if (isDrawing) {
219
+ const rect = svg.getBoundingClientRect();
220
+ const endX = e.clientX - rect.left;
221
+ const endY = e.clientY - rect.top;
222
+
223
+ const dx = endX - startX;
224
+ const dy = endY - startY;
225
+ const distance = Math.sqrt(dx * dx + dy * dy);
226
+ const direction = Math.atan2(dy, dx);
227
+
228
+ const speed = Math.min(6, distance / 50);
229
+ const length = Math.max(3, Math.min(12, Math.floor(distance / 30)));
230
+ robots.push(new Robot(startX, startY, speed, direction, length));
231
+
232
+ // Add points for new robot
233
+ updateScore(5, e.clientX, e.clientY);
234
+
235
+ drawingLine.setAttribute('visibility', 'hidden');
236
+ isDrawing = false;
237
+ }
238
+ });
239
+
240
+ svg.addEventListener('mouseleave', () => {
241
+ if (isDrawing) {
242
+ drawingLine.setAttribute('visibility', 'hidden');
243
+ isDrawing = false;
244
+ }
245
+ });
246
+
247
+ function addRobot() {
248
+ const robot = new Robot();
249
+ robots.push(robot);
250
+ // Add points for new random robot
251
+ const svgRect = svg.getBoundingClientRect();
252
+ updateScore(5, svgRect.left + robot.x, svgRect.top + robot.y);
253
+ }
254
+
255
+ function togglePause() {
256
+ paused = !paused;
257
+ }
258
+
259
+ function update() {
260
+ if (!paused) {
261
+ robots.forEach(robot => robot.update());
262
+
263
+ for (let i = 0; i < robots.length; i++) {
264
+ for (let j = i + 1; j < robots.length; j++) {
265
+ robots[i].checkCollision(robots[j]);
266
+ }
267
+ }
268
+ }
269
+ requestAnimationFrame(update);
270
+ }
271
+
272
+ // Start with 3 robots
273
+ for (let i = 0; i < 3; i++) {
274
+ addRobot();
275
+ }
276
+
277
+ update();
278
+ </script>
279
  </body>
280
  </html>