the character is stuck in the air:

import React, { useState, useEffect, useRef } from "react";

// Constants for gravity and jumping
const GRAVITY = 0.5;
const JUMP_STRENGTH = -10; // Negative because the Y axis is downward

const Platform = ({ width, height, top, left }) => {
  const style = {
    position: "absolute",
    width: `${width}px`,
    height: `${height}px`,
    backgroundColor: "brown",
    left: `${left}px`,
    top: `${top}px`,
  };

  return <div style={style} />;
};

const Player = ({ position }) => {
  const style = {
    position: "absolute",
    width: "50px",
    height: "50px",
    backgroundColor: "blue",
    left: `${position.x}px`,
    top: `${position.y}px`,
  };

  return <div style={style} />;
};

function GameMain() {
  const [playerPosition, setPlayerPosition] = useState({ x: 100, y: 100 });
  const [playerVelocity, setPlayerVelocity] = useState({ x: 0, y: 0 });
  const [isGrounded, setIsGrounded] = useState(false);
  const requestRef = useRef<number | null>(null);
  const lastTimeRef = useRef(0);
  const playerPositionRef = useRef({ x: 100, y: 100 });
  const playerVelocityRef = useRef({ x: 0, y: 0 });
  
  // Platform
  const platform = {
    width: 400,
    height: 20,
    top: 450,
    left: 100,
  };

  const checkCollisionWithPlatform = (newPosition) => {
    const playerFoot = newPosition.y + 50;
    if (playerFoot < platform.top) return false;
  
    const withinPlatformXBounds =
      newPosition.x < (platform.left + platform.width) &&
      (newPosition.x + 50) > platform.left;
  
    const fallingOntoPlatform = playerFoot >= platform.top && playerVelocityRef.current.y >= 0;
  
    return withinPlatformXBounds && fallingOntoPlatform;
  };
  
  const handleKeyPress = (event) => {
    if (event.key === "ArrowRight") {
      // Increment horizontal position
      setPlayerPosition((prev) => ({ ...prev, x: prev.x + 5 }));
    } else if (event.key === "ArrowLeft") {
      // Decrement horizontal position
      setPlayerPosition((prev) => ({ ...prev, x: prev.x - 5 }));
    } else if (event.key === "ArrowUp" && isGrounded) {
      // Set vertical velocity for jump only if player is grounded
      setPlayerVelocity((prev) => ({ ...prev, y: JUMP_STRENGTH }));
      setIsGrounded(false);
    }
  };
  
  useEffect(() => {
    window.addEventListener("keydown", handleKeyPress);
    return () => window.removeEventListener("keydown", handleKeyPress);
  }, [isGrounded]); // Adding isGrounded as a dependency ensures that the states are updated correctly.
  
  useEffect(() => {
    playerPositionRef.current = playerPosition;
    playerVelocityRef.current = playerVelocity;
  });
  
  const updateGame = (time) => {
    const deltaTime = (time - lastTimeRef.current) / 1000;
    lastTimeRef.current = time;
    
    // Calculate new velocity and position based on gravity
    let newVelocity = {
      x: playerVelocityRef.current.x,
      y: (!isGrounded ? playerVelocityRef.current.y + GRAVITY * deltaTime : 0)
    };
    
    let newPosition = {
      x: playerPositionRef.current.x + newVelocity.x * deltaTime,
      y: (!isGrounded ? playerPositionRef.current.y + newVelocity.y * deltaTime : playerPositionRef.current.y)
    };
    
    // If the player is not grounded and colliding with the platform, adjust their position and velocity
    if (!isGrounded && checkCollisionWithPlatform(newPosition)) {
      newPosition.y = platform.top - 50; // Adjust player to be on top of the platform
      newVelocity.y = 0; // Stop the vertical velocity as the player has landed
      setIsGrounded(true);
    }
    
    // Update player position and velocity
    setPlayerPosition(newPosition);
    setPlayerVelocity(newVelocity);
  
    // Continue the game loop
    requestRef.current = requestAnimationFrame(updateGame);
  };
    return (
      <div style={{ position: "relative", width: "100%", height: "100%" }}>
        <img src="assets/Grassy_Mountains_preview_fullcolor.png" style={{ width: "100%" }} alt="Background" />
        <Player position={playerPosition} />
        <Platform {...platform} />
      </div>
    );
  }

export default GameMain;