RU

Урок 1 — Hello world: меню, текст, звук

Самая маленькая игра на JumPHP: экран заставки с меню (играть, звук, выход), затем текст, который двигается стрелками, и звук по пробелу. Два файла. Вы можете изменить её прямо сейчас в песочнице или создать у себя командой bin/jumphp new hello-world.

Конфигурация: config/game.yaml

game:
  id: hello-world
  title: "HELLO WORLD"
  width: 320                    # разрешение игры, увеличивается до размера экрана
  height: 180
  start_scene: App\Scene\TitleScene
  touch: { a: Space, b: Escape, start: Return }    # кнопки геймпада на телефоне
  smoke:                        # что `bin/jumphp test` проигрывает сам, без экрана
    scene: App\Scene\HelloScene
    params: { demo: true }

Клавиши: движок уже определяет up down left right confirm back pause (стрелки, Enter, Esc, геймпад, сенсорный экран). Своё действие добавляется в config/input.yaml:

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

Экран заставки: src/Scene/TitleScene.php

Меню пишется наследованием от MenuScene: вы задаёте заголовок и строки, остальное делает движок (отрисовку, перемещение по меню с клавиатуры / геймпадом / пальцем, звуки меню).

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

    public function enter(array $params = []): void
    {
        parent::enter($params);
        // звуки, созданные на PHP: аудиофайлы не нужны
        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]]));
        }
    }

    /** Строки: [надпись, значение справа, действие по Enter, действие по стрелкам влево / вправо] */
    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()];   // в браузере пункта «выход» нет
        }
        return $items;
    }

    private function toggleSound(): void
    {
        $this->sound()->setMuted(!$this->sound()->isMuted());
        $this->refresh();    // меню заново показывает новое значение
    }
}

Звуки menu_move и menu_confirm меню воспроизводит автоматически. Надписи переводятся через config/lang.yaml (fr: { PLAY: JOUER }).

Игра: src/Scene/HelloScene.php

У сцены три основных метода:

  • enter($params): сцена начинается. Сбросьте здесь всё в ноль: одна и та же сцена используется много раз;
  • update($dt): 60 раз в секунду мы меняем состояние игры. $dt — прошедшее время в секундах;
  • render($r): мы рисуем, и больше ничего.
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));   // «бип», идущий вверх
        }
    }

    public function update(float $dt): void
    {
        if ($this->actions()->isPressed('back')) {          // Esc: возврат к заставке
            $this->scenes()->switchTo(TitleScene::class);
            return;
        }
        // axis() равно -1, 0 или 1: 90 пикселей в секунду
        $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]);
        // встроенный шрифт (5 × 7 пикселей), увеличенный в 2 раза, по центру, с чёрной тенью
        $this->font()->draw($r, 'HELLO WORLD!', $this->x, $this->y, 2, [255, 220, 80], 'center', [0, 0, 0]);
    }
}

Настоящий файл добавляет звёздочки, вылетающие при каждом звуке, текст, меняющий цвет, и демо-режим для тестов: прочитайте его в исходниках игры.

Попробовать

  • В песочнице: измените текст, цвет [255, 220, 80], скорость, звук (Synth::tone(220, 0.3, 'triangle')), затем ▶ Тест.
  • У себя: bin/jumphp run hello-world, bin/jumphp test hello-world.

Дальше: персонаж, который двигается и анимируется.