Uma tela ILI9341 de 2,4 polegadas, um D-pad feito de quatro botões de pressão e mais dois botões para A e B: isso é um console portátil, e um ESP32 é mais que suficiente para rodá-lo. Construímos cinco jogos para esse layout, depois um sexto, Skythread, para um portátil maior com um analógico, e colocamos todos os seis na galeria de exemplos do Velxio. Cada um é um sketch Arduino, e cada um roda no seu navegador: aperte Run e jogue, sem placa, sem tela, sem solda.
| Jogo | Placa | Tipo de jogo | Taxa de quadros no Velxio |
|---|---|---|---|
| ESP32 Doom | ESP32 DevKit | tiro em primeira pessoa | cerca de 18 FPS |
| Sky Duel | Seeed XIAO ESP32-S3 | combate aéreo em vista lateral | cerca de 29 FPS |
| XIAO Quest | Seeed XIAO ESP32-S3 | RPG de visão superior | cerca de 32 FPS |
| Gear Hop | Seeed XIAO ESP32-S3 | plataforma de rolagem lateral | cerca de 27 FPS |
| Circuit Defense | Seeed XIAO ESP32-S3 | tower defense | cerca de 31 FPS |
| Skythread | Seeed XIAO ESP32-S3 Sense | voo 3D sobre uma paisagem gerada | cerca de 20 FPS |
O primeiro, Doom, veio primeiro e roda no ESP32 clássico. Os quatro seguintes rodam no Seeed Studio XIAO ESP32-S3, a placa do tamanho de um polegar da nossa parceira Seeed, e compartilham uma pequena engine. O último, Skythread, roda no XIAO ESP32-S3 Sense, o mesmo chip com 8 MB de PSRAM, que ele precisa para manter uma paisagem inteira na memória. Este artigo explica como cada jogo funciona e como ele opera por dentro.
Como jogá-los no Velxio
- Abra qualquer jogo da tabela acima. O sketch, as bibliotecas e o circuito carregam juntos.
- Aperte Run. O Velxio compila o sketch e o inicia. A primeira compilação de um sketch leva até um minuto; depois disso, ele vem do cache de build.
- Todo jogo começa com uma demo em modo atração que se joga sozinha. Aperte qualquer tecla ou botão para assumir.
- Jogue com o teclado: as setas são o D-pad, Z é A e X é B. Cada botão na tela mostra sua tecla em um pequeno keycap. Você também pode clicar nos botões com o mouse, e segurar um para mantê-lo pressionado. Skythread tem um analógico e mais botões; seus controles estão na seção dele abaixo.
- Abra o monitor Serial para acompanhar o log do jogo: uma linha
STATcom a taxa de quadros, e uma linhaEVTpara cada abate, nível, item coletado e morte. Skythread imprime sua própria linha a cada dois segundos, com a taxa de quadros, o tempo que cada quadro levou para desenhar e para enviar, e a pontuação.
Qualquer botão de pressão no Velxio pode ser acionado pelo teclado, não apenas estes. Clique com o botão direito em um botão e use o cartão Keyboard control: clique nele, aperte uma tecla, e a partir daí segurar essa tecla pressiona o botão enquanto a simulação roda.
O simulador executa o próprio firmware, compilado para o chip real: o Velxio emula o ESP32 e o ESP32-S3 instrução por instrução, no seu navegador, e desenha o que quer que o sketch envie para o ILI9341.
O portátil

