## Navigator Usage Examples

The `Navigator` component allows objects to move over terrain surfaces with automatic height adjustment.

> **Note:** When `terrainData` is not provided, Navigator will use the `heightOffset` value (default is 2.5) as the y-position. This is useful when working with environments that don't use terrain data, such as when using the Stage component.

### Moving Object Example

```jsx
import React, { useState, useRef, useEffect } from 'react';
import { Navigator } from 'vibe-starter-3d-environment';
import { Vector3, Group } from 'three';
import { useFrame } from '@react-three/fiber';
import { Sphere } from '@react-three/drei';

interface StandardMovingObjectProps {
  terrainData?: TerrainData | null;
  waterLevel: number;
  radius?: number;
  speed?: number;
  heightOffset?: number;
  color?: string;
}

const StandardMovingObject: React.FC<StandardMovingObjectProps> = ({
  terrainData,
  waterLevel,
  radius = 50,
  speed = 0.2,
  heightOffset = 0,
  color = 'red',
}) => {
  // Update instance key when terrain data changes to create a new instance
  const [instanceKey, setInstanceKey] = useState(0);
  // Current position (Vector3)
  const [currentPosition, setCurrentPosition] = useState(
    () => new Vector3(radius, waterLevel + heightOffset, 0)
  );

  // Reference to group object
  const groupRef = useRef<Group>(null);
  // Rotation angle
  const angleRef = useRef(0);

  // Reset when terrainData or other key props change
  useEffect(() => {
    // Update instance key to create new TerrainNavigator instance
    setInstanceKey((prev) => prev + 1);

    // Set initial position (starting point of circle)
    const initialX = radius;
    const initialZ = 0;
    setCurrentPosition(
      new Vector3(initialX, waterLevel + heightOffset, initialZ)
    );
  }, [terrainData, radius, waterLevel, heightOffset]);

  // Update object position along circular path every frame
  useFrame((state, delta) => {
    // Update angle
    angleRef.current += speed * delta;

    // Calculate new x, z coordinates for circular path
    const newX = Math.cos(angleRef.current) * radius;
    const newZ = Math.sin(angleRef.current) * radius;

    // Update current position (y is calculated by Navigator)
    setCurrentPosition((prev) => new Vector3(newX, prev.y, newZ));
  });

  // Handle height updates calculated by Navigator
  const handleHeightUpdate = (updatedPosition: Vector3) => {
    // Update height of current position
    setCurrentPosition(
      (prev) => new Vector3(prev.x, updatedPosition.y, prev.z)
    );
  };

  return (
    <group ref={groupRef}>
      <Navigator
        key={`terrain-navigator-${instanceKey}`}
        terrainData={terrainData}
        heightOffset={heightOffset}
        onUpdate={(position) => handleHeightUpdate(position as Vector3)}
        targetPosition={[
          currentPosition.x,
          currentPosition.y,
          currentPosition.z,
        ]}
      >
        <Sphere args={[1.5, 32, 32]} castShadow receiveShadow>
          <meshStandardMaterial color={color} roughness={0.4} metalness={0.6} />
        </Sphere>
      </Navigator>
    </group>
  );
};

export default StandardMovingObject;
```

> **Note:** This example demonstrates a circular path movement, but this is just one example of possible movement patterns. You can implement any type of movement by updating the `targetPosition` in `useFrame` or other reactive hooks. The Navigator component will automatically calculate the correct height based on the terrain data.

### Using Navigator with Stage Component

```jsx
import React, { useState, useRef } from 'react';
import { Navigator } from 'vibe-starter-3d-environment';
import { Stage } from 'vibe-starter-3d-environment';
import { Vector3, Group } from 'three';
import { useFrame } from '@react-three/fiber';
import { Sphere } from '@react-three/drei';

const MovingObjectInStage = () => {
  // Current position state
  const [currentPosition, setCurrentPosition] = useState(new Vector3(0, 5, 0));
  // Reference to track angle for circular motion
  const angleRef = useRef(0);
  // Reference to group object
  const groupRef = useRef<Group>(null);

  // Motion parameters
  const radius = 30;
  const speed = 0.3;
  const heightOffset = 7; // Fixed height when no terrain data

  // Update position every frame
  useFrame((state, delta) => {
    // Update angle
    angleRef.current += speed * delta;

    // Calculate new x, z coordinates for circular path
    const newX = Math.cos(angleRef.current) * radius;
    const newZ = Math.sin(angleRef.current) * radius;

    // Update current position (y will be managed by Navigator)
    setCurrentPosition(prev => new Vector3(newX, prev.y, newZ));
  });

  // Handle position updates from Navigator
  const handlePositionUpdate = (updatedPosition: Vector3) => {
    // Update height of current position
    setCurrentPosition(prev => new Vector3(prev.x, updatedPosition.y, prev.z));
  };

  return (
    <>
      {/* Stage component creates a non-terrain environment */}
      <Stage seed="my-stage" size={200} />

      {/* Navigator without terrainData uses heightOffset for constant height */}
      <group ref={groupRef}>
        <Navigator
          onUpdate={handlePositionUpdate}
          targetPosition={[currentPosition.x, currentPosition.y, currentPosition.z]}
          heightOffset={heightOffset}
        >
          <Sphere args={[1.5, 32, 32]} castShadow>
            <meshStandardMaterial color="purple" roughness={0.4} metalness={0.6} />
          </Sphere>
        </Navigator>
      </group>
    </>
  );
};
```

> **Note:** The circular movement pattern shown in these examples is just for demonstration. You can implement any movement pattern you want by updating the target position coordinates. The Navigator component takes care of calculating the proper height based on terrain or using a fixed height offset.
