title: How to create JS Canvas Top Down Rain Effect or Reverse Warp Speed
body: <p>I am trying to figure out how to create a canvas rain effect, but from the top down perspective. Basically it's like you are looking down at the ground and you are watching the rain fall around you and fall slightly to the center at an angle, but it falls a short distance before ending. I am not seeing anything in searches except some game development that isn't canvas.</p>
  <p>I am also looking for a solution that doesn't require an external library.</p>
  <p>I have been able to modify some warp speed effect code to reverse the direction on the particles to fall to the background instead of off screen, but it is continuing to infinity toward the center and not redrawing or looping the particles that are coming from off screen.</p>
  <p>I think it has something to do with the particles not dropping off screen in this part of the code. Am I on the right track here or can I not accomplish this effect with the current code?</p>
  <pre><code>clear();
  
    const cx = w / 2;
    const cy = h / 2;
  
    const count = stars.length;
    for (var i = 0; i &lt; count; i++) {
      const star = stars[i];
  
      const x = cx + star.x / (star.z * 0.001);
      const y = cy + star.y / (star.z * 0.001);
  
      if (x &lt; 0 || x &gt;= w || y &lt; 0 || y &gt;= h) {
        continue;
      }
  
      const d = star.z / 1000.0;
      const b = 1000 - d * d;
  
      putPixel(x, y, b);
    }
  </code></pre>
  <p>Here is the full code that I am looking at. Any help would be appreciated trying to figure this out.</p>
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>const canvas = document.getElementById("canvas");
  const c = canvas.getContext("2d");
  
  let w;
  let h;
  
  const setCanvasExtents = () =&gt; {
    w = document.body.clientWidth;
    h = document.body.clientHeight;
    canvas.width = w;
    canvas.height = h;
  };
  
  setCanvasExtents();
  
  window.onresize = () =&gt; {
    setCanvasExtents();
  };
  
  const makeStars = count =&gt; {
    const out = [];
    for (let i = 0; i &lt; count; i++) {
      const s = {
        x: Math.random() * 1600 - 800,
        y: Math.random() * 900 - 450,
        z: Math.random() * 1000
      };
      out.push(s);
    }
    return out;
  };
  
  let stars = makeStars(1000);
  
  const clear = () =&gt; {
    c.fillStyle = "black";
    c.fillRect(0, 0, canvas.width, canvas.height);
  };
  
  const putPixel = (x, y, brightness) =&gt; {
    const intensity = brightness * 255;
    const rgb = "rgb(" + intensity + "," + intensity + "," + intensity + ")";
    c.fillStyle = rgb;
    c.fillRect(x, y, 5, 5);
  };
  
  const moveStars = distance =&gt; {
    const count = stars.length;
    for (var i = 0; i &lt; count; i++) {
      const s = stars[i];
      s.z += distance;
      while (s.z &lt;= 1) {
        s.z -= 10;
      }
    }
  };
  
  let prevTime;
  const init = time =&gt; {
    prevTime = time;
    requestAnimationFrame(tick);
  };
  
  const tick = time =&gt; {
    let elapsed = time - prevTime;
    prevTime = time;
  
    moveStars(elapsed * 1.5);
  
    clear();
  
    const cx = w / 2;
    const cy = h / 2;
  
    const count = stars.length;
    for (var i = 0; i &lt; count; i++) {
      const star = stars[i];
  
      const x = cx + star.x / (star.z * 0.001);
      const y = cy + star.y / (star.z * 0.001);
  
      if (x &lt; 0 || x &gt;= w || y &lt; 0 || y &gt;= h) {
        continue;
      }
  
      const d = star.z / 1000.0;
      const b = 1000 - d * d;
  
      putPixel(x, y, b);
    }
  
    requestAnimationFrame(tick);
  };
  
  requestAnimationFrame(init);</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>body {
    position: fixed;
    left: 0px;
    right: 0px;
    top: 0px;
    bottom: 0px;
    overflow: hidden;
    margin: 0;
    padding: 0;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;canvas id="canvas" style="width: 100%; height: 100%; padding: 0;margin: 0;"&gt;&lt;/canvas&gt;</code></pre>
  </div>
  </div>
  </p>