freeblox/packages/client/src/game/core/gameplay.ts

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);
};
}
}