Untitled
unknown
html
a year ago
13 kB
27
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