diff options
| author | metamuffin <metamuffin@disroot.org> | 2025-12-18 22:48:36 +0100 |
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2025-12-18 22:49:18 +0100 |
| commit | 6832af5ee35b9d16668e1d34f191715f3755679f (patch) | |
| tree | ff99fd6d10cb99f333f82598f17b22c3e66d145f | |
| parent | 5cf50403fabbb3e79b771bc157d5a4c57c614570 (diff) | |
| download | hurrycurry-6832af5ee35b9d16668e1d34f191715f3755679f.tar hurrycurry-6832af5ee35b9d16668e1d34f191715f3755679f.tar.bz2 hurrycurry-6832af5ee35b9d16668e1d34f191715f3755679f.tar.zst | |
test-client: enable movement prediction
| -rw-r--r-- | test-client/main.ts | 42 | ||||
| -rw-r--r-- | test-client/movement.ts | 32 | ||||
| -rw-r--r-- | test-client/visual.ts | 4 |
3 files changed, 41 insertions, 37 deletions
diff --git a/test-client/main.ts b/test-client/main.ts index f66a46a4..e106a135 100644 --- a/test-client/main.ts +++ b/test-client/main.ts @@ -96,7 +96,6 @@ export interface PlayerData extends MovementBase { id: number, name: string, hands: ItemSlot[], - direction: V2, class: PlayerClass, character: number, anim_position: V2, @@ -188,12 +187,13 @@ function packet(p: PacketC) { character: p.character.color, class: p.class, name: p.name, - rot: 0, + rotation: 0, facing: { x: 0, y: 1 }, - vel: { x: 0, y: 0 }, - direction: { x: 0, y: 0 }, + velocity: { x: 0, y: 0 }, stamina: 0, boosting: false, + input_boost: false, + input_direction: { x: 0, y: 0 }, }) break; } @@ -202,15 +202,13 @@ function packet(p: PacketC) { break; case "movement": { const pl = players.get(p.player)! - const pos = { x: p.pos[0], y: p.pos[1] } - // const dist = length(sub_v2(pl.position, pos));a - // TODO this is actually not a good idea if latency is too high - // if (p.player == my_id && dist < 3) return; // we know better where we are - if (p.player == my_id) return last_server_sent_position = pos - pl.position.x = pos.x - pl.position.y = pos.y - pl.boosting = p.boost - pl.rot = p.rot + if (p.player == my_id) return last_server_sent_position = { x: p.pos[0], y: p.pos[1] } + pl.position.x = p.pos[0] + pl.position.y = p.pos[1] + pl.rotation = p.rot + pl.input_direction.x = p.dir[0] + pl.input_direction.y = p.dir[1] + pl.input_boost = p.boost break; } case "move_item": { @@ -325,7 +323,7 @@ function packet(p: PacketC) { break; case "environment": break - case "effect": + case "effect2": break; case "flush_map": break; @@ -424,12 +422,12 @@ export function get_interact_target(): V2 | undefined { if (location.hash.search("oldinteract") != -1) return { - x: Math.floor(me.position.x + Math.sin(me.rot)), - y: Math.floor(me.position.y + Math.cos(me.rot)) + x: Math.floor(me.position.x + Math.sin(me.rotation)), + y: Math.floor(me.position.y + Math.cos(me.rotation)) } - const rx = me.position.x + Math.sin(me.rot) * 0.7 - const ry = me.position.y + Math.cos(me.rot) * 0.7 + const rx = me.position.x + Math.sin(me.rotation) * 0.7 + const ry = me.position.y + Math.cos(me.rotation) * 0.7 const bx = Math.floor(rx) const by = Math.floor(ry) let best = { x: bx, y: by } @@ -465,7 +463,7 @@ function set_interact(edge: boolean, hand: number) { function tick_update() { const p = players.get(my_id) if (!p) return - send({ player: my_id, type: "movement", pos: [p.position.x, p.position.y], dir: [p.direction.x, p.direction.y], boost: p.boosting }) + send({ player: my_id, type: "movement", pos: [p.position.x, p.position.y], dir: [p.input_direction.x, p.input_direction.y], boost: p.boosting }) } function frame_update(dt: number) { @@ -479,8 +477,10 @@ function frame_update(dt: number) { y: (+keys_down.has(KEY_DOWN) - +keys_down.has(KEY_UP)) }) if (interacting) direction.x *= 0, direction.y *= 0 - p.direction = direction - update_movement(p, dt, direction, keys_down.has("KeyK")) + p.input_direction = direction + p.input_boost = keys_down.has("KeyK") + + players.forEach(p => update_movement(p, dt)) for (const [_, a] of players) for (const [_, b] of players) diff --git a/test-client/movement.ts b/test-client/movement.ts index d3f30ae0..6d8d963c 100644 --- a/test-client/movement.ts +++ b/test-client/movement.ts @@ -27,30 +27,34 @@ export const BOOST_DURATION = 0.3 export const BOOST_RESTORE = 0.5 export interface MovementBase { + input_direction: V2, + input_boost: boolean, position: V2, - vel: V2, facing: V2, - rot: number, + rotation: number, + velocity: V2, boosting: boolean, stamina: number } -export function update_movement(p: MovementBase, dt: number, direction: V2, boost: boolean) { +export function update_movement(p: MovementBase, dt: number) { + const direction = p.input_direction; + let boost = p.input_boost; if (length(direction) > 0.05) lerp_exp_v2_mut(p.facing, direction, dt * 10.) if (length(direction) < 0.5) direction.x = direction.y = 0 - p.rot = Math.atan2(p.facing.x, p.facing.y) + p.rotation = Math.atan2(p.facing.x, p.facing.y) boost &&= length(direction) > 0.1 p.boosting = boost && (p.boosting || p.stamina >= 1) && p.stamina > 0 if (p.boosting) p.stamina -= dt / BOOST_DURATION else p.stamina += dt / BOOST_RESTORE p.stamina = Math.max(Math.min(p.stamina, 1), 0) const speed = PLAYER_SPEED * (p.boosting ? BOOST_FACTOR : 1) - p.vel.x += direction.x * dt * speed - p.vel.y += direction.y * dt * speed - p.position.x += p.vel.x * dt - p.position.y += p.vel.y * dt + p.velocity.x += direction.x * dt * speed + p.velocity.y += direction.y * dt * speed + p.position.x += p.velocity.x * dt + p.position.y += p.velocity.y * dt collide_player(p, dt) - lerp_exp_v2_mut(p.vel, { x: 0, y: 0 }, dt * PLAYER_FRICTION) + lerp_exp_v2_mut(p.velocity, { x: 0, y: 0 }, dt * PLAYER_FRICTION) } function collide_player(p: MovementBase, _dt: number) { for (let xo = -1; xo <= 1; xo++) { @@ -73,9 +77,9 @@ function collide_player(p: MovementBase, _dt: number) { p.position.x += (PLAYER_SIZE - d) * grad_x p.position.y += (PLAYER_SIZE - d) * grad_y - const vdotn = (grad_x * p.vel.x) + (grad_y * p.vel.y) - p.vel.x -= grad_x * vdotn - p.vel.y -= grad_y * vdotn + const vdotn = (grad_x * p.velocity.x) + (grad_y * p.velocity.y) + p.velocity.x -= grad_x * vdotn + p.velocity.y -= grad_y * vdotn } } } @@ -86,8 +90,8 @@ export function collide_player_player(a: MovementBase, b: MovementBase, dt: numb if (d >= PLAYER_SIZE * 2) return const norm = normalize(diff); const f = 100 / (1 + d) - a.vel.x += norm.x * f * dt - a.vel.y += norm.y * f * dt + a.velocity.x += norm.x * f * dt + a.velocity.y += norm.y * f * dt } export function aabb_point_distance( diff --git a/test-client/visual.ts b/test-client/visual.ts index 823fc006..fa183004 100644 --- a/test-client/visual.ts +++ b/test-client/visual.ts @@ -146,7 +146,7 @@ function draw_info_overlay() { ctx.textBaseline = "bottom" ctx.font = "20px sans-serif" ctx.fillText(`position = ${JSON.stringify(players.get(my_id)?.anim_position)}`, 10, 30) - ctx.fillText(`velocity = ${JSON.stringify(players.get(my_id)?.vel)}`, 10, 50) + ctx.fillText(`velocity = ${JSON.stringify(players.get(my_id)?.velocity)}`, 10, 50) ctx.fillText(`interact = ${JSON.stringify(get_interact_target())}`, 10, 70) ctx.fillText(`particle_count = ${particle_count()}`, 10, 90) } @@ -173,7 +173,7 @@ function draw_item(item: ItemData) { function draw_player(player: PlayerData) { ctx.save() ctx.translate(player.anim_position.x, player.anim_position.y) - ctx.rotate(-player.rot) + ctx.rotate(-player.rotation) if (player.boosting) ctx.scale(1.3, 1.3) draw_character(player.class, player.character) ctx.restore() |