summaryrefslogtreecommitdiff
path: root/scripts/script.js
blob: b3efd73e88072ebde66fa3661bdff24a047765ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
const IMGS = [
  "/img/rains/arch.png",
  "/img/rains/bmo.png",
  "/img/rains/cat.gif",
  "/img/rains/demi.png",
  "/img/rains/dnd.png",
  "/img/rains/eattherich.png",
  "/img/rains/gloomhaven.png",
  "/img/rains/iron_throne.png",
  "/img/rains/link.png",
  "/img/rains/meddle.jpeg",
  "/img/rains/moon.png",
  "/img/rains/note.png",
  "/img/rains/obsidian.png",
  "/img/rains/outerwilds.png",
  "/img/rains/piano.png",
  "/img/rains/pirate.svg",
  "/img/rains/ror.png",
  "/img/rains/smashball.svg",
  "/img/rains/ssa.png",
  "/img/rains/svelte.png",
  "/img/rains/usu.png",
];

const DROPLETS = 8;
const DROPLET_WIDTH_RANGE = [80, 120];
const DROPLET_DY_RANGE = [0.1, 0.4];
const DROPLET_DTHETA_RANGE = [-0.25, 0.25];
const DROPLET_INIT_THETA_RANGE = [-180, 180];

const makeDroplet = (src, width, x, y, theta, dtheta, dy) => {
  const img = document.createElement("img");
  img.style.position = "absolute";
  img.style.width = `${width}px`;
  img.src = src;
  document.body.appendChild(img);

  return {
    img,
    width,
    theta,
    pos: { x, y },
    vel: { dy, dtheta },
  };
};

const randBetween = (min, max) => Math.random() * (max - min) + min;

const update = (droplets, dt, boundedY) =>
  droplets
    .map((droplet) => {
      return {
        ...droplet,
        pos: { ...droplet.pos, y: droplet.pos.y + droplet.vel.dy * dt },
        theta: droplet.theta + droplet.vel.dtheta * dt,
      };
    })
    .map((droplet) => {
      const {
        pos: { y },
        img,
      } = droplet;
      if (y >= boundedY) {
        document.body.removeChild(img);
        return null;
      }
      return droplet;
    })
    .filter((x) => x)
    .map((droplet) => {
      const {
        img,
        pos: { x, y },
        theta,
      } = droplet;

      img.style.left = `${x}px`;
      img.style.top = `${y}px`;
      img.style.transform = `rotate(${theta}deg)`;

      return droplet;
    });

const buildRandomDroplet = () =>
  makeDroplet(
    IMGS[Math.floor(randBetween(0, IMGS.length))],
    randBetween(...DROPLET_WIDTH_RANGE),
    randBetween(0, window.innerWidth - DROPLET_WIDTH_RANGE[1]),
    randBetween(-50, window.innerHeight / 8),
    randBetween(...DROPLET_INIT_THETA_RANGE),
    randBetween(...DROPLET_DTHETA_RANGE),
    randBetween(...DROPLET_DY_RANGE),
  );

window.onload = () => {
  // cache 'em
  IMGS.forEach((x) => {
    ((img) => (img.src = x))(new Image());
  });

  let droplets = Array(DROPLETS).fill().map(buildRandomDroplet);

  let lastTimestamp = performance.now();
  const next = (timestamp) => {
    const dt = timestamp - lastTimestamp;
    lastTimestamp = timestamp;

    droplets = update(droplets, dt, window.innerHeight);

    if (droplets.length != DROPLETS) {
      droplets.push(buildRandomDroplet());
    }

    requestAnimationFrame(next);
  };
  requestAnimationFrame(next);
};