Canvas tap
useCanvasTap reports each tap on the scene as a ray in world space and the target your game finds on it. It suits a game with no player character, such as a farm or a city builder under the map camera, where a tap selects a tree or sends a worker. For the thumb button beside the joystick, see Tap.
You pass two functions:
findTarget(ray)returns your target under the ray, or nothing. Read your own layout, such as the plot nearest where the ray meets the ground, or callfindEntityUnderRayto take the nearest entity by what it draws.onTap({ ray, target, event })runs on each tap.targetis null on a tap on nothing, where a game usually clears its selection.eventis the release, for its pointer type.
What counts as a tap
Section titled “What counts as a tap”A tap is a still, short press of one pointer that went down on the canvas: a mouse’s left button, a finger or a pen. The following presses are no tap:
- A press that travels more than 4 pixels from where it went down, at any moment, so a drag that comes back is still a drag. The map camera pans past the same 4 pixels, so a pan never taps.
maxTravelPixelschanges the limit. - A press held longer than 0.4 seconds.
maxHoldSecondschanges the limit. - A press on the HUD over the canvas, such as a button or a panel.
- A pinch: a second finger cancels the press, as does the browser taking the touch to scroll.
- A press while the cursor is captured, whose position stands still.
The hook hears a release the map camera captured, and a release off the canvas.
A character on the page
Section titled “A character on the page”Where a game also has a character that walks to a click, a tap that found a target keeps the character still: the hook claims the click, as registerClickClaim does. A tap on nothing leaves the click to the walk. findTarget runs once a tap, so onTap may remove the target it was given.
Sample
Section titled “Sample”Mount the component inside the scene’s <Views>, since a room has no canvas to tap. A tap takes the near crate of two that stand in line:
import { createQuery, defineTrait, findEntityUnderRay, RefTrait, useCanvasTap, useWorld,} from "@spawnite/engine";import type { Entity } from "@spawnite/engine/core";
export const CrateTrait = defineTrait("crate", { opened: false });
const crates = createQuery(CrateTrait, RefTrait);
interface CrateTapsProps { /** The crate tapped, or null for a tap on nothing. */ onSelect: (crate: Entity | null) => void;}
// Mount it inside the scene's <Views>, which a room skips, as <MapCamera />// is. A tap takes the crate it lands on, the nearest of two in line.export function CrateTaps({ onSelect }: CrateTapsProps) { const world = useWorld(); useCanvasTap({ findTarget: (ray) => findEntityUnderRay(world, ray, { query: crates }), onTap: ({ target }) => onSelect(target), }); return null;}Its options are in CanvasTapOptions.