cohost/html/blowing-in-the-wind.tsx

239 lines
7.5 KiB
TypeScript
Raw Normal View History

2023-09-02 21:25:27 -04:00
import { Main, n_of, pick_random, render_and_copy } from "./common.tsx";
2023-09-02 21:08:44 -04:00
// ⾋ is grass which is neat
// meh, this seems to be the least worst option
// random ascii rocks and bunnies and such might be neat but would
// be total possible actually so i'm going to do that now
const grass_chars = ".,'`".split("");
// const grass_chars = ["^", '"', "'", ";", ":", "*", "+", "~"];
// authentic colors are kind of ugly
const grass_colors = ["#9DDA33", "#10F565"];
// const grass_colors = ["#136D15", "#117C13", "#138510", "#268B07", "#41980A"];
2023-09-02 21:25:27 -04:00
// i want to keep this minimal (i want to have a lot of grass :])
// b works nicely i think
// generally kinda doubting if the ascii look jives with the rest of the idea
// looks terrible when synchronized obviously lol
// i'm going to need to be smarter and consider the position but that's going
// to be a lot more difficult
// i should really have more randomness utilities
const blade_delay = (x: number, y: number): number => {
const t = x + y;
return t + (Math.random() - 0.5) * 1.5;
// return Math.sin(t / 3) < 0 ? 3 * Math.sin(t) : Math.sin(t) / 4;
// const den = 3;
// return (
// (Math.sin(t / den) < 0 && Math.sin(t) < 0
// ? Math.sin(t) / den
// : Math.sin(t)) +
// (Math.random() - 0.5) * 1.5
// );
};
// truncing floats a bit could save a lot of bytes but eh
// should be a util obviously
// toFixed is sufficient for css stuff methinks
// you know it's a good css crime when using toFixed saves multiple kilobytes
const Blade = ({ x, y }: { x: number; y: number }) => (
2023-09-02 21:25:27 -04:00
<b
style={{
// transformOrigin: "bottom",
// transform: "translateX(0.5rem)",
2023-09-02 23:18:27 -04:00
animation: "spin infinite ease-in-out alternate",
transform: "translateX(0.5rem)",
2023-09-02 23:18:27 -04:00
// putting math knowledge to work :D
animationDelay: `${blade_delay(x, y).toFixed(2)}s`,
2023-09-02 23:18:27 -04:00
// having some randomness with the duration is a great idea!!
// maybe not with things being synchronized though!
// animationDuration: `${2.5 + Math.random() * 0}s`,
animationDuration: "6.5s",
2023-09-02 23:18:27 -04:00
color: pick_random(grass_colors),
// helps the squareness
overflow: "hidden",
2023-09-02 21:25:27 -04:00
}}
>
{pick_random(grass_chars)}
</b>
);
2023-09-02 21:08:44 -04:00
2023-09-03 08:08:24 -04:00
// ☺ is too inconsistently rendered i think
// i can't NOT have it come on
const statics = "r•gbpM☺".split("");
2023-09-03 08:08:24 -04:00
const static_colors: Record<string, string[]> = {
r: ["rgb(215, 155, 45)"],
// turns out df has a lot of rocks
// there are repeated colors but that should be good for recreating the general distribution
"•": [
"rgb(255, 255, 255)",
"rgb(215, 155, 45)",
"rgb(160, 160, 160)",
"rgb(215, 155, 45)",
"rgb(255, 255, 255)",
"rgb(255, 255, 255)",
"rgb(215, 155, 45)",
"rgb(255, 255, 255)",
"rgb(215, 155, 45)",
"rgb(160, 160, 160)",
"rgb(215, 155, 45)",
"rgb(160, 160, 160)",
"rgb(160, 160, 160)",
"rgb(192, 192, 192)",
"rgb(160, 160, 160)",
"rgb(160, 160, 160)",
"rgb(192, 192, 192)",
"rgb(160, 160, 160)",
"rgb(160, 160, 160)",
"rgb(192, 192, 192)",
"rgb(255, 255, 255)",
"rgb(192, 192, 192)",
"rgb(255, 255, 255)",
"rgb(215, 155, 45)",
"rgb(160, 160, 160)",
],
g: ["white"],
b: [
"rgb(160, 160, 160)",
"rgb(192, 192, 192)",
"rgb(192, 192, 192)",
"rgb(215, 155, 45)",
"rgb(215, 155, 45)",
"rgb(255, 17, 58)",
"rgb(140, 102, 255)",
"rgb(215, 155, 45)",
"rgb(215, 155, 45)",
"rgb(160, 160, 160)",
"rgb(215, 155, 45)",
"rgb(160, 160, 160)",
"rgb(160, 160, 160)",
"rgb(160, 160, 160)",
"rgb(255, 255, 255)",
"rgb(255, 255, 255)",
"rgb(255, 113, 17)",
"rgb(167, 60, 213)",
"rgb(215, 155, 45)",
"rgb(215, 155, 45)",
"rgb(160, 160, 160)",
"rgb(160, 160, 160)",
"rgb(162, 220, 52)",
],
p: [
"rgb(140, 102, 255)",
"rgb(232, 17, 255)",
"rgb(140, 102, 255)",
"rgb(192, 192, 192)",
"rgb(192, 192, 192)",
"rgb(215, 155, 45)",
"rgb(215, 155, 45)",
"rgb(19, 253, 101)",
"rgb(215, 155, 45)",
"rgb(215, 155, 45)",
"rgb(232, 17, 255)",
"rgb(215, 155, 45)",
"rgb(215, 155, 45)",
"rgb(255, 17, 58)",
"rgb(255, 17, 58)",
"rgb(140, 102, 255)",
"rgb(255, 255, 255)",
"rgb(140, 102, 255)",
"rgb(160, 160, 160)",
"rgb(255, 255, 255)",
"rgb(215, 155, 45)",
"rgb(215, 155, 45)",
"rgb(160, 160, 160)",
"rgb(160, 160, 160)",
],
M: [
"rgb(192, 192, 192)",
"rgb(215, 155, 45)",
"rgb(18, 254, 207)",
"rgb(192, 192, 192)",
"rgb(160, 160, 160)",
"rgb(140, 102, 255)",
"rgb(19, 253, 101)",
"rgb(192, 192, 192)",
"rgb(215, 155, 45)",
"rgb(215, 155, 45)",
"rgb(160, 160, 160)",
"rgb(215, 155, 45)",
"rgb(215, 155, 45)",
"rgb(192, 192, 192)",
"rgb(160, 160, 160)",
"rgb(215, 155, 45)",
"rgb(215, 155, 45)",
"rgb(215, 155, 45)",
"rgb(215, 155, 45)",
"rgb(215, 155, 45)",
"rgb(215, 155, 45)",
"rgb(232, 17, 255)",
"rgb(255, 17, 58)",
"rgb(255, 113, 17)",
"rgb(160, 160, 160)",
"rgb(160, 160, 160)",
"rgb(255, 113, 17)",
"rgb(255, 113, 17)",
"rgb(215, 155, 45)",
"rgb(215, 155, 45)",
"rgb(160, 160, 160)",
"rgb(18, 254, 207)",
"rgb(160, 160, 160)",
],
"☺": ["grey", "rgb(113, 187, 176)"],
2023-09-03 08:08:24 -04:00
};
const StaticGuy = () => {
const stat = pick_random(statics);
return (
<b
style={{
overflow: "hidden",
color: pick_random(static_colors[stat]),
}}
>
{stat}
</b>
);
};
2023-09-02 21:08:44 -04:00
const Field = ({ width }: { width: number }) => (
<div
style={{
width: "100%",
aspectRatio: "1",
display: "grid",
2023-09-02 21:25:27 -04:00
gridTemplateRows: `repeat(${width}, 1fr)`,
gridTemplateColumns: `repeat(${width}, 1fr)`,
2023-09-03 08:08:24 -04:00
// what dfwiki uses
fontFamily:
'"Courier New", "Quicktype Mono", "Bitstream Vera Sans Mono", "Lucida Console", "Lucida Sans Typewriter", monospace',
// brown doesn't really work because the grass isn't dense enough
// maybe a complete dfivorce isn't in order
2023-09-02 21:25:27 -04:00
backgroundColor: "black",
2023-09-02 23:18:27 -04:00
fontWeight: "bolder",
fontSize: "1.1rem",
2023-09-03 08:08:24 -04:00
// shweet
lineHeight: "100%",
2023-09-02 21:08:44 -04:00
}}
2023-09-02 21:25:27 -04:00
>
2023-09-03 08:08:24 -04:00
{new Array(width * width)
.fill(undefined)
.map((_, i) =>
Math.random() < 0.05 ? (
<StaticGuy />
) : (
<Blade x={i % width} y={Math.floor(i / width)} />
)
)}
2023-09-02 21:25:27 -04:00
</div>
2023-09-02 21:08:44 -04:00
);
// it's funny how the whole idea was to emulate waves of grass but then i just
// didn't do that because it's hawd :[
// okay, seeing how pretty the waves in the wrapped text of the source are has
// inspired me. i'm going to work on this tomorrow and do the hawd thing (waves)
// adding more grass doesn't really help and mainly just causes size problems
2023-09-03 08:08:24 -04:00
// takes some shuffling to get a nice distribution of statics
render_and_copy(<Field width={30} />);