O XIAO tem apenas 11 pinos GPIO, e uma tela e seis botões precisam de doze. O truque é que a tela não precisa de duas de suas linhas habituais: nada é lido de volta dela, então o MISO fica desconectado, e seu pino de reset é ligado a 3,3 V para que ela reinicie junto com a placa. Isso deixa exatamente o suficiente.
| Pino do XIAO | Vai para | Pino do XIAO | Vai para | |
|---|---|---|---|---|
| D8 | tela SCK | D0 | D-pad CIMA | |
| D10 | tela MOSI | D1 | D-pad BAIXO | |
| D7 | tela CS | D2 | D-pad ESQUERDA | |
| D9 | tela D/C | D3 | D-pad DIREITA | |
| 3V3 | tela VCC, LED e RST | D4 | A | |
| GND | tela GND, todos os botões | D5 | B |
Cada botão conecta seu pino ao terra. O sketch liga os resistores de pull-up internos do chip com pinMode(pin, INPUT_PULLUP), então um pino lê HIGH quando o botão está solto e LOW quando é pressionado. Nenhum resistor é necessário, na tela ou em uma protoboard real. Doom usa a mesma ideia no ESP32 DevKit maior, com seus próprios pinos (eles estão listados na seção dele abaixo).
Por que o XIAO ESP32-S3
Os quatro jogos do XIAO desenham a imagem inteira na memória primeiro e depois a enviam para a tela de uma só vez. Uma imagem de 320 x 240 a dois bytes por pixel tem 153.600 bytes, e ela precisa ficar em um bloco contínuo de RAM.
É aí que os dois chips diferem. Imprimimos o maior bloco livre a partir de um sketch em cada um: 110.592 bytes no ESP32 clássico e 278.528 bytes no ESP32-S3. O S3 consegue manter o quadro inteiro com folga; o ESP32 clássico não consegue, e é por isso que Doom desenha sua imagem uma coluna por vez (mais sobre isso abaixo).
O S3 também é o mais rápido dos dois no simulador. Com o mesmo benchmark de frame buffer nas duas placas, a engine no navegador do Velxio rodou o ESP32 a 81 a 90 milhões de instruções por segundo e o ESP32-S3 a 96 a 106 milhões, e o S3 empurrou 33 quadros completos por segundo contra os 31 do ESP32.
Uma engine para quatro jogos
Os quatro sketches do XIAO começam com as mesmas 200 linhas: a engine. Ela é dona do frame buffer, dos botões, de um punhado de funções de desenho e do loop de quadros.

Desenhar na RAM significa que a ordem não importa. Um jogo pode pintar o céu, depois as colinas, depois os aviões, depois as explosões por cima, e a tela só vê a imagem finalizada, então nada pisca. Enviá-la são três chamadas à biblioteca Adafruit ILI9341:
static void present() {
tft.startWrite();
tft.setAddrWindow(0, 0, SCR_W, SCR_H); // the whole 320 x 240 screen
tft.writePixels(fb, SCR_W * SCR_H); // 153,600 bytes in one burst
tft.endWrite();
}
A 40 MHz, esses 153.600 bytes levam cerca de 31 ms nos fios SPI, então a transferência sozinha define o teto perto de 30 quadros por segundo. O resto do quadro, a lógica do jogo e o desenho, precisa caber no que sobra, e é por isso que as funções de desenho são simples: retângulos preenchidos, linhas, círculos, texto na fonte 5 x 7 que vem com o Adafruit GFX, e sprites.
Os sprites são escritos como texto, um caractere por pixel, com . para pixels transparentes e uma paleta de 128 entradas para o resto. Este é o robô do Gear Hop:
"........a.......",
"....mmmmmmmm....",
"...mMMMMMMMMm...",
"...mMllMMllMm...", // l = the eyes, light cyan
"...mMllMMllMm...",
"...mMMMMMMMMm...",
"....mmmrrmmm....", // r = the red mouth
Nada nesses jogos vem de um arquivo de imagem. Os tiles do mapa, as texturas e os efeitos são desenhados por código na RAM quando a placa inicia, então cada sketch é texto puro que você pode ler e alterar no editor.
Sky Duel: um combate aéreo com modelo de voo
Você pilota um biplano sobre um mundo com quatro telas de largura que dá a volta: voe para fora da borda direita e você volta pela esquerda. Um esquadrão vermelho te caça, canhões antiaéreos e caminhões esperam no chão, e cada onda traz mais um avião inimigo.
Como jogar. Aponte o D-pad para onde você quer voar, diagonais incluídas; o avião vira na direção apontada. Segure A para as metralhadoras e toque B para soltar uma bomba (seis por onda). As bombas são a única forma de destruir os alvos no chão. O radar no topo mostra o mundo inteiro, para você encontrar os aviões que estão fora da tela.
Como funciona. O avião não se move a uma velocidade fixa. A cada quadro o sketch executa um pequeno modelo de voo:

