feat: initialize project with core dependencies and game entry point
This commit is contained in:
109
src/Player.js
Normal file
109
src/Player.js
Normal file
@@ -0,0 +1,109 @@
|
||||
import * as THREE from 'three';
|
||||
import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js';
|
||||
|
||||
export class Player {
|
||||
constructor(camera, colliders) {
|
||||
this.camera = camera;
|
||||
this.colliders = colliders;
|
||||
|
||||
// Player stats
|
||||
this.speed = 5.0;
|
||||
this.height = 1.7; // Eyes height
|
||||
|
||||
// Init controls
|
||||
this.controls = new PointerLockControls(camera, document.body);
|
||||
|
||||
// Movement state
|
||||
this.moveForward = false;
|
||||
this.moveBackward = false;
|
||||
this.moveLeft = false;
|
||||
this.moveRight = false;
|
||||
this.velocity = new THREE.Vector3();
|
||||
this.direction = new THREE.Vector3();
|
||||
|
||||
this.setupInput();
|
||||
}
|
||||
|
||||
setupInput() {
|
||||
const onKeyDown = (event) => {
|
||||
switch (event.code) {
|
||||
case 'KeyW': this.moveForward = true; break;
|
||||
case 'KeyA': this.moveLeft = true; break;
|
||||
case 'KeyS': this.moveBackward = true; break;
|
||||
case 'KeyD': this.moveRight = true; break;
|
||||
}
|
||||
};
|
||||
|
||||
const onKeyUp = (event) => {
|
||||
switch (event.code) {
|
||||
case 'KeyW': this.moveForward = false; break;
|
||||
case 'KeyA': this.moveLeft = false; break;
|
||||
case 'KeyS': this.moveBackward = false; break;
|
||||
case 'KeyD': this.moveRight = false; break;
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('keydown', onKeyDown);
|
||||
document.addEventListener('keyup', onKeyUp);
|
||||
}
|
||||
|
||||
lockControls() {
|
||||
this.controls.lock();
|
||||
}
|
||||
|
||||
getObject() {
|
||||
return this.controls.getObject();
|
||||
}
|
||||
|
||||
update(dt) {
|
||||
if (!this.controls.isLocked) return;
|
||||
|
||||
// Friction-like dampening
|
||||
// Simple direct velocity for now
|
||||
this.velocity.x = 0;
|
||||
this.velocity.z = 0;
|
||||
|
||||
this.direction.z = Number(this.moveForward) - Number(this.moveBackward);
|
||||
this.direction.x = Number(this.moveRight) - Number(this.moveLeft);
|
||||
this.direction.normalize(); // Ensure consistent speed in all directions
|
||||
|
||||
if (this.moveForward || this.moveBackward) this.velocity.z -= this.direction.z * this.speed * dt;
|
||||
if (this.moveLeft || this.moveRight) this.velocity.x -= this.direction.x * this.speed * dt;
|
||||
|
||||
// Apply movement
|
||||
this.controls.moveRight(-this.velocity.x);
|
||||
this.controls.moveForward(-this.velocity.z);
|
||||
|
||||
// Simple Collision: Push back
|
||||
const playerPos = this.controls.getObject().position;
|
||||
const playerRadius = 0.5; // approximated radius
|
||||
|
||||
for (const collider of this.colliders) {
|
||||
// Assume colliders are BoxGeometry meshes aligned with axes for now
|
||||
const box = new THREE.Box3().setFromObject(collider);
|
||||
|
||||
// Check if player is inside the box (expanded by radius)
|
||||
// We only check X/Z for walls
|
||||
if (playerPos.x > box.min.x - playerRadius && playerPos.x < box.max.x + playerRadius &&
|
||||
playerPos.z > box.min.z - playerRadius && playerPos.z < box.max.z + playerRadius) {
|
||||
|
||||
// Very simple resolution: determine closest edge and push out
|
||||
// This is a naive implementation but works for static orthogonal walls
|
||||
const dx1 = Math.abs(playerPos.x - (box.min.x - playerRadius));
|
||||
const dx2 = Math.abs(playerPos.x - (box.max.x + playerRadius));
|
||||
const dz1 = Math.abs(playerPos.z - (box.min.z - playerRadius));
|
||||
const dz2 = Math.abs(playerPos.z - (box.max.z + playerRadius));
|
||||
|
||||
const minOverlap = Math.min(dx1, dx2, dz1, dz2);
|
||||
|
||||
if (minOverlap === dx1) playerPos.x = box.min.x - playerRadius;
|
||||
else if (minOverlap === dx2) playerPos.x = box.max.x + playerRadius;
|
||||
else if (minOverlap === dz1) playerPos.z = box.min.z - playerRadius;
|
||||
else if (minOverlap === dz2) playerPos.z = box.max.z + playerRadius;
|
||||
}
|
||||
}
|
||||
|
||||
// Keep player on ground
|
||||
playerPos.y = this.height;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user