Aim, follow and shake the camera, and light and color the scene.
A Camera has mutable eye and target tuples and a vertical fov in radians. ortho (half the visible height in world units) makes it orthographic and overrides fov.
Mutate the object from onUpdate; GameView reads it every frame. Keep a tiny offset for straight-down views so eye and target never align vertically.
Two cameras
React and React Native · shared engine API
import type { Camera } from "@nayan-ui/engine";export const perspective: Camera = { eye: [8, 6, 12], target: [0, 1, 0], fov: Math.PI / 3 };export const board: Camera = { eye: [0, 20, 0.01], target: [0, 0, 0], fov: 1, ortho: 6 };export function orbit(camera: Camera, time: number) {camera.eye[0] = Math.sin(time) * 12;camera.eye[2] = Math.cos(time) * 12;}
camera.follow = { target, offset, smoothing? } eases the target toward the entity's drawn position and keeps the eye at offset. smoothing is roughly the catch-up time in seconds (default 0.15, 0 is rigid); null returns control.
camera.shake is a strength in world units that fades by itself.
Chase and hit feedback
React and React Native · shared engine API
import type { Camera, Entity } from "@nayan-ui/engine";export function chase(camera: Camera, player: Entity) {camera.follow = { target: player, offset: [0, 4, 7], smoothing: 0.12 };}export function onHit(camera: Camera) {camera.shake = 0.3;}export function release(camera: Camera) {camera.follow = null;}
One directional light with ambient fill and a shadow map centred on the camera target. A small shadowExtent clips distant shadows; a large one blurs them.
| Light field | Behavior |
|---|---|
| direction | Toward the light; need not be normalized. |
| ambient | 0..1 ambient term. |
| color | CSS or tuple multiplying sun and ambient; glowing colors unaffected. |
| shadows | Cast shadows; default true. |
| shadowExtent | Half-size of the shadowed area in world units; default 30. |
Moonlit scene
React and React Native · shared engine API
import { GameView, type Light, type World } from "@nayan-ui/engine";const moon: Light = { direction: [-0.5, 0.8, 0.3], ambient: 0.3, color: "#5A61A0", shadowExtent: 24 };export function Night({ world }: { world: World }) {return <GameView source={world} light={moon} background="#0B1020" style={{ flex: 1 }} />;}
background is the clear color (CSS or tuple, alpha ignored; default dark navy) and also the fog color. fog is the density toward it, such as 0.02; default 0.
Hazy horizon
React and React Native · shared engine API
import { GameView, type World } from "@nayan-ui/engine";export function Haze({ world }: { world: World }) {return <GameView source={world} background="rgb(200, 215, 230)" fog={0.03} style={{ flex: 1 }} />;}
frontLight(direction, ambient) lights camera-facing surfaces at exactly 1, so flat tiles show their exact theme color while rounded shapes keep shading. It turns shadows off; pair it with a camera looking down -z.
Puzzle board
React and React Native · shared engine API
import { GameView, frontLight, type World } from "@nayan-ui/engine";const light = frontLight([-0.45, 0.6, 1], 0.5);export function Board({ world }: { world: World }) {return (<GameView source={world} light={light} background="#F4F1EA" style={{ flex: 1 }}camera={{ eye: [0, 0, 50], target: [0, 0, 0], fov: 1, ortho: 10 }} />);}
Every color option takes '#RGB', '#RGBA', '#RRGGBB', '#RRGGBBAA', 'rgb(…)', 'rgba(…)', a name (transparent, black, white, red, green, blue, yellow, orange, purple, gray, grey) or a 0..1 tuple. Tuple channels above 1 glow, and at 2 ignore light and shadow.
toColor(color, alpha?) returns the [r, g, b, a] tuple, for when you need the numbers. Unknown strings throw.
Brighten a theme color
React and React Native · shared engine API
import { toColor, type World } from "@nayan-ui/engine";const [r, g, b] = toColor("#FF4757");export const ember = [r * 2, g * 2, b * 2] as const; // self-lit glowexport const ghost = toColor("#FF4757", 0.4); // see-throughexport function addLamp(world: World) {return world.spawn({ mesh: "sphere", color: ember, position: [0, 3, 0] });}