IT

Tutorial 1 — Hello world: un menu, un testo, un suono

Il gioco JumPHP più piccolo possibile: una schermata del titolo con un menu (gioca, suono, esci), poi un testo che si sposta con le frecce e un suono alla pressione di Spazio. Due file. Puoi modificarlo subito nella sandbox, oppure crearlo a casa tua con bin/jumphp new hello-world.

La configurazione: config/game.yaml

game:
  id: hello-world
  title: "HELLO WORLD"
  width: 320                    # la risoluzione del gioco, ingrandita alle dimensioni dello schermo
  height: 180
  start_scene: App\Scene\TitleScene
  touch: { a: Space, b: Escape, start: Return }    # i pulsanti del pad sul telefono
  smoke:                        # ciò che `bin/jumphp test` gioca da solo, senza schermo
    scene: App\Scene\HelloScene
    params: { demo: true }

I tasti: il motore definisce già up down left right confirm back pause (frecce, Invio, Esc, il gamepad, il touch screen). Si aggiunge un'azione in config/input.yaml:

actions:
  jump: [Space, pad0:a, touch:tap]

La schermata del titolo: src/Scene/TitleScene.php

Un menu si scrive ereditando da MenuScene: si danno il titolo e le righe, il motore pensa al resto (disegno, spostamento con tastiera / gamepad / dito, suoni del menu).

final class TitleScene extends MenuScene
{
    protected string $title = 'HELLO WORLD';

    public function enter(array $params = []): void
    {
        parent::enter($params);
        // suoni fabbricati in PHP: nessun file audio necessario
        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]]));
        }
    }

    /** Le righe: [etichetta, valore mostrato a destra, azione su Invio, azione su sinistra / destra] */
    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()];   // niente «esci» nel browser
        }
        return $items;
    }

    private function toggleSound(): void
    {
        $this->sound()->setMuted(!$this->sound()->isMuted());
        $this->refresh();    // il menu mostra di nuovo il nuovo valore
    }
}

I suoni menu_move e menu_confirm vengono riprodotti automaticamente dal menu. Le etichette sono tradotte con config/lang.yaml (fr: { PLAY: JOUER }).

Il gioco: src/Scene/HelloScene.php

Una scena ha tre metodi essenziali:

  • enter($params): la scena inizia. Azzera tutto qui: la stessa scena viene riutilizzata più volte;
  • update($dt): 60 volte al secondo si cambia lo stato del gioco. $dt è il tempo trascorso in secondi;
  • render($r): si disegna, e nient'altro.
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));   // un «bip» che sale
        }
    }

    public function update(float $dt): void
    {
        if ($this->actions()->isPressed('back')) {          // Esc: ritorno al titolo
            $this->scenes()->switchTo(TitleScene::class);
            return;
        }
        // axis() vale -1, 0 o 1: 90 pixel al secondo
        $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]);
        // il font integrato (5 × 7 pixel), ingrandito 2 volte, centrato, con un'ombra nera
        $this->font()->draw($r, 'HELLO WORLD!', $this->x, $this->y, 2, [255, 220, 80], 'center', [0, 0, 0]);
    }
}

Il file vero aggiunge stelle che sprizzano a ogni suono, un testo che cambia colore e una modalità demo per i test: leggilo nei sorgenti del gioco.

Provare

  • Nella sandbox: cambia il testo, il colore [255, 220, 80], la velocità, il suono (Synth::tone(220, 0.3, 'triangle')), poi ▶ Testa.
  • A casa tua: bin/jumphp run hello-world, bin/jumphp test hello-world.

Prossimo passo: un personaggio che si muove e si anima.