A velocidade tende a um valor de cruzeiro, mas subir custa velocidade e mergulhar ganha, em proporção ao ângulo. Puxe direto para cima por tempo demais e o avião cai abaixo da velocidade de estol: o nariz cai em direção ao chão sozinho, e você precisa mergulhar para voltar a voar. Os pilotos inimigos voam o mesmo modelo, com o mesmo estol, e é isso que faz disso um combate aéreo em vez de um tiro ao alvo.
O avião é um único sprite de 16 x 16 voltado para a direita. Na inicialização o sketch o rotaciona em 32 direções e armazena todas, espelhando as que apontam para a esquerda para que o avião não voe de cabeça para baixo. Desenhar um avião é então uma consulta à tabela, ampliada duas vezes na tela. Os inimigos se dirigem para um ponto logo à sua frente, atiram quando você está na frente das armas deles, e se afastam após uma passagem próxima para não te abaterem.
XIAO Quest: um pequeno RPG
Um herói, uma vila, uma floresta e uma caverna. O ancião perto da fonte te conta que o Rei das Sombras levou o cristal da vila para a caverna antiga, e te dá a chave do portão que bloqueia o caminho. Na floresta e na caverna, monstros atacam e você luta contra eles por turnos.
Como jogar. Ande com o D-pad. A fala com as pessoas, lê placas, abre baús e confirma; B mostra seus atributos e itens. A fonte te cura, o mercador vende poções por 10 de ouro, e três baús guardam duas poções, uma espada de ferro e um anel de prata. Em uma batalha, escolha com o D-pad e confirme com A: atacar, lançar fogo (3 de MP, dano dobrado, ignora defesa), beber uma poção ou fugir.
Como funciona. O jogo é uma pequena máquina de estados. Cada estado tem seu próprio tratamento de entrada e seu próprio desenho, e estes são os eventos que o movem de um para outro:

Os três mapas são 20 x 14 tiles de 16 pixels, escritos no sketch como strings, um caractere por tile: # é uma árvore, ~ água, = um caminho, K o portão trancado. O herói se move um tile por vez e desliza entre tiles ao longo de 0,16 segundos, então o movimento parece suave mas as colisões continuam simples: um passo é permitido ou não é.
As batalhas usam pequenas fórmulas de números inteiros. Um ataque causa seu ataque mais um sorteio de 0 a 3, menos a defesa do inimigo. A experiência traz níveis, e cada nível adiciona vida, magia, ataque e defesa. A caverna é escura: após desenhar o mapa, o sketch escurece cada pixel entre 50 e 70 pixels do herói para metade do brilho e tudo mais distante para um quarto, então você carrega uma lanterna. Medir a distância de cada pixel levou a taxa de quadros de cerca de 27 para 16. Calculando uma vez por linha em vez disso, como um trecho iluminado, um trecho escurecido e o resto escuro, traz de volta para cerca de 22.
Gear Hop: um jogo de plataforma
Um pequeno robô corre por dois níveis coletando engrenagens. Besouros andam pelo chão, drones flutuam no ar, espinhos revestem alguns pisos, e os vãos mais largos só podem ser atravessados em plataformas móveis. Alcance a bandeira no final de cada nível.
Como jogar. Ande com ESQUERDA e DIREITA, segure B para correr, pressione A para pular. Segure A por mais tempo para um pulo mais alto. Aterrisse em um inimigo para pisá-lo, e pule em um bloco ? por baixo para derrubar uma engrenagem dele. Você tem três corações; espinhos e inimigos tiram um, e cair em um buraco também.
Como funciona. Os níveis são 128 x 14 tiles, gerados por um pequeno script e colados no sketch como strings. O robô é uma caixa de 10 x 14 pixels, e a cada quadro ele se move em duas etapas: primeiro lateralmente, empurrado de volta para fora de qualquer parede em que acabe dentro; depois verticalmente, aterrissando no chão, em uma prancha de sentido único ou em uma plataforma móvel, ou batendo a cabeça em um bloco. Fazer os dois eixos separadamente é o que impede o robô de grudar nas paredes ou deslizar pelos cantos.
Três pequenas regras fazem o pulo parecer certo. Um pulo pressionado até 0,12 segundos antes de aterrissar ainda acontece quando o robô toca o chão (um buffer de pulo). Um pulo pressionado até 0,08 segundos depois de sair de uma beirada ainda conta (tempo do coiote). E soltar A cedo corta a velocidade ascendente, que é como segurar o botão dá um pulo mais alto. Duas camadas de colinas rolam a um quinto e a menos da metade da velocidade da câmera, o que dá profundidade à cena.
Circuit Defense: tower defense em uma placa de circuito
Bugs rastejam por uma placa de circuito em direção ao chip. Você constrói peças eletrônicas na placa para detê-los: um LED dispara um laser rápido em um bug, um capacitor descarrega em todos os bugs ao seu redor, e uma bobina desacelera os bugs. Cada bug que alcança o chip custa um ponto de vida a ele, e as ondas continuam ficando mais fortes.
Como jogar. Mova o cursor com o D-pad. B escolhe a peça, A a constrói, e A em uma peça que você já construiu a melhora, até o nível 3. Bugs destruídos pagam moedas, e cada onda concluída paga um bônus. O círculo ao redor do cursor mostra o alcance da peça que você está prestes a construir.
Como funciona. Os bugs não seguem uma trilha fixa. Eles caminham pela placa aberta, e você pode conduzi-los com o que constrói: a trilha de cobre na placa é sempre a rota que eles vão seguir. Por trás disso está uma busca em largura, executada novamente após cada construção:

