Как сделать цвет фона прозрачным с помощью Phaser 3

Беда

Я добавил в сцену два текстовых объекта. Но для последнего я не смог установить прозрачный цвет фона.

Может кто-нибудь мне помочь?

Вот скриншот.

Как сделать цвет фона прозрачным с помощью Phaser 3


Что я пробовал

Я хочу, чтобы текстовые объекты имели прозрачный фон.

Я попытался установить backgroundColor например:

this.scene.add.text(0, 0, "hoge", {
  backgroundColor: "rgb(255 255 255 / 0.5)",
});

но это не работает.

Как сделать цвет фона прозрачным с помощью Phaser 3


Исходный код

Этот текстовый объект выглядит хорошо. Он имеет прозрачный фон.

    this.text = (() => {
      const text = this.scene.add.text(0, 0, "x: -, y: -", {
        padding: {
          y: 50 / this.scene.cameras.main.zoom,
        },
        align: "center",
        fixedWidth: containerWidth,
        fixedHeight: containerHeight,
        fontSize: `${100 / this.scene.cameras.main.zoom}px`,
        lineSpacing: 0,
      });

      return text;
    })();

Этот текст выглядит плохо. Он имеет черный фон.

    this.text = (() => {
      const text = this.scene.add.text(0, 0, [
        "a10a",
        "VIT: 0",
      ], {
        fixedWidth: containerWidth,
        fixedHeight: containerHeight,
        fontSize: `${100 / this.scene.cameras.main.zoom}px`,
      });

      return text;
    })();

Минимальный воспроизводимый пример

Я создал минимальный воспроизводимый пример.

Я обнаружил, что опция type: CANVAS в new PhaserGame и this.load.image что-то делает. Я мог бы сделать фон текста прозрачным, когда закомментировал эти строки. Но я не хочу этого делать, потому что мне нужно загружать изображения, и если я изменю параметр type: CANVAS, возникнут другие ошибки.

+ app/
  + _components/
  |  + game/
  |     + scenes/
  |     |   + main-scene/
  |     |       + index.ts
  |     |
  |     + index.tsx
  |
  + globals.css
  + layout.tsx
  + page.tsx
  • _компоненты/игра/index.tsx
"use client";

import { CANVAS, Game as PhaserGame, Scale } from "phaser";
import { useEffect, useRef } from "react";
import { MainScene } from "./scenes/main-scene";

export function Game() {
  const game = useRef<Phaser.Game | null>(null);

  useEffect(() => {
    if (game.current === null) {
      game.current = new PhaserGame({
        parent: "game-container",
        // If AUTO, it doesn't work on smartphone browser
        type: CANVAS,
        width: 100,
        height: 100,
        scale: {
          mode: Scale.ScaleModes.FIT,
        },
        backgroundColor: "#028af8",
        scene: [
          MainScene,
        ],
      });
    }

    return () => {
      if (game.current) {
        game.current.destroy(true);
        
        if (game.current !== null) {
          game.current = null;
        }
      }
    }
  }, []);

  return (
    <div id = "game-container"></div>
  );
}

export default Game;
  • _comComponents/game/scenes/main-scene/index.ts
import { Scene } from "phaser";

export class MainScene extends Scene {
  constructor () {
    super("MainScene");
  }

  preload() {
    this.load.image("tiles", "assets/tiles.1.png");
  }

  create () {
    this.add.text(0, 0, "Text 1", {
      fontSize: `10px`,
    });

    this.add.text(0, 20, "Text 2", {
      fontSize: `10px`,
    });
  }
}

GitHub

(клонируйте stackoverflow/questions/78791454 ветку и запустите npm run dev для воспроизведения)

Как сделать цвет фона прозрачным с помощью Phaser 3


Это зависит от окружающей среды

Я обнаружил, что это происходит только в браузере Chrome.

  • Воспроизводимый
    • Chrome (126.0.6478.183) в MacOS (14.5)
  • Не воспроизводимо
    • Safari (17.5) в MacOS (14.5)
    • Chrome (127.0.6533.56) в iOS (17.5.1)
    • Сафари в iOS (17.5.1)

Этого не должно происходить, можете ли вы привести минимальный воспроизводимый пример ? Потому что, если вы не установите фоновый цвет для текстового GameObject, насколько я знаю, никакого цвета быть не должно. Возможно, это какие-то побочные эффекты с другим кодом

winner_joiner 25.07.2024 07:32

@winner_joiner Я добавил раздел «Минимальный воспроизводимый пример» в тело вопроса. Мне все еще нужна твоя помощь. Спасибо.

a10adotapp 25.07.2024 09:50

