Tutorial 1 — Hello world: um menu, um texto, um som
O menor jogo JumPHP: uma tela de título com um menu (jogar, som, sair) e, depois, um texto que se move com
as setas e um som ao apertar Espaço. Dois arquivos. Você pode modificá-lo agora mesmo na
sandbox ou criá-lo na sua máquina com bin/jumphp new hello-world.
A configuração: config/game.yaml
game:
id: hello-world
title: "HELLO WORLD"
width: 320 # a resolução do jogo, ampliada para o tamanho da tela
height: 180
start_scene: App\Scene\TitleScene
touch: { a: Space, b: Escape, start: Return } # os botões do pad no celular
smoke: # o que `bin/jumphp test` joga sozinho, sem tela
scene: App\Scene\HelloScene
params: { demo: true }
As teclas: o motor já define up down left right confirm back pause (setas, Enter, Esc, o
gamepad, a tela de toque). Adiciona-se uma ação em config/input.yaml:
actions:
jump: [Space, pad0:a, touch:tap]
A tela de título: src/Scene/TitleScene.php
Um menu se escreve herdando de MenuScene: você informa o título e as linhas, e o motor cuida do resto
(desenho, navegação por teclado / gamepad / toque, sons do menu).
final class TitleScene extends MenuScene
{
protected string $title = 'HELLO WORLD';
public function enter(array $params = []): void
{
parent::enter($params);
// sons fabricados em PHP: nenhum arquivo de áudio necessário
if (!$this->sound()->hasSfx('menu_move')) {
$this->sound()->synth('menu_move', Synth::tone(660, 0.04));
$this->sound()->synth('menu_confirm', Synth::sequence([[660, 0.05], [990, 0.08]]));
}
}
/** As linhas: [rótulo, valor exibido à direita, ação ao apertar Enter, ação para esquerda / direita] */
protected function items(): array
{
$items = [
['PLAY', null, fn () => $this->scenes()->switchTo(HelloScene::class)],
['SOUND', fn () => $this->sound()->isMuted() ? 'OFF' : 'ON', fn () => $this->toggleSound(), fn () => $this->toggleSound()],
];
if (Platform::isDesktop()) {
$items[] = ['QUIT', null, fn () => $this->engine->quit()]; // sem “sair” no navegador
}
return $items;
}
private function toggleSound(): void
{
$this->sound()->setMuted(!$this->sound()->isMuted());
$this->refresh(); // o menu exibe de novo o novo valor
}
}
Os sons menu_move e menu_confirm são tocados automaticamente pelo menu. Os rótulos são traduzidos
com config/lang.yaml (pt: { PLAY: JOGAR }).
O jogo: src/Scene/HelloScene.php
Uma cena tem três métodos essenciais:
enter($params): a cena começa. Zere tudo aqui: a mesma cena é usada várias vezes;update($dt): 60 vezes por segundo, muda-se o estado do jogo.$dté o tempo decorrido em segundos;render($r): desenha-se, e nada mais.
final class HelloScene extends AbstractScene
{
private float $x = 0.0;
private float $y = 0.0;
public function enter(array $params = []): void
{
$this->x = $this->width() / 2;
$this->y = $this->height() / 2;
if (!$this->sound()->hasSfx('beep')) {
$this->sound()->synth('beep', Synth::sweep(440, 880, 0.12)); // um “bip” que sobe
}
}
public function update(float $dt): void
{
if ($this->actions()->isPressed('back')) { // Esc: volta ao título
$this->scenes()->switchTo(TitleScene::class);
return;
}
// axis() vale -1, 0 ou 1: 90 pixels por segundo
$this->x += $this->actions()->axis('left', 'right') * 90 * $dt;
$this->y += $this->actions()->axis('up', 'down') * 90 * $dt;
if ($this->actions()->isPressed('jump') || $this->actions()->isPressed('confirm')) {
$this->sound()->playSfx('beep');
}
}
public function render(Renderer $r): void
{
$r->clear([16, 16, 40]);
// a fonte embutida (5 × 7 pixels), ampliada 2 vezes, centralizada, com uma sombra preta
$this->font()->draw($r, 'HELLO WORLD!', $this->x, $this->y, 2, [255, 220, 80], 'center', [0, 0, 0]);
}
}
O arquivo de verdade acrescenta estrelas que jorram a cada som, um texto que muda de cor e um modo demo para os testes: leia-o no código-fonte do jogo.
Experimentar
- Na sandbox: mude o texto, a cor
[255, 220, 80], a velocidade, o som (Synth::tone(220, 0.3, 'triangle')) e depois ▶ Testar. - Na sua máquina:
bin/jumphp run hello-world,bin/jumphp test hello-world.
Próximo: um personagem que se move e se anima.