diff --git a/src/game/humanoid.object.ts b/src/game/humanoid.object.ts index 384819a..6f86a13 100644 --- a/src/game/humanoid.object.ts +++ b/src/game/humanoid.object.ts @@ -119,6 +119,11 @@ export class Humanoid extends GameObject implements PhysicsTicking { tick(dt: number): void { if (!this.ready) return; + // Stick to ground + if (this.grounded) { + this._appliedGravity.y = 0; + } + // Apply rigidbody transforms to object from last process tick if (this.rigidBody) { this.parent!.position.copy(this.rigidBody.translation() as any); @@ -146,11 +151,6 @@ export class Humanoid extends GameObject implements PhysicsTicking { this.parent?.lookAt(this._currentLookAt); this.applyRotation(this.parent!.quaternion); - - // Stick to ground - if (this.grounded) { - this._appliedGravity.y = 0; - } } die() { diff --git a/src/world/physics.service.ts b/src/world/physics.service.ts index feb6e9b..c8c5a8c 100644 --- a/src/world/physics.service.ts +++ b/src/world/physics.service.ts @@ -15,27 +15,33 @@ export class PhysicsService { private running = false; private sceneInitialized = false; - private physicsTicker: ReturnType; + private physicsTicker: ReturnType; private trackedObjects: PhysicsTicking[] = []; + private tickCallback?: () => void; loop() { if (!this.running) return; - this.physicsTicker = setTimeout(() => this.loop(), 25); - this.physicsWorld.step(); - for (const object of this.trackedObjects) object.tick(0.025); // TODO: DT + this.physicsTicker = setInterval(() => { + this.physicsWorld.step(); + for (const object of this.trackedObjects) object.tick(0.016); + this.tickCallback?.(); + }, 16); } - async start(world: World) { + async start(world: World, cb?: () => void) { this.world = world; await RAPIER.init(); this.physicsWorld = new RAPIER.World(new Vector3(0, this.world.gravity, 0)); + this.physicsWorld.timestep = 0.016; this.running = true; + this.tickCallback = cb; this.initializePhysicsScene(); this.loop(); } stop() { this.running = false; + clearInterval(this.physicsTicker); } getObjectPackets() { @@ -48,7 +54,10 @@ export class PhysicsService { .write(object.uuid, String) .write(body.translation(), 'vec3') .write(body.rotation(), 'quat') - .write(body.linvel(), 'vec3') + .write( + object instanceof Humanoid ? body.nextTranslation() : body.linvel(), + 'vec3', + ) .write(body.angvel(), 'vec3') .toBuffer(), ); diff --git a/src/world/world.service.ts b/src/world/world.service.ts index bcf3c49..e556205 100644 --- a/src/world/world.service.ts +++ b/src/world/world.service.ts @@ -19,7 +19,7 @@ export class WorldService implements OnModuleInit { private logger = new Logger(WorldService.name); private world = new World(); private environment = new Environment(); - private broadcastWorldStateTicker!: ReturnType; + private broadcastTick = 0; constructor( private readonly players: PlayerStoreService, @@ -33,8 +33,14 @@ export class WorldService implements OnModuleInit { this.loadWorld() .then(() => { this.logger.log('World file loaded'); - this.physics.start(this.world); - this.startUpdateTick(); + this.physics.start(this.world, () => { + if (this.broadcastTick >= 0.25) { + this.broadcastTick = 0; + this.broadcastWorldState(); + return; + } + this.broadcastTick += 0.016; + }); }) .catch((err) => { this.logger.error('Failed to load world:', err.stack); @@ -207,11 +213,4 @@ export class WorldService implements OnModuleInit { this.players.broadcastExcept(data, this.players.getUninitializedIds()), ); } - - private startUpdateTick() { - this.broadcastWorldStateTicker = setInterval( - () => this.broadcastWorldState(), - 5000, - ); - } }