Search code examples
rotationspritephaser-frameworkphaserjs

Phaser 3: Rotate a sprite and automatically rotate all subsequent sprites


I have a series of horizontally-lined sprites in Phaser 3:

const sprite1 = this.add.sprite(20, 40, 'diamonds');
const sprite2 = this.add.sprite(50, 40, 'diamonds');
const sprite3 = this.add.sprite(80, 40, 'diamonds');
const sprite4 = this.add.sprite(110, 40, 'diamonds');
const sprite5 = this.add.sprite(140, 40, 'diamonds');
const sprite6 = this.add.sprite(170, 40, 'diamonds');

which produce the following:

enter image description here

When I rotate sprite3 by 90 degrees, I want the subsequent sprites to be rotated as well as shown below:

enter image description here

If I then rotate sprite5 by 90 degrees, I want the following output:

enter image description here

I have unsuccessfully tried using Phaser.Container. Any help?


Solution

  • Well that what you want to achieve is not really possible out-of-the-box or with a container, since you would have to nest them several times. This approach can only "work" if you always rotate those specific sprites, but I assume this is not the goal. So a solution, could be to calculate the new positions of the following sprites.

    Using Vectors and an Array should make this task easy.

    Here a short demo:
    (this is just a proof of concept an would/should be optimized)

    document.body.style = 'margin:0;';
    
    var config = {
        width: 536,
        height: 183,
        scene: {
            create,
            preload,
        }
    }; 
    
    function preload () {
        this.load.spritesheet('diamonds', 'https://labs.phaser.io/assets/sprites/diamonds32x24x5.png', { frameWidth: 32, frameHeight: 24 });
    }
    
    function create () {
        this.label = this.add.text(10,10, '3 Sprite and following, will Rotate in few moments...')
            .setScale(1.15)
            .setOrigin(0)
            .setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
            
        this.diamonds = [];
        
        for(let i = 0; i < 7; i++){
             let helperSprite = this.add.sprite(100 + 40 * i, 60, 'diamonds');
             this.diamonds.push(helperSprite);
        }
        
        // First rotation
        this.time.delayedCall(1000, rotateSpriteThree90DegRight, [2], this);
        
        // Second rotation
        this.time.delayedCall(2000, rotateSpriteThree90DegRight, [4], this); 
    
        // Final message
        this.time.delayedCall(2500, () => this.label.setText('...Demo ended!') , null, this);
            
    }
    
    function rotateSpriteThree90DegRight( firstSpriteToRotateIdx ){
        let firstDiamond = this.diamonds[firstSpriteToRotateIdx];
        
        this.label.setText( 'will rotate again in a few moments...')
        
        for(let idx = firstSpriteToRotateIdx; idx < this.diamonds.length; idx++ ){
            let diamond = this.diamonds[idx];
            diamond.angle += 90;
            
            if(idx > firstSpriteToRotateIdx){
                let vector = new Phaser.Math.Vector2( diamond.x - firstDiamond.x, diamond.y - firstDiamond.y  );
                vector.normalizeRightHand();
                diamond.x = firstDiamond.x + vector.x;
                diamond.y = firstDiamond.y + vector.y;
            }
        }
    }
    
    new Phaser.Game(config);
    <script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>