From be36b310b469e07a137d4783cb14038371546e7b Mon Sep 17 00:00:00 2001 From: Paul Mathieu Date: Fri, 14 Feb 2025 19:05:49 +0100 Subject: [PATCH] skycraft: can walk around the earth --- skycraft/draw.ts | 4 +++- skycraft/index.ts | 40 ++++++++++++++++++++++++++++++++-------- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/skycraft/draw.ts b/skycraft/draw.ts index 24e531b..5d611d7 100644 --- a/skycraft/draw.ts +++ b/skycraft/draw.ts @@ -312,10 +312,12 @@ export function draw(context) { gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + const thirdPerson = context.landed ? se3.identity() : se3.translation(0, 1, 4); + const playerView = [ player.tf, // player position & orientation camera.tf, // camera orientation relative to player - se3.translation(0, 1, 4), // step back from the player + thirdPerson, ]; if (context.landed) { const body = context.landedBody; diff --git a/skycraft/index.ts b/skycraft/index.ts index 6d61b75..afd4bd9 100644 --- a/skycraft/index.ts +++ b/skycraft/index.ts @@ -173,10 +173,20 @@ function initUiListeners(canvas: HTMLCanvasElement, context) { } }; const moveListener = e => { -// context.camera.orientation[0] -= e.movementY / 500; -// context.camera.orientation[1] -= e.movementX / 500; - context.camera.tf =[ - context.camera.tf, + const cam = context.camera; + if (context.landed) { + cam.orientation[1] -= e.movementX / 500; + cam.orientation[0] -= e.movementY / 500; + cam.tf = [ + se3.roty(cam.orientation[1]), + se3.rotx(cam.orientation[0]), + ].reduce(se3.product); + + return; + } + + cam.tf =[ + cam.tf, se3.roty(-e.movementX / 500), se3.rotx(-e.movementY / 500), ].reduce(se3.product); @@ -252,21 +262,25 @@ function moveOnGround(context, forward, right) { se3.orientationOnly(context.player.tf), context.camera.tf, ); - const dir = [right, 0, -forward, 0]; + const dir = se3.apply(tf, [right, 0, -forward, 0]); if (context.flying) { context.player.tf = [ - context.player.tf, se3.translation(...dir), + context.player.tf, ].reduce(se3.product); return; } - const dv = linalg.scale(se3.apply(tf, dir), 10); + const dv = linalg.scale(dir, 10); + const maxSpeed = 8; const airMovement = 0.08; if (context.isOnGround) { - context.player.velocity = dv; + const up = upDirection(context); + const vertical = linalg.dot(dv, up); + const horizontal = linalg.diff(dv, linalg.scale(up, vertical)); + context.player.velocity = horizontal; return; } @@ -466,6 +480,11 @@ function effectiveGravity(position: number[], rootBody: Body) : number[] { return acceleration; } +function upDirection(context) { + const gravity = landedGravity(context); + return linalg.normalize(linalg.scale(gravity, -1)); +} + function landedGravity(context) { // just clamp "down" to one of our six directions const pos = context.player.position; @@ -558,6 +577,11 @@ function updateLandedPhysics(context, dt) { } context.isOnGround = isOnGround; context.player.tf = se3.setPosition(context.player.tf, newPos); + + // up is up + const p = context.player; + const currentOrientation = slerp(p.tf, alignUp(p.tf, upDirection(context)), 0.1); + p.tf = se3.setOrientation(p.tf, currentOrientation); } function updatePhysics(time: number, context) {