awacke1's picture
Update index.html
fd5acb3 verified
raw
history blame
6.75 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Drawing Game (Multiplayer)</title>
<style>
body {
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f0f0f0;
font-family: Arial, sans-serif;
}
#gameContainer {
width: 800px;
height: 600px;
border: 2px solid #333;
background-color: #fff;
}
#controls {
margin-top: 10px;
}
button {
margin: 0 5px;
padding: 5px 10px;
}
</style>
</head>
<body>
<div id="gameContainer">
<svg id="gameSvg" width="800" height="600"></svg>
</div>
<div id="controls">
<button id="clearBtn">Clear Canvas</button>
<input type="color" id="colorPicker" value="#000000">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.4.1/socket.io.min.js"></script>
<script>
const socket = io('http://localhost:3000');
const svg = document.getElementById('gameSvg');
const clearBtn = document.getElementById('clearBtn');
const colorPicker = document.getElementById('colorPicker');
let isDrawing = false;
let currentLine = null;
let lines = [];
let rotationX = 0;
let rotationY = 0;
let currentColor = '#000000';
function project3Dto2D(x, y, z) {
const focalLength = 400;
const scale = focalLength / (focalLength + z);
return {
x: x * scale + 400,
y: y * scale + 300
};
}
function rotatePoint(x, y, z) {
const cosX = Math.cos(rotationX);
const sinX = Math.sin(rotationX);
const cosY = Math.cos(rotationY);
const sinY = Math.sin(rotationY);
const rotatedY = y * cosX - z * sinX;
const rotatedZ = y * sinX + z * cosX;
const rotatedX = x * cosY + rotatedZ * sinY;
return { x: rotatedX, y: rotatedY, z: -x * sinY + rotatedZ * cosY };
}
function startDrawing(e) {
isDrawing = true;
const { clientX, clientY } = e;
const start = project3Dto2D(clientX - 400, clientY - 300, 0);
currentLine = { points: [{ x: clientX - 400, y: clientY - 300, z: 0 }], color: currentColor };
const lineElement = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');
lineElement.setAttribute('points', `${start.x},${start.y}`);
lineElement.setAttribute('fill', 'none');
lineElement.setAttribute('stroke', currentColor);
lineElement.setAttribute('stroke-width', '2');
svg.appendChild(lineElement);
currentLine.element = lineElement;
socket.emit('startLine', { x: clientX - 400, y: clientY - 300, z: 0, color: currentColor });
}
function draw(e) {
if (!isDrawing) return;
const { clientX, clientY } = e;
const point = { x: clientX - 400, y: clientY - 300, z: 0 };
currentLine.points.push(point);
const projected = project3Dto2D(point.x, point.y, point.z);
const points = currentLine.element.getAttribute('points');
currentLine.element.setAttribute('points', `${points} ${projected.x},${projected.y}`);
socket.emit('drawLine', { x: clientX - 400, y: clientY - 300, z: 0 });
}
function stopDrawing() {
if (!isDrawing) return;
isDrawing = false;
lines.push(currentLine);
currentLine = null;
socket.emit('endLine');
}
function updateRotation(e) {
rotationY -= e.movementX * 0.01;
rotationX -= e.movementY * 0.01;
redrawLines();
socket.emit('updateRotation', { rotationX, rotationY });
}
function redrawLines() {
lines.forEach(line => {
const projectedPoints = line.points.map(point => {
const rotated = rotatePoint(point.x, point.y, point.z);
return project3Dto2D(rotated.x, rotated.y, rotated.z);
});
const pointsString = projectedPoints.map(p => `${p.x},${p.y}`).join(' ');
line.element.setAttribute('points', pointsString);
});
}
function clearCanvas() {
lines.forEach(line => svg.removeChild(line.element));
lines = [];
socket.emit('clearCanvas');
}
svg.addEventListener('mousedown', startDrawing);
svg.addEventListener('mousemove', (e) => {
if (e.buttons === 1) {
draw(e);
} else if (e.buttons === 2) {
updateRotation(e);
}
});
svg.addEventListener('mouseup', stopDrawing);
svg.addEventListener('mouseleave', stopDrawing);
svg.addEventListener('contextmenu', (e) => e.preventDefault());
clearBtn.addEventListener('click', clearCanvas);
colorPicker.addEventListener('change', (e) => {
currentColor = e.target.value;
});
// Socket.io event listeners
socket.on('startLine', (data) => {
const start = project3Dto2D(data.x, data.y, data.z);
const lineElement = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');
lineElement.setAttribute('points', `${start.x},${start.y}`);
lineElement.setAttribute('fill', 'none');
lineElement.setAttribute('stroke', data.color);
lineElement.setAttribute('stroke-width', '2');
svg.appendChild(lineElement);
lines.push({ points: [data], element: lineElement, color: data.color });
});
socket.on('drawLine', (data) => {
const line = lines[lines.length - 1];
line.points.push(data);
const projected = project3Dto2D(data.x, data.y, data.z);
const points = line.element.getAttribute('points');
line.element.setAttribute('points', `${points} ${projected.x},${projected.y}`);
});
socket.on('updateRotation', (data) => {
rotationX = data.rotationX;
rotationY = data.rotationY;
redrawLines();
});
socket.on('clearCanvas', clearCanvas);
</script>
</body>
</html>