Samouczek 1 — Hello world: menu, tekst, dźwięk
Najmniejsza gra JumPHP: ekran tytułowy z menu (graj, dźwięk, wyjdź), a potem tekst poruszany strzałkami i dźwięk na Spacji. Dwa pliki. Możesz ją zmienić od razu w piaskownicy albo utworzyć u siebie poleceniem bin/jumphp new hello-world.
Konfiguracja: config/game.yaml
game:
id: hello-world
title: "HELLO WORLD"
width: 320 # rozdzielczość gry, powiększana do rozmiaru ekranu
height: 180
start_scene: App\Scene\TitleScene
touch: { a: Space, b: Escape, start: Return } # przyciski pada na telefonie
smoke: # to, co `bin/jumphp test` odgrywa samo, bez ekranu
scene: App\Scene\HelloScene
params: { demo: true }
Klawisze: silnik już definiuje up down left right confirm back pause (strzałki, Enter, Esc, pad, ekran dotykowy). Dodajemy akcję w config/input.yaml:
actions:
jump: [Space, pad0:a, touch:tap]
Ekran tytułowy: src/Scene/TitleScene.php
Menu piszemy, dziedzicząc po MenuScene: podajemy tytuł i wiersze, a silnik zajmuje się resztą (rysowaniem, poruszaniem się klawiaturą / padem / palcem, dźwiękami menu).
final class TitleScene extends MenuScene
{
protected string $title = 'HELLO WORLD';
public function enter(array $params = []): void
{
parent::enter($params);
// dźwięki wytworzone w PHP: żaden plik audio nie jest potrzebny
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]]));
}
}
/** Wiersze: [etykieta, wartość wyświetlana po prawej, akcja na Enter, akcja na lewo / prawo] */
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()]; // w przeglądarce nie ma „wyjścia”
}
return $items;
}
private function toggleSound(): void
{
$this->sound()->setMuted(!$this->sound()->isMuted());
$this->refresh(); // menu wyświetla nową wartość
}
}
Dźwięki menu_move i menu_confirm menu odtwarza automatycznie. Etykiety są tłumaczone przez config/lang.yaml (fr: { PLAY: JOUER }).
Gra: src/Scene/HelloScene.php
Scena ma trzy podstawowe metody:
enter($params): scena się zaczyna. Wyzeruj tutaj wszystko: ta sama scena służy wielokrotnie;update($dt): 60 razy na sekundę zmieniamy stan gry.$dtto czas, który upłynął, w sekundach;render($r): rysujemy i nic więcej.
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)); // „bip” idący w górę
}
}
public function update(float $dt): void
{
if ($this->actions()->isPressed('back')) { // Esc: powrót do tytułu
$this->scenes()->switchTo(TitleScene::class);
return;
}
// axis() zwraca -1, 0 lub 1: 90 pikseli na sekundę
$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]);
// wbudowana czcionka (5 × 7 pikseli), powiększona 2 razy, wyśrodkowana, z czarnym cieniem
$this->font()->draw($r, 'HELLO WORLD!', $this->x, $this->y, 2, [255, 220, 80], 'center', [0, 0, 0]);
}
}
Prawdziwy plik dodaje gwiazdki tryskające przy każdym dźwięku, tekst zmieniający kolor i tryb demo do testów: przeczytasz go w kodzie źródłowym gry.
Wypróbuj
- W piaskownicy: zmień tekst, kolor
[255, 220, 80], prędkość, dźwięk (Synth::tone(220, 0.3, 'triangle')), a potem ▶ Testuj. - U siebie:
bin/jumphp run hello-world,bin/jumphp test hello-world.