134 lines
3.5 KiB
TypeScript
134 lines
3.5 KiB
TypeScript
import {
|
|
EngineComponent,
|
|
World,
|
|
instanceCharacterObject,
|
|
getCharacterController,
|
|
Humanoid,
|
|
} from '@freeblox/engine';
|
|
|
|
import { Vector3 } from 'three';
|
|
import { ThirdPersonCamera } from './camera';
|
|
|
|
/**
|
|
* Gameplay manager.
|
|
*/
|
|
export class GameplayComponent extends EngineComponent {
|
|
public name = GameplayComponent.name;
|
|
public world!: World;
|
|
public cleanUpEvents?: () => void;
|
|
|
|
public characters: Humanoid[] = [];
|
|
|
|
public controls!: ThirdPersonCamera;
|
|
public character!: Humanoid;
|
|
public movementSpeed = 16;
|
|
public movement = {
|
|
forward: 0,
|
|
backward: 0,
|
|
left: 0,
|
|
right: 0,
|
|
};
|
|
|
|
private move = new Vector3();
|
|
private look = new Vector3();
|
|
|
|
override initialize(): void {
|
|
this.world = this.renderer.scene.getObjectByName('World') as World;
|
|
this.cleanUpEvents = this.bindEvents();
|
|
}
|
|
|
|
override update(delta: number): void {
|
|
this.controls?.update(delta);
|
|
for (const character of this.characters) {
|
|
character.tick(delta);
|
|
}
|
|
|
|
this.move.set(0, 0, 0);
|
|
this.look.setFromMatrixColumn(this.renderer.camera.matrix, 0);
|
|
this.look.multiplyScalar(this.movement.forward + -this.movement.backward);
|
|
this.look.crossVectors(this.renderer.camera.up, this.look);
|
|
this.move.add(this.look);
|
|
|
|
this.look.setFromMatrixColumn(this.renderer.camera.matrix, 0);
|
|
this.look.multiplyScalar(this.movement.right + -this.movement.left);
|
|
this.move.add(this.look);
|
|
|
|
this.look.copy(this.move).normalize();
|
|
this.character?.localToWorld(this.look);
|
|
|
|
this.character?.setVelocity(this.move);
|
|
if (this.move.length()) {
|
|
this.character?.setLook(this.move.clone().normalize());
|
|
}
|
|
}
|
|
|
|
override dispose(): void {
|
|
this.cleanUpEvents?.();
|
|
}
|
|
|
|
public async loadCharacter(name: string, uuid?: string) {
|
|
const char = await instanceCharacterObject(name);
|
|
if (uuid) char.uuid = uuid;
|
|
const ctrl = getCharacterController(char);
|
|
this.world.add(char);
|
|
this.characters.push(ctrl);
|
|
ctrl.initialize();
|
|
this.character = ctrl;
|
|
|
|
this.controls = new ThirdPersonCamera(
|
|
this.renderer.camera,
|
|
char,
|
|
this.renderer.renderer.domElement
|
|
);
|
|
this.controls.initialize();
|
|
}
|
|
|
|
private bindEvents() {
|
|
const keyDownEvent = (event: KeyboardEvent) => {
|
|
switch (event.code) {
|
|
case 'KeyW':
|
|
this.movement.forward = this.movementSpeed;
|
|
break;
|
|
case 'KeyS':
|
|
this.movement.backward = this.movementSpeed;
|
|
break;
|
|
case 'KeyA':
|
|
this.movement.left = this.movementSpeed;
|
|
break;
|
|
case 'KeyD':
|
|
this.movement.right = this.movementSpeed;
|
|
break;
|
|
}
|
|
};
|
|
const keyUpEvent = (event: KeyboardEvent) => {
|
|
switch (event.code) {
|
|
case 'KeyW':
|
|
this.movement.forward = 0;
|
|
break;
|
|
case 'KeyS':
|
|
this.movement.backward = 0;
|
|
break;
|
|
case 'KeyA':
|
|
this.movement.left = 0;
|
|
break;
|
|
case 'KeyD':
|
|
this.movement.right = 0;
|
|
break;
|
|
}
|
|
};
|
|
|
|
const initializedEvent = () => {
|
|
this.loadCharacter('Diamond');
|
|
};
|
|
|
|
window.addEventListener('keydown', keyDownEvent);
|
|
window.addEventListener('keyup', keyUpEvent);
|
|
this.events.addListener('initialized', initializedEvent);
|
|
return () => {
|
|
window.removeEventListener('keydown', keyDownEvent);
|
|
window.removeEventListener('keyup', keyUpEvent);
|
|
this.events.removeEventListener('initialized', initializedEvent);
|
|
};
|
|
}
|
|
}
|