aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-12-18 22:48:36 +0100
committermetamuffin <metamuffin@disroot.org>2025-12-18 22:49:18 +0100
commit6832af5ee35b9d16668e1d34f191715f3755679f (patch)
treeff99fd6d10cb99f333f82598f17b22c3e66d145f
parent5cf50403fabbb3e79b771bc157d5a4c57c614570 (diff)
downloadhurrycurry-6832af5ee35b9d16668e1d34f191715f3755679f.tar
hurrycurry-6832af5ee35b9d16668e1d34f191715f3755679f.tar.bz2
hurrycurry-6832af5ee35b9d16668e1d34f191715f3755679f.tar.zst
test-client: enable movement prediction
-rw-r--r--test-client/main.ts42
-rw-r--r--test-client/movement.ts32
-rw-r--r--test-client/visual.ts4
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()