1
\$\begingroup\$

I have a top-down character object that is a Container of various parts. This character can have elements that should move along with it (think a health bar, a speech bubble) that should NOT rotate when the character rotates.

If I add it to the Container, it rotates by default. If I don't add it to the Container, the element needs to be moved separately to keep up.

Neither of those work super well for me. Is there a neat way to flag that part of a Container should not rotate with it? Or that one object should stick to another without having them be in a Container? 🤔

I have added a functional snippet below. My goal is to have the ability to rotate the character container WITHOUT rotating the text field while still having the text field follow my character when it moves.

class DemoScene extends Phaser.Scene { create () { this.character = new Phaser.GameObjects.Container(this, 100, 100); this.character.add(this.add.circle(0, 0, 35, 0x00ff00)); this.character.add(this.add.rectangle(0, 20, 40, 40, 0x009900) .setAngle(45)); this.character.add(this.add.text(40, -20, 'Hi there!')); this.add.existing(this.character); this.tweens.add({ targets: this.character, x: 400, angle: 180, repeat: -1, duration: 3000, yoyo: 1 }); } } var config = { width: 540, height: 180, scene: DemoScene, }; new Phaser.Game(config); console.clear(); document.body.style = 'margin:0;';
<script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>

\$\endgroup\$
3
  • \$\begingroup\$ So you want to billboard the healthbar graphic... \$\endgroup\$ Commented Sep 25 at 8:33
  • 1
    \$\begingroup\$ I guess? I'm not familiar with that term. Can you explain what you mean exactly? \$\endgroup\$ Commented Sep 26 at 9:16
  • 1
    \$\begingroup\$ Can you share a small / short demo, showcasing the problem. \$\endgroup\$ Commented Oct 3 at 17:37

2 Answers 2

1
\$\begingroup\$

Alright, the way I found to do it is to have a Container inside the Container that rotates while the whole thing moves, much like @PhilB suggested in the comments on the other answer.

It's not perfect, but it should do the job.

class DemoScene extends Phaser.Scene { create () { this.character = new Phaser.GameObjects.Container(this, 100, 100); this.rotatingCharacter = new Phaser.GameObjects.Container(this, 0, 0); this.rotatingCharacter.add(this.add.circle(0, 0, 35, 0x00ff00)); this.rotatingCharacter.add(this.add.rectangle(0, 20, 40, 40, 0x009900) .setAngle(45)); this.character.add(this.add.text(40, -20, 'Hi there!')); this.character.add(this.rotatingCharacter); this.add.existing(this.character); this.tweens.add({ targets: this.rotatingCharacter, angle: 180, repeat: -1, duration: 3000, yoyo: 1 }); this.tweens.add({ targets: this.character, x: 400, repeat: -1, duration: 3000, yoyo: 1 }) } } var config = { width: 540, height: 180, scene: DemoScene, }; new Phaser.Game(config); console.clear(); document.body.style = 'margin:0;';
<script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>

\$\endgroup\$
0
\$\begingroup\$

You need to consider a position close to the container. If it is a character let say it is above the head.

Transform this position in screen space. Use the screen space position as the topleft (in screen coordinates) of a rectangle that will receive the information. Then create a quad mesh (for simplicity is should be directly in screen space) that will receive a texture for your health bar or whatever.

I use this method to display the names of my characters above their heads. The mesh displaying the text is directly calculated in screen space.

When I say mesh in screen space it means the 4 vertices of the quad are calculated in screen space at the CPU level only once. So you don't need any transformation in the GPU shaders.

You can also use this for popup menus using the screen position of the mouse.

I use this for all my interfaces displayed on screen and I can move them easily by adding an offset in the vertex shaders. View of Name and popupmenu

\$\endgroup\$
7
  • \$\begingroup\$ I'm not sure how relevant that is to what I'm doing. Sorry. Is that Phaser as well? I'm working with a VERY simple 2D thing here and don't really know if what you're suggesting could be applied to my problem and if it can, how. \$\endgroup\$ Commented Oct 7 at 6:10
  • \$\begingroup\$ It's made with DirectX11, not Phaser which is 2D only if I understand well. The idea remains applicable. Define a position close to the object that could be used to display the text. I don't know about Phaser but it seems you are obliged to create another container that will move and roate independently from the character to hold the text only. Do you have the possibility to make a "gametext container" like the gameobject and make the gametext moves like the gameobject moves whitout the rotation? \$\endgroup\$ Commented Oct 7 at 6:51
  • \$\begingroup\$ Sure, but that is a lot of overhead trying to keep it positioned with the other container. I was hoping there'd be to keep it in the same Container object, but only have part of it rotate. \$\endgroup\$ Commented Oct 7 at 10:44
  • \$\begingroup\$ Can you do this : targets: this.character.circle to move rotate the circle only and the same for the rectangle or text? Of course you may have three teewns lines of code or some thing like that \$\endgroup\$ Commented Oct 7 at 14:40
  • \$\begingroup\$ A good suggestion! But the problem with that is if you rotate the rectangle separately it will just spin in place, rather than spin around the circle as if it's attached. (And also, this is a simplified example, there are other elements that would also need to rotate like that.) \$\endgroup\$ Commented Oct 8 at 7:45

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.