Untitled
unknown
html
a year ago
13 kB
24
Indexable
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>MULTIPLAYER ENABLE3D</title> <link rel="stylesheet" href="/css/examples.css" /> <style> /* Centering using CSS */ .centered { text-align: center; } </style> <script src="/lib/enable3d/enable3d.framework.0.25.4.min.js"></script> <script src="/js/examples.js"></script> </head> <body> <div class="centered" id="info-text">Use WASD, SPACE and your Mouse.<br />Try to play it on your mobile device :)</div> <br> <br> <br> <div class="centered" id="forms"> <div id="login-form"> <h2>Login</h2> <input type="text" id="login-username" placeholder="Username" /><br><Br> <input type="password" id="login-password" placeholder="Password" /><Br><Br><Br> <button onclick="login()">Login</button> <p><a href="#" onclick="toggleForms()">Register</a></p> </div> <div id="register-form" style="display:none;"> <h2>Register</h2> <input type="text" id="register-username" placeholder="Username" /><Br><Br> <input type="password" id="register-password" placeholder="Password" /><Br><Br><Br> <button onclick="register()">Register</button> <p><a href="#" onclick="toggleForms()">Login</a></p> </div> </div> <script> function toggleForms() { const loginForm = document.getElementById('login-form'); const registerForm = document.getElementById('register-form'); loginForm.style.display = loginForm.style.display === 'none' ? 'block' : 'none'; registerForm.style.display = registerForm.style.display === 'none' ? 'block' : 'none'; } async function login() { const username = document.getElementById('login-username').value; const password = document.getElementById('login-password').value; const response = await fetch('/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) }); const result = await response.json(); if (result.success) { initGame(result.user); alert("Login success"); } else { alert('Login failed'); } } async function register() { const username = document.getElementById('register-username').value; const password = document.getElementById('register-password').value; const response = await fetch('/api/register', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) }); const result = await response.json(); if (result.success) { toggleForms(); } else { alert('Registration failed'); } } function initGame(user) { document.getElementById('forms').style.display = 'none'; document.getElementById('info-text').style.display = 'none'; // Initialize the game with user data startGame(user); } function startGame(user) { const { Project, PhysicsLoader, Scene3D, ExtendedObject3D, THREE, JoyStick, ThirdPersonControls, PointerLock, PointerDrag } = ENABLE3D; class MainScene extends Scene3D { constructor() { super('MainScene'); this.user = user; } async init() { this.renderer.setPixelRatio(Math.max(1, window.devicePixelRatio / 2)); this.canJump = true; this.move = false; this.moveTop = 0; this.moveRight = 0; } async preload() { try { const map = this.load.preload('map', '/assets/glb/map.glb'); const character = this.load.preload('character', '/assets/glb/character.glb'); await Promise.all([map, character]); } catch (error) { console.error('Error loading assets:', error); } } async create() { console.log("Creating scene..."); await this.preload(); const { lights } = await this.warpSpeed('-ground', '-orbitControls'); const { hemisphereLight, ambientLight, directionalLight } = lights; const intensity = 1; hemisphereLight.intensity = intensity; ambientLight.intensity = intensity; directionalLight.intensity = intensity; const addMap = async () => { const object = await this.load.gltf('map'); const scene = object.scenes[0]; const map = new ExtendedObject3D(); map.name = 'scene'; map.add(scene); this.add.existing(map); object.animations.forEach((anim, i) => { map.mixer = this.animationMixers.create(map); map.action = []; map.action[i] = map.mixer.clipAction(anim); map.action[i].play(); }); map.traverse(child => { if (child.isMesh) { child.castShadow = child.receiveShadow = false; child.material.metalness = 0; child.material.roughness = 1; if (/mesh/i.test(child.name)) { this.physics.add.existing(child, { shape: 'concave', mass: 0, collisionFlags: 1, autoCenter: false }); child.body.setAngularFactor(0, 0, 0); child.body.setLinearFactor(0, 0, 0); } } }); }; const addCharacter = async () => { const object = await this.load.gltf('character'); const character = object.scene.children[0]; this.character = new ExtendedObject3D(); this.character.name = 'character'; this.character.rotateY(Math.PI + 0.1); this.character.add(character); this.character.rotation.set(0, Math.PI * 1.5, 0); this.character.position.set(this.user.position.x, this.user.position.y, this.user.position.z); this.character.traverse(child => { if (child.isMesh) { child.castShadow = child.receiveShadow = false; child.material.roughness = 1; child.material.metalness = 0; } }); this.animationMixers.add(this.character.animation.mixer); object.animations.forEach(animation => { if (animation.name) { this.character.animation.add(animation.name, animation); } }); this.character.animation.play('idle'); this.add.existing(this.character); this.physics.add.existing(this.character, { shape: 'sphere', radius: 0.25, width: 0.5, offset: { y: -0.25 } }); this.character.body.setFriction(0.8); this.character.body.setAngularFactor(0, 0, 0); this.character.body.setCcdMotionThreshold(1e-7); this.character.body.setCcdSweptSphereRadius(0.25); this.controls = new ThirdPersonControls(this.camera, this.character, { offset: new THREE.Vector3(0, 1, 0), targetRadius: 3 }); this.controls.theta = 90; if (!isTouchDevice) { let pl = new PointerLock(this.canvas); let pd = new PointerDrag(this.canvas); pd.onMove(delta => { if (pl.isLocked()) { this.controls.update(delta.x * 2, delta.y * 2); } }); } }; await addMap(); await addCharacter(); this.keys = { w: { isDown: false }, a: { isDown: false }, s: { isDown: false }, d: { isDown: false }, space: { isDown: false } }; const press = (e, isDown) => { e.preventDefault(); const { keyCode } = e; switch (keyCode) { case 87: this.keys.w.isDown = isDown; break; case 38: this.keys.w.isDown = isDown; break; case 32: this.keys.space.isDown = isDown; break; } }; document.addEventListener('keydown', e => press(e, true)); document.addEventListener('keyup', e => press(e, false)); if (isTouchDevice) { const joystick = new JoyStick(); const axis = joystick.add.axis({ styles: { left: 35, bottom: 35, size: 100 } }); axis.onMove(event => { const { top, right } = event; this.moveTop = top * 3; this.moveRight = right * 3; }); const buttonA = joystick.add.button({ letter: 'A', styles: { right: 35, bottom: 110, size: 80 } }); buttonA.onClick(() => this.jump()); const buttonB = joystick.add.button({ letter: 'B', styles: { right: 110, bottom: 35, size: 80 } }); buttonB.onClick(() => (this.move = true)); buttonB.onRelease(() => (this.move = false)); } setTimeout(() => { const placeholder = document.getElementById('welcome-game-placeholder'); if (placeholder) placeholder.remove(); }, 500); } jump() { if (!this.character || !this.canJump) return; this.canJump = false; this.character.animation.play('jump_running', 500, false); setTimeout(() => { this.canJump = true; this.character.animation.play('idle'); }, 650); this.character.body.applyForceY(6); } update(time, delta) { if (this.character && this.character.body) { this.controls.update(this.moveRight * 2, -this.moveTop * 2); const speed = 4; const v3 = new THREE.Vector3(); const rotation = this.camera.getWorldDirection(v3); const theta = Math.atan2(rotation.x, rotation.z); const rotationcharacter = this.character.getWorldDirection(v3); const thetacharacter = Math.atan2(rotationcharacter.x, rotationcharacter.z); this.character.body.setAngularVelocityY(0); const l = Math.abs(theta - thetacharacter); let rotationSpeed = isTouchDevice ? 2 : 4; let d = Math.PI / 24; if (l > d) { if (l > Math.PI - d) rotationSpeed *= -1; if (theta < thetacharacter) rotationSpeed *= -1; this.character.body.setAngularVelocityY(rotationSpeed); } if (this.keys.w.isDown || this.move) { if (this.character.animation.current === 'idle' && this.canJump) this.character.animation.play('run'); const x = Math.sin(theta) * speed, y = this.character.body.velocity.y, z = Math.cos(theta) * speed; this.character.body.setVelocity(x, y, z); } else { if (this.character.animation.current === 'run' && this.canJump) this.character.animation.play('idle'); } if (this.keys.space.isDown && this.canJump) { this.jump(); } savePlayerState(this.user._id, this.character.position); } } } window.addEventListener('load', async () => { await PhysicsLoader('/lib/ammo/kripken'); const project = new Project({ antialias: false, maxSubSteps: 10, fixedTimeStep: 1 / 120, scenes: [MainScene] }); // Since MainScene is constructed internally, you need to hook into it after initialization project.scenes.forEach(scene => { scene.on('start', async () => { await scene.create(); // Ensure create() is called after everything is loaded }); }); }); async function savePlayerState(userId, position) { await fetch('/api/save', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ userId, position }) }); } } </script> </body> </html>
Editor is loading...
Leave a Comment