diff options
author | metamuffin <metamuffin@disroot.org> | 2024-06-21 12:39:50 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-06-23 19:26:47 +0200 |
commit | 1ab1fd8cc03678ac180673884eff098821bcecd2 (patch) | |
tree | fc4d4668628dd4cd45b7d57c4efe74fec135ecba /test-client/movement.ts | |
parent | 607b3509f6bfd7d8ca39b12d01a6428689bb3ded (diff) | |
download | hurrycurry-1ab1fd8cc03678ac180673884eff098821bcecd2.tar hurrycurry-1ab1fd8cc03678ac180673884eff098821bcecd2.tar.bz2 hurrycurry-1ab1fd8cc03678ac180673884eff098821bcecd2.tar.zst |
refactor movement
Diffstat (limited to 'test-client/movement.ts')
-rw-r--r-- | test-client/movement.ts | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/test-client/movement.ts b/test-client/movement.ts new file mode 100644 index 00000000..883a64ec --- /dev/null +++ b/test-client/movement.ts @@ -0,0 +1,62 @@ +import { data } from "./main.ts"; +import { tiles, players, PlayerData } from "./main.ts"; +import { V2, normalize, length, sub_v2, lerp_exp_v2_mut } from "./util.ts"; + +export const PLAYER_SIZE = 0.4; + +export function player_movement_update(p: PlayerData, dt: number, input: V2) { + if (length(input) > 0.1) lerp_exp_v2_mut(p.facing, input, dt * 10.) + p.rot = Math.atan2(p.facing.x, p.facing.y) + p.vel.x += input.x * dt * 25 + p.vel.y += input.y * dt * 25 + p.x += p.vel.x * dt + p.y += p.vel.y * dt + collide_player(p, dt) + lerp_exp_v2_mut(p.vel, { x: 0, y: 0 }, dt * 5.) +} + +function collide_player(p: PlayerData, dt: number) { + for (const [_, tile] of tiles) { + if (!data.tile_collide[tile.kind]) continue + + const d = aabb_point_distance(tile.x, tile.y, tile.x + 1, tile.y + 1, p.x, p.y) + if (d > PLAYER_SIZE) continue + + const h = 0.01 + const d_sample_x = aabb_point_distance(tile.x, tile.y, tile.x + 1, tile.y + 1, p.x + h, p.y) + const d_sample_y = aabb_point_distance(tile.x, tile.y, tile.x + 1, tile.y + 1, p.x, p.y + h) + const grad_x = (d_sample_x - d) / h + const grad_y = (d_sample_y - d) / h + + p.x += (PLAYER_SIZE - d) * grad_x + p.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 + } + + for (const [_, player] of players) { + const diff = sub_v2(p, player) + const d = length(diff) + if (d < 0.01) continue + if (d >= PLAYER_SIZE * 2) continue + const norm = normalize(diff); + const f = 1 / (1 + d) + p.vel.x += norm.x * f * dt + p.vel.y += norm.y * f * dt + } +} + +export function aabb_point_distance( + min_x: number, + min_y: number, + max_x: number, + max_y: number, + px: number, + py: number +): number { + const dx = px - Math.max(min_x, Math.min(max_x, px)) + const dy = py - Math.max(min_y, Math.min(max_y, py)) + return Math.sqrt(dx * dx + dy * dy) +} |