O Projeto
Valvecraft é um jogo para trompetistas que querem melhorar dedilhado, leitura de partitura e senso de ritmo de forma interativa. Com amostras de áudio reais e feedback visual em tempo real, o estudo técnico vira uma experiência dinâmica.
Suporta Trompete em Si♭ (padrão) e Trompete em Dó.
Modos de Jogo
Modo Quiz
Você vê uma nota na pauta e precisa identificar e tocar o dedilhado correto nas válvulas.
| Variante | Descrição |
|---|---|
| Desafio | Cronômetro de 60s. Acertos estendem o tempo, erros penalizam. Sistema de streaks com multiplicadores. |
| Treino | Sem tempo, com dicas visuais de dedilhado. Ideal para iniciantes. |
O sistema de streaks premia acertos consecutivos com multiplicadores de pontuação:
| Nível | Acertos | Multiplicador |
|---|---|---|
| Ritmo | 0+ | 1.0x |
| Combo | 5+ | 1.15x |
| Foco | 10+ | 1.3x |
| Blitz | 15+ | 1.5x |
Modo Ritmo
Toque músicas reais em partitura. Um playhead percorre as notas no tempo certo, você precisa pressionar as válvulas corretas no momento exato.
Feedback por nota:
- Perfeito — dedilhado correto no tempo certo
- Dedilhado errado — tempo certo, nota errada
- Miss — janela de tempo perdida
Repertório disponível: escalas maiores, exercícios técnicos e melodias como Ode à Alegria, Amazing Grace, When the Saints, entre outras.
Desafios Técnicos
Renderização de Partituras com VexFlow
O maior desafio foi integrar o VexFlow para renderizar partituras musicais corretamente no React. VexFlow manipula o DOM diretamente via canvas ou SVG, o que conflita com o modelo de reconciliação do React.
1// hooks/useSheetMusic.ts2export function useSheetMusic(containerRef: RefObject<HTMLDivElement>) {3 useEffect(() => {4 if (!containerRef.current) return;56 // VexFlow requer limpeza manual antes de re-renderizar7 containerRef.current.innerHTML = "";89 const renderer = new Renderer(containerRef.current, Renderer.Backends.SVG);10 renderer.resize(600, 150);1112 const context = renderer.getContext();13 const stave = new Stave(10, 10, 580);14 stave.addClef("treble").addTimeSignature("4/4");15 stave.setContext(context).draw();1617 return () => {18 if (containerRef.current) {19 containerRef.current.innerHTML = "";20 }21 };22 }, [note]);23}Engine de Áudio com Tone.js
Para o áudio, usei Tone.js com ToneAudioBuffer carregando amostras reais de trompete por nota. A detecção de timing no Modo Ritmo usa Tone.Transport para sincronizar o playhead com a janela de acerto de cada nota.
1// hooks/useTrumpetAudio.ts2const SAMPLE_MAP: Record<string, string> = {3 C4: "/audio/trumpet/C4.mp3",4 D4: "/audio/trumpet/D4.mp3",5 // ...6};78export function useTrumpetAudio() {9 const samplerRef = useRef<Tone.Sampler | null>(null);1011 useEffect(() => {12 samplerRef.current = new Tone.Sampler(SAMPLE_MAP).toDestination();13 return () => samplerRef.current?.dispose();14 }, []);1516 const playNote = useCallback((note: string) => {17 samplerRef.current?.triggerAttackRelease(note, "8n");18 }, []);1920 return { playNote };21}Mapeamento de Dedilhado
Cada nota do trompete tem um dedilhado específico (combinação de válvulas 1, 2 e 3). O fingeringMap mapeia nota para válvulas e também inclui dedilhados alternativos para notas com múltiplas opções.
1// data/fingeringMap.ts2export const fingeringMap: Record<string, number[][]> = {3 C4: [[0, 0, 0]], // Nota aberta4 D4: [[1, 3, 0]], // Válvulas 1 e 35 E4: [[1, 2, 0]], // Válvulas 1 e 26 F4: [[1, 0, 0]], // Válvula 17 "F#4": [8 [2, 3, 0],9 [1, 2, 3],10 ], // Alternativo: todas as válvulas11 G4: [[0, 0, 0]], // Nota aberta (parcial diferente)12 // ...13};Controles
| Ação | Tecla |
|---|---|
| Válvula 1 | Q |
| Válvula 2 | W |
| Válvula 3 | E |
| 3º slide (afinação) | Shift |
| Confirmar / Nota aberta | Espaço |
Os controles podem ser alterados no menu principal.
O que aprendi
- VexFlow tem uma API imperativa que requer atenção ao ciclo de vida do React: precisei gerenciar limpeza do DOM manualmente nos
useEffect - Tone.js e timing preciso: a janela de detecção de acerto no Modo Ritmo foi a parte mais difícil, sincronizar áudio com animação visual tem latências diferentes
- Sistema de gamificação simples mas eficaz: o multiplier de streaks foi o que mais engajou nos testes, pequenos feedbacks visuais fazem diferença