JSFiddle - React, Tailwind, and code Playground

by teaearlgraycold

HTML

<div id="pusher"></div>
<div id="ball"></div>
<div id="score">Score: 0</div>

CSS

#ball {
    position: fixed;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background-color: black;
}

#score {
    position: fixed;
    top: 0;
    width: 12rem;
    left: 50%;
    margin-left: -6rem;
    margin-top: 1rem;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 2rem;
}

JavaScript

requestAnimationFrame(main_loop);

/**
 * If a position is to the right of the scrollbar.
 */
const past_scrollbar = ({x, y}) => (x > document.documentElement.clientWidth);

/**
 * If a position is on (or past) the scroll bar.
 */
const touching_scrollbar = ({x, y}) => {
    const on_right_edge = (x + ball_diameter >= document.documentElement.clientWidth);
    const in_line_with_scrollbar = (y >= scrollbar_pos()) && (y < scrollbar_pos() + scrollbar_height());

    return on_right_edge && in_line_with_scrollbar;
};

/**
 * Approximate size of the scrollbar in pixels.
 */
const scrollbar_height = () => {
    const view_height = document.documentElement.clientHeight;
    const page_height = document.documentElement.scrollHeight;
    const view_proportion = view_height / page_height;

    return view_height * view_proportion;
};

/**
 * How far scrolled down the page the view is in pixels.
 */
const scrollbar_pos = () => {
    const view_height = document.documentElement.clientHeight;
    const page_height = document.documentElement.scrollHeight;
    const scroll_position = document.scrollingElement.scrollTop;

    return view_height * scroll_position / page_height;
};

const rand_int = (min, max) => Math.floor((Math.random() * (max - min)) + min);
const rand_float = (min, max) => (Math.random() * (max - min)) + min;


const pusher = document.getElementById("pusher");
const scoreboard = document.getElementById("score");
const ball = document.getElementById("ball");

// Ball state
const ball_diameter = 30;
let ball_position = { x: 15, y: 15 };
let ball_velocity = { x: rand_int(250, 350), y: rand_int(250, 350) };

// Bar state
let bar_velocity = 0;
let last_bar_position = document.scrollingElement.scrollTop;

// Game state
let last_timestamp = null;
let score = 0;

function main_loop(timestamp) {
    if (!last_timestamp) {
        last_timestamp = timestamp;
        requestAnimationFrame(main_loop);
        return;
    }

    if (past_scrollbar(ball_position)) {
      ...