Прежде всего, я должен сказать: отличный вопрос и потрясающее резюме и анализ.

winner_joiner 25.07.2024 17:09

Я провел небольшое тестирование и заметил, что это может быть связано с реакцией/nextjs и/или проблемой с очисткой canvas . Поскольку ваш код фазера работает не на React, а на базовой странице React или с набором type: Phaser.WEBGL. В вашей демонстрации DevTools дважды покажите баннер фазера. Если вы закомментируете деструктор в файле _components/game/index.tsx, баннер фазера отобразится один раз, и текст будет выглядеть правильно. К сожалению, я недостаточно хорошо знаю React/Next, чтобы сузить проблему. Я добавил тег nextjs, так как думаю, что настройка следующего кода может решить вашу проблему.

winner_joiner 25.07.2024 17:09

@winner_joiner Спасибо, твой совет мне очень помог. Я написал деструктор, потому что в стиле React обратный вызов useEffect должен возвращать функцию, которая очищает все элементы, измененные в этом обратном вызове. Как вы упомянули, я также обнаружил, что type: Phaser.WEBGL все работает хорошо, и обнаружил, что это зависит от среды: только в Chrome на ПК. У меня такое ощущение, что это ошибка в библиотеке фазера...

a10adotapp 26.07.2024 03:55

Я обновил свой первоначальный ответ, добавив два решения для использования обычного текстового GameObject. Надеюсь, это решит вашу проблему, и удачного кодирования. :)

winner_joiner 26.07.2024 13:31

@winner_joiner Спасибо за помощь! Я застрял над этой проблемой несколько дней и почти отказываюсь от фреймворка фазера. Вы помогли мне по-настоящему.

a10adotapp 27.07.2024 05:52
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
7
85
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Обновление (26 июля 2024 г.). Два возможных «решения»:

Я покопался еще немного и нашел решение проблемы:

  1. Поскольку проблема связана с некоторой проблемой очистки холста, вы можете просто установить фазер «CanvasPool» в пустой список в деструкторе, прежде чем уничтожать объект game. Это приведет к созданию новых объектов html-canvas.

    // ...
    return () => {
      if (game.current) {
        Phaser.Display.Canvas.CanvasPool.pool = [];
        game.current.destroy(true);      
    
        if (game.current !== null) {
          game.current = null;
        }
      }
    } //...
    
  2. Похоже, что двойной вызов useEffect связан с запуском приложения в режиме разработки (StrictMode). Если вы запустите приложение в производственном режиме (npm run build и npm run start), фазер не будет запускаться так быстро подряд, поэтому и этой ошибки не возникнет. Никаких других изменений не требуется (эта информация основана на этом ответе на stackoverflow и кратком просмотре документации)

Я протестировал оба варианта с вашим MRE, и оба работают нормально.

Это «обходной путь» на базе Phaser (первоначальный ответ)

вы можете использовать Phaser BitmapFonts . Поскольку Bitmap Text GameObject визуализируется/генерируется другим способом (а не на скрытом внутреннем холсте, как обычный Text GameObject), проблем не возникнет.

Я протестировал ваше демонстрационное приложение с растровым шрифтом, и оно работает (на Win11 Chrome 126+).

По их словам, растровый текст не так гибок, как обычный текст, но имеет лучшую производительность. Существует несколько инструментов преобразования шрифтов, которые могут помочь, если вам нужен какой-то специальный шрифт, но, поскольку я никогда им не пользовался, я не могу его предложить. Также существует множество готовых к использованию растровых шрифтов (, как здесь , или в примерах растровых шрифтов Phaser, ...).

Спасибо за ваш труд и очень подробный ответ!

a10adotapp 27.07.2024 05:49

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

winner_joiner 27.07.2024 06:34

Другие вопросы по теме

TypeScript: [Страна, Штат], где параметры автозаполнения штата меняются в зависимости от введенной страны
После недопустимого входа на сервер ASP.NET MVC, как я могу записать текст ошибки в возвращенном ответе Json и отобразить его в клиенте Angular?
Angular – почему мой раскрывающийся список не работает
Angular V18 PM [vite] Внутренняя ошибка сервера: страница /home не отображается в течение 30 секунд
Как выполнить проверку Type Guard для индексированного свойства
Angular 18 @для возврата ОШИБКИ TypeError: newCollection[Symbol.iterator] не является функцией
Сохранение информации о типе при обеспечении связи типов между членами кортежа при использовании в параметре функции сопоставленного типа
Как упростить это троичное выражение?
Ошибка Angular 18: TS-992003: нет подходящего токена внедрения для параметра MovieService класса MovielistComponent
Как избежать .then или повторного ожидания при объединении обещаний в TypeScript?