118 lines
2.9 KiB
TypeScript
118 lines
2.9 KiB
TypeScript
|
import {
|
||
|
EngineComponent,
|
||
|
EventEmitter,
|
||
|
World,
|
||
|
instanceCharacterObject,
|
||
|
getCharacterController,
|
||
|
Humanoid,
|
||
|
} from '@freeblox/engine';
|
||
|
import { GameEvents } from '../types/events';
|
||
|
|
||
|
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
||
|
import { Vector3 } from 'three';
|
||
|
|
||
|
/**
|
||
|
* Gameplay manager.
|
||
|
*/
|
||
|
export class GameplayComponent extends EngineComponent {
|
||
|
public name = GameplayComponent.name;
|
||
|
public events = new EventEmitter<GameEvents>();
|
||
|
public world!: World;
|
||
|
public cleanUpEvents?: () => void;
|
||
|
|
||
|
public characters: Humanoid[] = [];
|
||
|
|
||
|
public controls!: OrbitControls;
|
||
|
public character!: Humanoid;
|
||
|
public movementSpeed = 16;
|
||
|
public movement = {
|
||
|
forward: 0,
|
||
|
backward: 0,
|
||
|
left: 0,
|
||
|
right: 0,
|
||
|
};
|
||
|
|
||
|
override initialize(): void {
|
||
|
this.world = this.renderer.scene.getObjectByName('World') as World;
|
||
|
this.cleanUpEvents = this.bindEvents();
|
||
|
this.controls = new OrbitControls(
|
||
|
this.renderer.camera,
|
||
|
this.renderer.renderer.domElement
|
||
|
);
|
||
|
this.controls.enablePan = false;
|
||
|
|
||
|
this.loadCharacter('Diamond');
|
||
|
}
|
||
|
|
||
|
override update(delta: number): void {
|
||
|
this.controls.update();
|
||
|
for (const character of this.characters) {
|
||
|
character.tick(delta);
|
||
|
}
|
||
|
this.character?.setVelocity(
|
||
|
new Vector3(
|
||
|
this.movement.left + -this.movement.right,
|
||
|
0,
|
||
|
this.movement.forward + -this.movement.backward
|
||
|
)
|
||
|
);
|
||
|
this.character?.getWorldPosition(this.controls.target);
|
||
|
}
|
||
|
|
||
|
override cleanUp(): 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;
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
window.addEventListener('keydown', keyDownEvent);
|
||
|
window.addEventListener('keyup', keyUpEvent);
|
||
|
return () => {
|
||
|
window.removeEventListener('keydown', keyDownEvent);
|
||
|
window.removeEventListener('keyup', keyUpEvent);
|
||
|
};
|
||
|
}
|
||
|
}
|