A busca começa nas células ao lado do chip, numera-as com 0, e se espalha para fora: cada vizinho livre de uma célula numerada recebe aquele número mais um. Quando termina, cada célula guarda sua distância até o chip, incluindo as paredes de torres. Um bug parado em uma célula simplesmente avança para qualquer vizinho com um número menor. Não há planejamento de rota por bug: uma busca, 260 células, serve para todos eles.
Os mesmos números tornam fácil impor a única regra do jogo: você pode alongar o caminho, mas nunca fechá-lo. Quando você constrói, o sketch coloca a peça, executa a busca novamente e olha para a célula de entrada. Se ela não tiver mais um número, os bugs não conseguiriam passar: a peça é removida e o jogo exibe THAT BLOCKS THE PATH.
ESP32 Doom: um jogo de tiro em primeira pessoa
O mais antigo dos cinco roda no clássico ESP32 DevKit. Você percorre um labirinto de paredes texturizadas, atira em robôs que te perseguem e em slimes que cospem ácido, abre portas, pega kits médicos e munição, e limpa onda após onda.
Como jogar. O D-pad anda e vira, A atira (segure para tiro automático), B abre a porta à sua frente, e B segurado com ESQUERDA ou DIREITA faz strafe. Os pinos são diferentes dos jogos do XIAO: CIMA no GPIO 32, BAIXO 33, ESQUERDA 25, DIREITA 15, A no 22, B no 21, e a tela no barramento VSPI do ESP32 (SCK 18, MOSI 23, MISO 19, CS 5, D/C 2, RST 4).
Como funciona. Doom é um raycaster, a técnica de Wolfenstein 3D (1992): para cada coluna da tela ele envia um raio do jogador para um mapa em grade de 20 x 20 e o interrompe na primeira parede. A distância define a altura com que a fatia da parede é desenhada. Como o ESP32 clássico não tem espaço para um quadro completo, o sketch monta uma coluna por vez em um buffer de 200 pixels, com o chão, o teto, a parede, os inimigos, a arma e os efeitos já compostos, e a envia em um único disparo:
Robôs caminham direto até você e atacam com garras causando 5 de vida por segundo; slimes mantêm distância e cospem ácido que custa 7. Um tiro atinge o inimigo mais próximo sob a mira, desde que nenhuma parede esteja mais perto. Cada inimigo eliminado traz a próxima onda com dois a mais deles, um pouco mais rápidos e um pouco mais resistentes.
Skythread: voo 3D sobre um mundo gerado
Doom é 3D em ambientes fechados. Skythread é 3D ao ar livre: você pilota um planador de asa delta baixo sobre campo aberto, ao longo de vales de rios, passando por montanhas e sobre lagos, com névoa em direção ao horizonte e um céu que vai do dia à hora dourada e à noite. Anéis ficam suspensos no ar à sua frente, e o relógio está correndo. Você começa com 45 segundos, e cada anel adiciona mais alguns. Cada anel em sequência aumenta o combo, até cinco vezes os pontos, e voar pelo meio de um anel marca um PERFECT. Perca um anel e o combo recomeça; toque o chão e você quica nele, mais devagar e três segundos mais pobre. Como os outros, ele começa com uma demo que voa sozinha.
O portátil. Skythread foi escrito para o portátil que roda nossos ports de Metal Gear Solid e Castlevania, não para o layout de D-pad dos outros quatro: um Seeed Studio XIAO ESP32-S3 Sense, a mesma tela ILI9341, um analógico de dois eixos, dois botões em pinos próprios e mais seis em um único pino. No Velxio o exemplo abre com o layout desse portátil: o analógico à esquerda, a tela no meio, os botões à direita e embaixo da tela.
| Pino do XIAO | Vai para | Pino do XIAO | Vai para | |
|---|---|---|---|---|
| D8 | SCK da tela | D0 | analógico X (esquerda e direita) | |
| D10 | MOSI da tela | D1 | analógico Y (cima e baixo) | |
| D9 | MISO da tela | D2 | seis botões, através de uma escada de resistores | |
| D3 | CS da tela | D5 | FIRE | |
| D6 | D/C da tela | D7 | BRAKE | |
| D4 | RST da tela | 3V3, GND | alimentação da tela, do analógico e da escada |
Como jogar. Dirija com o analógico: clique nele na tela e use as setas, ou segure o mouse em uma de suas setas. Puxe para trás (baixo) para subir, empurre para frente para mergulhar, e esquerda ou direita para inclinar e virar. FIRE (Z) é um turbo que drena a barra azul, e também inicia um jogo. BRAKE (X) desacelera você para curvas fechadas. START (Enter) inicia e pausa, CROSS (C) também inicia um jogo, SELECT (Q) volta para a demo, CIRCLE (T) muda a hora do dia, TRIANGLE (W) constrói um novo mundo, e L1 (F) mostra a taxa de quadros.
Seis botões em um pino. O XIAO tem 11 pinos, e a tela, o analógico e oito botões precisariam de 16. O truque para seis dos botões é uma escada de resistores. Um resistor de 10 kΩ puxa D2 para 3,3 V, e cada botão conecta D2 ao terra através de um resistor diferente, de modo que cada um forma um divisor de tensão diferente. O pino lê 3,3 V × R / (R + 10 kΩ):
| Botão | Para o terra através de | Esperado | Medido no Velxio |
|---|---|---|---|
| CIRCLE | 0 Ω | 0 V | 0 mV |
| CROSS | 2,2 kΩ | 0,595 V | 612 mV |
| TRIANGLE | 4,7 kΩ | 1,055 V | 1065 mV |
| L1 | 10 kΩ | 1,650 V | 1651 mV |
| START | 22 kΩ | 2,269 V | 2258 mV |
| SELECT | 47 kΩ | 2,721 V | 2665 mV |
O sketch lê D2 com analogReadMilliVolts() e escolhe o botão cuja tensão está mais próxima, com limiares no meio do caminho entre vizinhos (300, 824, 1350, 1960, 2496 e 2960 mV). O Velxio resolve a escada como um circuito real: a última coluna é o que o sketch imprimiu no monitor serial quando pressionamos cada botão na tela. Uma escada lê um botão por vez, já que dois pressionados juntos parecem um único botão com um resistor menor. É por isso que o jogo mantém FIRE e BRAKE, os dois que você segura enquanto voa, em pinos próprios. Ele também ignora a escada até tê-la visto solta uma vez, para que um D2 deixado desconectado nunca pressione botões fantasma.
Como funciona. O mundo é gerado quando a placa inicia: um mapa 512 x 512 da paisagem feito com ruído diamond-square, onde cada célula ocupa dois bytes, um para a altura e um para uma cor da paleta. Com uma cópia em metade da resolução para a distância longa e dois frame buffers, isso dá cerca de 940 KB, e é por isso que Skythread precisa do Sense e de sua PSRAM. No Velxio o mundo leva 3 segundos de tempo simulado para ser construído, e o primeiro quadro chega à tela 3,4 segundos após a energização.
O desenho usa o ray casting por colunas dos jogos de voo voxel do início dos anos 1990. Para cada coluna da tela, o sketch percorre um raio da câmera sobre o mapa, de perto para longe, até 160 passos e 340 células de distância; após 110 células ele lê o mapa em metade da resolução. A cada passo ele converte a altura do terreno ali em uma linha na tela. Se essa linha for mais alta do que qualquer coisa desenhada até agora na coluna, ele preenche a lacuna com a cor daquela célula e lembra o novo topo:

