Last active
March 15, 2024 20:27
-
-
Save jespertheend/53cddb4a15055d63ab2a9c0585265eda to your computer and use it in GitHub Desktop.
A function that allows you to convert a 2d vector into a single byte and back into a vector. Useful when you want to send player joystick input over the network.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { mod, Vec2 } from "https://cdn.jsdelivr.net/npm/renda@0.3.0/dist/renda.min.js"; | |
const RING_SEGMENTS = 36; | |
const RING_COUNT = 7; | |
// https://www.desmos.com/calculator/zpob0tj445 | |
/** | |
* Normalizes a Vec2 (between -1 and 1) and returns a byte (a value between 0 and 255) | |
* which can be used to turn it back into a Vec2 using {@linkcode byteToVec2d}. | |
* Naturally, a lot of precision is lost when using this operation. | |
* @param {import("$renda").Vec2} vec | |
*/ | |
export function vec2dToByte(vec) { | |
if (vec.magnitude == 0) return 0; | |
const theta = vec.clockwiseAngleTo(new Vec2(-1, 0)); | |
const ba = mod(Math.round(((Math.PI - theta) / (2 * Math.PI)) * RING_SEGMENTS - 1), RING_SEGMENTS) + 1; | |
const bb = Math.round(vec.magnitude * RING_COUNT) * RING_SEGMENTS - RING_SEGMENTS; | |
return ba + bb; | |
} | |
/** | |
* Converts a byte which was generated by {@linkcode vec2dToByte} back into a Vec2. | |
* Naturally, a lot of precision is lost when using this operation. | |
* @param {number} byte | |
*/ | |
export function byteToVec2d(byte) { | |
const radius = Math.floor(((byte - 1) / RING_SEGMENTS) + 1) / RING_COUNT; | |
const theta = byte / RING_SEGMENTS * Math.PI * 2; | |
return new Vec2(Math.cos(theta) * radius, Math.sin(theta) * radius); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { byteToVec2d, vec2dToByte } from "./vec2ToByte.js"; | |
import { assertVecAlmostEquals, Vec2 } from "https://cdn.jsdelivr.net/npm/renda@0.3.0/dist/renda.min.js"; | |
/** | |
* @param {number} byte | |
*/ | |
function assertIsByte(byte) { | |
if (Math.round(byte) != byte) { | |
throw new Error(`${byte} is not an integer`); | |
} | |
if (byte < 0 || byte > 255) { | |
throw new Error(`${byte} is not within the 0-255 range`); | |
} | |
} | |
Deno.test({ | |
name: "Some common vectors stay exactly the same", | |
fn() { | |
const tests = [ | |
new Vec2(), | |
new Vec2(0, 1), | |
new Vec2(0, -1), | |
new Vec2(1, 0), | |
new Vec2(-1, 0), | |
]; | |
for (const test of tests) { | |
const byte = vec2dToByte(test); | |
assertIsByte(byte); | |
const vec = byteToVec2d(byte); | |
assertVecAlmostEquals(vec, test); | |
} | |
}, | |
}); | |
Deno.test({ | |
name: "Other vectors stay roughly the same", | |
fn() { | |
const tests = [ | |
new Vec2(), | |
new Vec2(0, 1), | |
new Vec2(0, -1), | |
new Vec2(1, 0), | |
new Vec2(-1, 0), | |
]; | |
for (const test of tests) { | |
const byte = vec2dToByte(test); | |
assertIsByte(byte); | |
const vec = byteToVec2d(byte); | |
assertVecAlmostEquals(vec, test); | |
} | |
}, | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment