Spaces:
Sleeping
Sleeping
Update index.html
Browse files- index.html +30 -62
index.html
CHANGED
@@ -11,12 +11,10 @@
|
|
11 |
</style>
|
12 |
</head>
|
13 |
<body>
|
14 |
-
<div id="info">
|
15 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"></script>
|
16 |
-
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/PointerLockControls.js"></script>
|
17 |
<script>
|
18 |
-
let scene, camera, renderer,
|
19 |
-
let moveForward = false, moveBackward = false, moveLeft = false, moveRight = false;
|
20 |
const username = window.USERNAME || 'Anonymous';
|
21 |
const websocketUrl = window.WEBSOCKET_URL || 'ws://localhost:8765';
|
22 |
const plotWidth = window.PLOT_WIDTH || 50.0;
|
@@ -24,15 +22,21 @@
|
|
24 |
|
25 |
function init() {
|
26 |
scene = new THREE.Scene();
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
renderer = new THREE.WebGLRenderer();
|
29 |
renderer.setSize(window.innerWidth, window.innerHeight);
|
30 |
document.body.appendChild(renderer.domElement);
|
31 |
|
32 |
-
controls = new THREE.PointerLockControls(camera, document.body);
|
33 |
-
scene.add(controls.getObject());
|
34 |
-
camera.position.y = 1.6;
|
35 |
-
|
36 |
const groundGeometry = new THREE.PlaneGeometry(plotWidth, plotDepth);
|
37 |
const groundMaterial = new THREE.MeshBasicMaterial({ color: 0x888888 });
|
38 |
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
|
@@ -42,12 +46,13 @@
|
|
42 |
const gridHelper = new THREE.GridHelper(plotWidth, plotWidth / 2);
|
43 |
scene.add(gridHelper);
|
44 |
|
45 |
-
document.addEventListener('click', () => controls.lock());
|
46 |
-
document.addEventListener('keydown', onKeyDown);
|
47 |
-
document.addEventListener('keyup', onKeyUp);
|
48 |
document.addEventListener('mousedown', onMouseDown);
|
49 |
window.addEventListener('resize', () => {
|
50 |
-
|
|
|
|
|
|
|
|
|
51 |
camera.updateProjectionMatrix();
|
52 |
renderer.setSize(window.innerWidth, window.innerHeight);
|
53 |
});
|
@@ -74,8 +79,6 @@
|
|
74 |
removeObjectFromScene(data.payload.obj_id);
|
75 |
delete worldObjects[data.payload.obj_id];
|
76 |
}
|
77 |
-
} else if (data.type === 'player_moved') {
|
78 |
-
// Handle player movement visualization if needed
|
79 |
} else if (data.type === 'user_join' || data.type === 'user_leave' || data.type === 'user_rename') {
|
80 |
console.log(`${data.payload.username} ${data.type === 'user_join' ? 'joined' : data.type === 'user_leave' ? 'left' : 'renamed to ' + data.payload.new_username}`);
|
81 |
}
|
@@ -189,46 +192,28 @@
|
|
189 |
}
|
190 |
}
|
191 |
|
192 |
-
function onKeyDown(event) {
|
193 |
-
switch (event.code) {
|
194 |
-
case 'KeyW': moveForward = true; break;
|
195 |
-
case 'KeyS': moveBackward = true; break;
|
196 |
-
case 'KeyA': moveLeft = true; break;
|
197 |
-
case 'KeyD': moveRight = true; break;
|
198 |
-
}
|
199 |
-
}
|
200 |
-
|
201 |
-
function onKeyUp(event) {
|
202 |
-
switch (event.code) {
|
203 |
-
case 'KeyW': moveForward = false; break;
|
204 |
-
case 'KeyS': moveBackward = false; break;
|
205 |
-
case 'KeyA': moveLeft = false; break;
|
206 |
-
case 'KeyD': moveRight = false; break;
|
207 |
-
}
|
208 |
-
}
|
209 |
-
|
210 |
function onMouseDown(event) {
|
211 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
212 |
if (event.button === 0 && selectedObjectType !== 'None') {
|
213 |
-
const raycaster = new THREE.Raycaster();
|
214 |
-
const mouse = new THREE.Vector2(0, 0);
|
215 |
-
raycaster.setFromCamera(mouse, camera);
|
216 |
-
const intersects = raycaster.intersectObjects(scene.children);
|
217 |
for (let intersect of intersects) {
|
218 |
-
if (intersect.object
|
219 |
const position = intersect.point;
|
220 |
-
position.y
|
221 |
placeObject(position);
|
222 |
break;
|
223 |
}
|
224 |
}
|
225 |
} else if (event.button === 2) {
|
226 |
-
const raycaster = new THREE.Raycaster();
|
227 |
-
const mouse = new THREE.Vector2(0, 0);
|
228 |
-
raycaster.setFromCamera(mouse, camera);
|
229 |
-
const intersects = raycaster.intersectObjects(scene.children);
|
230 |
for (let intersect of intersects) {
|
231 |
-
if (intersect.object
|
232 |
websocket.send(JSON.stringify({
|
233 |
type: 'delete_object',
|
234 |
payload: { obj_id: intersect.object.name, username }
|
@@ -256,23 +241,6 @@
|
|
256 |
|
257 |
function animate() {
|
258 |
requestAnimationFrame(animate);
|
259 |
-
const delta = 0.1;
|
260 |
-
const velocity = new THREE.Vector3();
|
261 |
-
if (moveForward) velocity.z -= 0.1;
|
262 |
-
if (moveBackward) velocity.z += 0.1;
|
263 |
-
if (moveLeft) velocity.x -= 0.1;
|
264 |
-
if (moveRight) velocity.x += 0.1;
|
265 |
-
controls.getObject().position.add(velocity);
|
266 |
-
const pos = controls.getObject().position;
|
267 |
-
const rot = controls.getObject().rotation;
|
268 |
-
websocket.send(JSON.stringify({
|
269 |
-
type: 'player_position',
|
270 |
-
payload: {
|
271 |
-
username,
|
272 |
-
position: { x: pos.x, y: pos.y, z: pos.z },
|
273 |
-
rotation: { x: rot.x, y: rot.y, z: rot.z }
|
274 |
-
}
|
275 |
-
}));
|
276 |
renderer.render(scene, camera);
|
277 |
}
|
278 |
|
|
|
11 |
</style>
|
12 |
</head>
|
13 |
<body>
|
14 |
+
<div id="info">Click to place selected object, right-click to delete.</div>
|
15 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"></script>
|
|
|
16 |
<script>
|
17 |
+
let scene, camera, renderer, websocket, selectedObjectType = 'None', worldObjects = {};
|
|
|
18 |
const username = window.USERNAME || 'Anonymous';
|
19 |
const websocketUrl = window.WEBSOCKET_URL || 'ws://localhost:8765';
|
20 |
const plotWidth = window.PLOT_WIDTH || 50.0;
|
|
|
22 |
|
23 |
function init() {
|
24 |
scene = new THREE.Scene();
|
25 |
+
// Orthographic camera for top-down view
|
26 |
+
const aspect = window.innerWidth / window.innerHeight;
|
27 |
+
const viewSize = plotWidth * 0.6;
|
28 |
+
camera = new THREE.OrthographicCamera(
|
29 |
+
-viewSize * aspect, viewSize * aspect,
|
30 |
+
viewSize, -viewSize,
|
31 |
+
0.1, 1000
|
32 |
+
);
|
33 |
+
camera.position.set(0, 20, 0);
|
34 |
+
camera.lookAt(0, 0, 0);
|
35 |
+
|
36 |
renderer = new THREE.WebGLRenderer();
|
37 |
renderer.setSize(window.innerWidth, window.innerHeight);
|
38 |
document.body.appendChild(renderer.domElement);
|
39 |
|
|
|
|
|
|
|
|
|
40 |
const groundGeometry = new THREE.PlaneGeometry(plotWidth, plotDepth);
|
41 |
const groundMaterial = new THREE.MeshBasicMaterial({ color: 0x888888 });
|
42 |
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
|
|
|
46 |
const gridHelper = new THREE.GridHelper(plotWidth, plotWidth / 2);
|
47 |
scene.add(gridHelper);
|
48 |
|
|
|
|
|
|
|
49 |
document.addEventListener('mousedown', onMouseDown);
|
50 |
window.addEventListener('resize', () => {
|
51 |
+
const aspect = window.innerWidth / window.innerHeight;
|
52 |
+
camera.left = -viewSize * aspect;
|
53 |
+
camera.right = viewSize * aspect;
|
54 |
+
camera.top = viewSize;
|
55 |
+
camera.bottom = -viewSize;
|
56 |
camera.updateProjectionMatrix();
|
57 |
renderer.setSize(window.innerWidth, window.innerHeight);
|
58 |
});
|
|
|
79 |
removeObjectFromScene(data.payload.obj_id);
|
80 |
delete worldObjects[data.payload.obj_id];
|
81 |
}
|
|
|
|
|
82 |
} else if (data.type === 'user_join' || data.type === 'user_leave' || data.type === 'user_rename') {
|
83 |
console.log(`${data.payload.username} ${data.type === 'user_join' ? 'joined' : data.type === 'user_leave' ? 'left' : 'renamed to ' + data.payload.new_username}`);
|
84 |
}
|
|
|
192 |
}
|
193 |
}
|
194 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
195 |
function onMouseDown(event) {
|
196 |
+
event.preventDefault();
|
197 |
+
const mouse = new THREE.Vector2(
|
198 |
+
(event.clientX / window.innerWidth) * 2 - 1,
|
199 |
+
-(event.clientY / window.innerHeight) * 2 + 1
|
200 |
+
);
|
201 |
+
const raycaster = new THREE.Raycaster();
|
202 |
+
raycaster.setFromCamera(mouse, camera);
|
203 |
+
const intersects = raycaster.intersectObjects(scene.children);
|
204 |
+
|
205 |
if (event.button === 0 && selectedObjectType !== 'None') {
|
|
|
|
|
|
|
|
|
206 |
for (let intersect of intersects) {
|
207 |
+
if (intersect.object.name === '') { // Ground plane
|
208 |
const position = intersect.point;
|
209 |
+
position.y = 0.5; // Adjust height above ground
|
210 |
placeObject(position);
|
211 |
break;
|
212 |
}
|
213 |
}
|
214 |
} else if (event.button === 2) {
|
|
|
|
|
|
|
|
|
215 |
for (let intersect of intersects) {
|
216 |
+
if (intersect.object.name && intersect.object.name !== '') {
|
217 |
websocket.send(JSON.stringify({
|
218 |
type: 'delete_object',
|
219 |
payload: { obj_id: intersect.object.name, username }
|
|
|
241 |
|
242 |
function animate() {
|
243 |
requestAnimationFrame(animate);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
244 |
renderer.render(scene, camera);
|
245 |
}
|
246 |
|