"use client"; import { type PointerEvent, useEffect, useRef, useState } from "react"; import { alavanca } from "@/lib/jogo/alavanca"; import type { ArmaId } from "@/lib/jogo/tipos"; import type { Controle } from "./contrato"; import { TOQUE_ATIRAR, TOQUE_BOTAO, TOQUE_DIREITA, TOQUE_EMBAIXO, TOQUE_ESPACO, } from "./medidas"; const RAIO = 56; const MIRA = 0.005; const FACA: ArmaId = 2; // right/bottom e tamanhos dos botões vêm de ./medidas, que o Hud também lê. /** "tiro" é o dedo no botão Atirar: segura o tiro e também mira. */ type Dedo = { papel: "mover" | "mirar" | "tiro"; x: number; y: number }; type Direcional = { x: number; y: number; kx: number; ky: number }; const BOTAO = "pointer-events-auto flex min-w-14 flex-col items-center justify-center border bg-[color:var(--ink)]/30 px-3 font-[family-name:var(--font-mono)] text-[13px] leading-tight tracking-[0.02em] text-[color:var(--paper)] select-none"; export function Toque({ controle, arma, municao, mirando, }: { controle: Controle; arma: ArmaId; municao: number; mirando: boolean; }) { const dedos = useRef(new Map()); const apertado = useRef(false); const automatico = useRef(false); const [direcional, setDirecional] = useState(null); useEffect(() => { automatico.current = mirando && arma !== FACA; controle.definirAtirar(apertado.current || automatico.current); }, [controle, mirando, arma]); function aoApertar(e: PointerEvent) { const papel = (e.target as HTMLElement).closest("[data-papel]") ?.dataset.papel; if (papel === "arma") return; const { clientX: x, clientY: y, pointerId } = e; if (papel === "atirar") { apertado.current = true; controle.definirAtirar(true); dedos.current.set(pointerId, { papel: "tiro", x, y }); return; } const lado = x < window.innerWidth / 2 ? "mover" : "mirar"; const ocupado = [...dedos.current.values()].some((d) => d.papel === lado); if (ocupado) return; dedos.current.set(pointerId, { papel: lado, x, y }); if (lado === "mover") setDirecional({ x, y, kx: 0, ky: 0 }); } function aoMover(e: PointerEvent) { const dedo = dedos.current.get(e.pointerId); if (!dedo) return; const dx = e.clientX - dedo.x; const dy = e.clientY - dedo.y; if (dedo.papel !== "mover") { controle.somarOlhar(-dx * MIRA, -dy * MIRA); dedo.x = e.clientX; dedo.y = e.clientY; return; } const [direita, frente] = alavanca(dx, dy, RAIO); controle.definirMover(direita, frente); setDirecional({ x: dedo.x, y: dedo.y, kx: direita * RAIO, ky: -frente * RAIO, }); } function aoSoltar(e: PointerEvent) { const dedo = dedos.current.get(e.pointerId); if (!dedo) return; dedos.current.delete(e.pointerId); if (dedo.papel === "tiro") { apertado.current = false; controle.definirAtirar(automatico.current); } if (dedo.papel === "mover") { controle.definirMover(0, 0); setDirecional(null); } } const armas: { id: ArmaId; nome: string }[] = [ { id: 0, nome: "Pistola" }, { id: 1, nome: "Automática" }, { id: 2, nome: "Faca" }, ]; return (
e.preventDefault()} > {direcional && (
)}
{armas.map(({ id, nome }) => ( ))}
); }