본문 바로가기
프로그래밍/Game Dev

[Phaser] Toast 메시지

by YuminK 2023. 10. 4.

채팅으로 입력한 데이터를 Toast 형태로 출력해준다. 

 

미리 Text와 graphics 객체를 만들어서 Container로 묶어준다. 

  createMessageContainer() {
    // 메시지 컨테이너를 생성한다. 세부 설정은 하지 않음
    this.messageWidth = 0;
    this.messageHeight = 0;
    this.messagePadding = 2;

    // positions are relative to the container
    this.messageRect = this.add.graphics();
    this.messageText = this.add
      .text(this.messagePadding, this.messagePadding, "")
      .setFont("10px")
      .setColor("#000000");

    this.container = this.add
      .container(0, 0, [this.messageRect, this.messageText])
      .setDepth(100)
      .setVisible(false)
      .setActive(false);
  }

 

받은 문자열을 토대로 텍스트를 설정하고 배경 영역을 잡아준다.

기존에 사용하던 리소스를 날려서 문제가 생기지 않도록 한다.

  static setMessage(scene, message) {
    // 받은 메시지를 토대로 메시지를 표출한다.
    // 메시지가 너무 긴 경우 잘라서 처리한다.
    let text = "";
    if (message.length <= 25) {
      text = message;
    } else {
      let count = parseInt(message.length / 25) + 1;
      for (let i = 0; i < count; i++) {
        text += message.substring(i * 25, (i + 1) * 25);
        if (i != count - 1) text += "\n";
      }
    }

    scene.messageRect.clear();
    scene.messageText.setText(text);
    scene.container.setActive(true).setVisible(true);
    if (scene.tweenAnim) scene.tweenAnim.destroy();

    scene.messageWidth = scene.messageText.width + scene.messagePadding * 2;
    scene.messageHeight = scene.messageText.height + scene.messagePadding * 2;
    scene.messageRect
      .lineStyle(2, 0x000000, 1)
      .fillStyle(0xffffff, 1.0)
      .fillRoundedRect(0, 0, scene.messageWidth, scene.messageHeight, 5)
      .strokeRoundedRect(0, 0, scene.messageWidth, scene.messageHeight, 5);

    // Tween 애니메이션은 재활용이 안 된다.
    scene.tweenAnim = scene.tweens.add({
      targets: [scene.container],
      ease: "Sine.easeInOut",
      duration: 4000,
      alpha: {
        getStart: () => 1.0,
        getEnd: () => 0.0,
      },
      onComplete: () => {
        scene.container.setActive(false).setVisible(false);
      },
    });
  }

graphics의 경우에는 clear를 해줘야 이전에 그려놓았던 도형이 사라진다.

텍스트는 그냥 바꾸면 되는 거고, text의 크기를 토대로 배경을 만들어 준다.

(fillRoundedRect로 내부를, strokeRoundedRect로 border를 그린다.)

 

이후 Tween 애니메이션을 통해 Fade 처리를 해준다. 

 

업데이트 부분에서 플레이어의 위치에 맞추어 출력해주고 있다. 

  updateMessageContainer() {
    // player's offset is 0.5
    // x는 중간에 오도록 처리하고 y는 플레이어 상단 기준에서 메시지 크기 만큼 올린다. (12 is yOffset)
    if (this.container.visible) {
      this.container.x = this.player.x - this.messageWidth * 0.5;
      this.container.y =
        this.player.y - this.player.height * 0.5 - this.messageHeight - 12;
    }
  }

 

전체적인 흐름:

초기에 생성만 해놓고 메시지가 오면 리소스를 초기화하고 토스트를 뛰운다.

반복적으로 호출해도 기존 리소스를 날리고 시작하여 문제가 발생하지 않는다. 

 

Container와 Text, Graphics를 재사용하기 위해, 모든 처리가 끝났을 때

Container의 update/render를 비활성화해주고 다시 시작할 때 활성화한다.

(Graphics와 Text쪽도 사용하던 부분을 제거, 애니메이션 제거)

 

참고 자료

https://stackoverflow.com/questions/67912372/phaser3-how-to-create-a-graphic-with-text
https://phaser.discourse.group/t/is-there-any-way-to-give-a-text-object-a-border-or-background/5132

컨테이너 예제
https://phaser.io/examples/v3/view/game-objects/container/create-container

 

애니메이션 처리를 위한 tween(5년전 질문인데 잘 돌아간다..)
https://stackoverflow.com/questions/49711554/phaser-3-tween-opacity

rendering, update를 끄는 것과 오브젝트 삭제의 차이(오브젝트 풀링의 관점에서 설명)
https://phaser.discourse.group/t/best-way-to-destroy-a-object/3209/2

'프로그래밍 > Game Dev' 카테고리의 다른 글

[Phaser] 미니맵  (2) 2023.10.04
[Phaser] UI Text, Camera, Switching Scene  (0) 2023.10.03
[Phaser] Pixel bleeding 이슈  (0) 2023.10.02
[Phaser] Animation, TileMap  (0) 2023.09.28
[Node.js] 간단한 멀티 슈팅게임 소스 분석  (0) 2023.09.26

댓글