component

Shore

Sloped beach/shore strip to meet a Lake.

⌖ Explore the library in 3D → · View as Markdown

Tune every prop in the workshop →

Add it

npx @runek/cli add shore

Pulls @react-three/rapier@^2.2.0, @runek/core@^0.15.0.

Use it

import { Shore } from './runek/Shore'

<Shore position={[0, 0, 0]} />

Or as a node in a world file (worlds as data):

{ "type": "Shore", "props": { "position": [0, 0, 0] } }

Props

Prop Type Default Description
position [x, y, z] [0, 0, 0] Position [x, y, z] in units (1 unit = 1 m, Y-up).
rotation [x, y, z] [0, 0, 0] Euler rotation [x, y, z] in radians.
seed number Accepted for the component contract; this component has no seeded variation yet.
size [number, number] [24, 24] [width, depth] in units. The sandy top sits at the component origin.
thickness number 0.3 Thickness, in units.
color color palette sand Defaults to the world palette’s sand slot.

Registry manifest

registry manifest /r/components/shore.json Self-contained JSON: inlined source plus resolved dependencies, exactly what runek add shore fetches.

Browse the whole catalog in the gallery →.

Source (2 files)

Shore.tsx

import { RigidBody } from '@react-three/rapier'
import { useWorld, type Vec3 } from '@runek/core'
import { shoreSurface } from './surfaces/shore'

export interface ShoreProps {
  position?: Vec3
  rotation?: Vec3
  /** Accepted for the component contract; this component has no seeded variation yet. */
  seed?: number
  /** `[width, depth]` in units. The sandy top sits at the component origin. */
  size?: [number, number]
  thickness?: number
  /** Defaults to the world palette's `sand` slot. */
  color?: string
}

export function Shore({
  position = [0, 0, 0],
  rotation = [0, 0, 0],
  size = [24, 24],
  thickness = 0.3,
  color,
}: ShoreProps) {
  const { unit, palette } = useWorld()
  const sandColor = color ?? palette.sand
  const w = size[0] * unit
  const d = size[1] * unit
  const t = thickness * unit

  return (
    <RigidBody type="fixed" colliders="cuboid" position={position} rotation={rotation}>
      <mesh receiveShadow position={[0, -t / 2, 0]}>
        <boxGeometry args={[w, t, d]} />
        <meshStandardMaterial color={sandColor} roughness={1} />
      </mesh>
    </RigidBody>
  )
}

Shore.surface = shoreSurface

surfaces/shore.ts

import type { SurfaceDef } from '@runek/core'

/** Shore's sandy top, a flat band at the origin. */
export const shoreSurface: SurfaceDef = {
  kind: 'terrain',
  build(props, { unit }) {
    const [w, d] = (props.size as [number, number] | undefined) ?? [24, 24]
    return (x, z) => (Math.abs(x) <= (w * unit) / 2 && Math.abs(z) <= (d * unit) / 2 ? 0 : null)
  },
}