Esse topo lembrado por coluna é chamado de y-buffer. O chão próximo é sempre desenhado primeiro, então o chão distante só pode aparecer acima dele, e nenhum pixel é pintado duas vezes. A névoa são 20 paletas, cada uma misturada um pouco mais em direção à cor do céu, uma por faixa de distância. A inclinação é uma cisalha: o horizonte de cada coluna sobe ou desce em proporção à sua distância do centro da tela, o que parece um rolamento. Os anéis, a sombra do planador e o sol são verificados contra o mesmo y-buffer na sua própria distância, então uma montanha na frente de um anel o esconde.
O quadro é armazenado coluna por coluna, já na ordem de bytes que o ILI9341 espera. No endereçamento retrato do próprio painel, uma coluna da imagem da paisagem é uma de suas linhas, então o quadro inteiro sai em uma única rajada. Com dois frame buffers, os dois núcleos do chip trabalham ao mesmo tempo: uma tarefa no núcleo 0 envia um quadro para a tela via SPI a 40 MHz enquanto o núcleo 1 desenha o próximo.
O sketch também observa sua própria velocidade. Quando desenhar um quadro leva mais de 22 ms em média, ele lança 160 raios em vez de 320 e desenha cada coluna com dois pixels de largura, e volta à largura total abaixo de 7 ms. Acima de 45 ms, um caso que seus comentários reservam para um host lento como um simulador de navegador, ele para de sobrepor os dois núcleos e espera cada quadro terminar de sair antes de desenhar o próximo, para que o painel simulado sempre receba quadros inteiros. No Velxio ele rodou nesse modo o tempo todo, com 160 colunas, desenhando cada quadro em 33 a 50 ms de tempo simulado.
Taxas de quadros
Medimos cada jogo em velxio.dev em um navegador Chrome headless no nosso servidor, jogando por cerca de um minuto cada.
| Jogo | Reportado pelo sketch (mediana, faixa) | Quadros por segundo de tempo real |
|---|---|---|
| ESP32 Doom | 17,6 (13 a 24) | 16,1 |
| Sky Duel | 28,9 (23 a 38) | 27,2 |
| XIAO Quest | 32,2 (21 a 39) | 30,8 |
| Gear Hop | 27,0 (21 a 35) | 23,4 |
| Circuit Defense | 31,3 (23 a 40) | 29,4 |
| Skythread | 20,4 (16 a 23) | 17,7 |
Dois números por jogo. O primeiro é o que o próprio jogo reporta no monitor serial, a partir do millis() do próprio chip: a taxa de quadros da placa simulada. O segundo é quantos quadros o navegador realmente mostrou por segundo de tempo real. Eles diferem quando o computador que roda a simulação não consegue manter o chip simulado em velocidade máxima; o tempo simulado então corre um pouco mais devagar que o relógio da parede. Seus próprios números dependem do seu computador.
Os quatro jogos 2D do XIAO rodam a quase o dobro da taxa de quadros do Doom. Parte disso é o trabalho: um raycaster lança 320 raios e calcula o chão e o teto pixel por pixel. Parte disso é a transferência: uma rajada por quadro em vez de 320 pequenas, cada uma com sua própria janela de endereço. Skythread, o único que desenha uma paisagem 3D, mantém cerca de 20 quadros por segundo lançando 160 raios em vez de 320, a troca que seu próprio código faz sempre que um quadro leva mais de 22 ms para ser desenhado.
Faça-os do seu jeito
Cada jogo é um sketch, e o código é organizado em blocos: a engine, a arte, o estado do jogo, a atualização e o desenho. Algumas mudanças que levam um minuto:
- Sky Duel: altere a velocidade de cruzeiro (125) ou a velocidade de estol (50) em
fly()e sinta como o avião muda. - XIAO Quest: os mapas são as strings em
MAP_V,MAP_FeMAP_C; os números dos monstros estão na tabelaFOES. - Gear Hop: a força do salto é
-335emmovePlayer(), a gravidade é950; experimente a lua. - Circuit Defense: adicione uma quarta peça a
TW_NAME,TW_COSTeupdateTowers(). - Doom:
MAP_SRCsão 20 strings de 20 dígitos; cada dígito é uma textura de parede, e um 9 é uma porta. - Skythread:
WORLD_SEEDno topo do sketch escolhe o mundo em que você inicia, ePITCH_PULL_TO_CLIMBdefinido como 0 faz o manche subir quando você o empurra para frente.
Pressione Run após uma edição e o Velxio compila o sketch alterado, então você pode mudar um número e ver o resultado alguns segundos depois. Quando funcionar do jeito que você gosta, o mesmo sketch roda em um XIAO ESP32-S3 real com um ILI9341 e seis botões ligados como acima, e o Skythread em um XIAO ESP32-S3 Sense com o manche e os botões da sua seção.