О чем этот пример

Внешний вид игрового курсора — это важная деталь, которая влияет на погружение игрока. Используя стандартные стрелки, вы упускаете возможность усилить атмосферу вашего проекта. В этой статье мы разберём, как в Phaser 3 заменить системный курсор на собственные изображения, в том числе вдохновлённые интерфейсами популярных игр. Вы научитесь задавать курсор для всей сцены и назначать уникальные указатели для отдельных интерактивных объектов, что позволит создать более выразительный и стилистически целостный пользовательский интерфейс.

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class Example extends Phaser.Scene
{
    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('logo', 'assets/input/cursors/sc2/logo.png');
        this.load.image('folder', 'assets/input/cursors/sc2/starcraft2-mac-folder-by-gazol-d3d7ctl.png');
    }

    create ()
    {
        this.input.setDefaultCursor('url(assets/input/cursors/sc2/SC2-cursor.cur), pointer');

        this.add.image(400, 100, 'logo');

        //  Create some custom cursor folders

        this.add.sprite(100, 300, 'folder').setInteractive({ cursor: 'url(assets/input/cursors/sc2/SC2-cursor-busy-protoss.cur), pointer' });
        this.add.sprite(300, 300, 'folder').setInteractive({ cursor: 'url(assets/input/cursors/sc2/SC2-cursor-zerg.cur), pointer' });
        this.add.sprite(500, 300, 'folder').setInteractive({ cursor: 'url(assets/input/cursors/sc2/SC2-hyperlink.cur), pointer' });
        this.add.sprite(700, 300, 'folder').setInteractive({ cursor: 'url(assets/input/cursors/sc2/SC2-target-none.cur), pointer' });

        this.add.sprite(100, 450, 'folder').setInteractive({ cursor: 'url(assets/input/cursors/sc2/SC2-cursor-busy-zerg.cur), pointer' });
        this.add.sprite(300, 450, 'folder').setInteractive({ cursor: 'url(assets/input/cursors/sc2/SC2-cursor-protoss.cur), pointer' });
        this.add.sprite(500, 450, 'folder').setInteractive({ cursor: 'url(assets/input/cursors/sc2/SC2-ibeam.cur), pointer' });
        this.add.sprite(700, 450, 'folder').setInteractive({ cursor: 'url(assets/input/cursors/sc2/SC2-resize-diagonal-right.cur), pointer' });
    }
}

const config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    backgroundColor: '#003a7b',
    scene: Example
};

const game = new Phaser.Game(config);

Загрузка ресурсов для курсоров

Перед использованием курсоров необходимо загрузить их изображения, как и любые другие ассеты игры. В методе preload мы устанавливаем базовый URL для загрузки и указываем файлы. Важно помнить, что Phaser поддерживает для курсоров форматы .cur (специфичный для Windows) и .png. Для кроссплатформенности рекомендуется использовать PNG.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('logo', 'assets/input/cursors/sc2/logo.png');
    this.load.image('folder', 'assets/input/cursors/sc2/starcraft2-mac-folder-by-gazol-d3d7ctl.png');
}

Установка курсора по умолчанию для всей сцены

Чтобы изменить вид курсора во всей сцене, используется метод this.input.setDefaultCursor(). В него передаётся CSS-совместимая строка. Синтаксис url(...), pointer важен: url указывает путь к файлу, а pointer — это fallback-значение, которое будет использовано, если загрузка кастомного курсора по какой-то причине не удастся.

create ()
{
    this.input.setDefaultCursor('url(assets/input/cursors/sc2/SC2-cursor.cur), pointer');
    // ... остальной код
}

После этого вызова основной курсор в пределах canvas вашей игры изменится на указанный файл.

Назначение уникальных курсоров для интерактивных объектов

Часто требуется, чтобы курсор менялся при наведении на конкретный объект, например, на кнопку или иконку. Для этого объект должен быть интерактивным. В Phaser это делается методом setInteractive(). В его параметрах можно напрямую задать свойство cursor с такой же CSS-строкой.

this.add.sprite(100, 300, 'folder').setInteractive({ cursor: 'url(assets/input/cursors/sc2/SC2-cursor-busy-protoss.cur), pointer' });

В этом примере создаётся спрайт, который становится интерактивным. При наведении на него курсор сменится на «занятый протосс» из StarCraft II, а за пределами спрайта будет действовать курсор по умолчанию, заданный ранее для сцены. Таким образом можно создавать сложную систему визуальных подсказок.

Практические советы по работе с курсорами

1. **Размер и форма:** Идеальная «горячая точка» (активная точка клика) у кастомного курсора должна находиться на его кончике (как у стрелки). Убедитесь, что ваше изображение не слишком большое и не перекрывает важные элементы интерфейса. 2. **Производительность:** Курсоры — это ресурсы, которые браузер должен отрисовывать поверх всего. Слишком тяжёлые анимированные курсоры могут негативно сказаться на производительности, особенно на мобильных устройствах. 3. **Fallback:** Всегда указывайте резервное значение (например, pointer или default). Это гарантирует, что игровой интерфейс останется функциональным даже если пользовательский файл не загрузится. 4. **Интерактивность:** Метод setInteractive() без параметров делает объект кликабельным с курсором по умолчанию. Чтобы задать свой курсор, передавайте конфигурационный объект.

Что попробовать дальше

Кастомизация курсоров в Phaser — это простой, но мощный инструмент для улучшения пользовательского опыта и усиления игровой атмосферы. Вы можете назначить общий стиль для всей игры и точечно менять курсор для различных типов взаимодействий (атака, диалог, перемещение). Для экспериментов попробуйте создать анимированный курсор из последовательности спрайтов, меняя его в реальном времени в ответ на игровые события, или реализуйте систему, где вид курсора зависит от выбранного игроком персонажа или оружия.