Search code examples
javascriptarraysgame-physicsphaser-framework

How to move an array of objects the same distance in Phaser 3?


I have a game in Phaser. When an arrow is in the game is fired, it is pushed to an array. The arrow hits a target, and the target moves back before the next arrow is fired. If that doesn't make sense, the arrows that are already stuck to the target, need to move with the target when it moves.

I have tried just moving the array's x value, and tried looping through the array. I have also tried just moving the this.arrows variable.

Code

function update ()
{   
    //Declare constants for movement
    const arrowMoveAmt = 1500;
    this.player.setDrag(2000);

    //Rotation of the player
    if (this.cursors.up.isDown && this.player.angle > -45) {
        this.player.angle -= angleModifier;}

    if (this.cursors.down.isDown && this.player.angle < 0) {
        this.player.angle += angleModifier;}

    //Shooting with the spacebar
    if (Phaser.Input.Keyboard.JustDown(this.spacebar)) {

        //Animate the shooting
        this.player.anims.play('shoot', true);

        //Arrow shooting
        let arrow = this.physics.add.sprite(this.player.x, (this.player.y + 20), 'arrow');

        //Make sure the arrow has a hitbox
        arrow.enableBody = true;
        //Let the arrow move
        arrow.body.immovable = false;
        //Edit arrow hitbox 
        arrow.setSize(50, 15).setOffset(5, 50);

        arrow.setGravityY(3600); //Gravity will affect the arrows
        //Arrow speeds
        arrow.setVelocityX(arrowMoveAmt);
        arrow.setVelocityY((this.player.angle * 50));

        this.arrows.push(arrow); //Add arrow to the array created earlier

        this.arrowSound.play(); //Play the sound

        //Reset the angle modifier for added difficulty
        angleModifier = (Math.random() + .1) * 2;
    }

    else if(target.body.touching.left) {

        //Variable for loop
        let i = 0;

        //Set initial position of new medals
        let firstMedalX = 180;

        //Loop to create multiple arrows
        while (i < this.arrows.length) {
            newArrows = this.arrows[i];
            newArrows.setGravityY(0);
            newArrows.setVelocityX(0);
            newArrows.setVelocityY(0);

            //Add 30 to the new medal's x position
            firstMedalX += 40;

            //Increment for every arrow shot
            i++;

            //Reset the player angle for difficulty
            this.player.angle = 0;

            //Move the target
            var x = target.x;
            target.x += 10;
            var x2 = target.x;
            var arrowMove = x2 - x;
            newArrows.x = newArrows.x + arrowMove;

            console.log("Target X = " + target.x);
            console.log("Arrows X = " + newArrows.x);

        }

        //Call the function to determine medal and pass the variable
        if(this.arrows.length <= 5) {
            //Only track the first five arrows
            getMedal(firstMedalX);
        }
    }

    //Function to decide medal, and where it goes
    getMedal = (value) => {
        //Gold medal
        if (410 < newArrows.y && newArrows.y < 435) {
            this.add.image(value, 175, 'gold_medal');
            score += 5;
        }
        //Silver medal
        else if (395 < newArrows.y && newArrows.y < 450) {
            this.add.image(value, 175, 'silver_medal');
            score += 3;
        }
        //Bronze medal
        else if (380 < newArrows.y && newArrows.y < 460) {
            this.add.image(value, 175, 'bronze_medal');
            score += 1;
        }
        else {
            this.add.image(value, 175, 'no_medal');
        }
        //Set the scoreboard to the new score
        scoreBoard.setText('SCORE: ' + score);
    }
}

Solution

  • I have found a solution:

    • First, remove the following code block from the while loop.
    //Move the target
    var x = target.x;
    target.x += 10;
    var x2 = target.x;
    var arrowMove = x2 - x;
    newArrows.x = newArrows.x + arrowMove;
    
    console.log("Target X = " + target.x);
    console.log("Arrows X = " + newArrows.x);
    
    • Second, add this line newArrows.x += 10; in the while loop after the this.player.angle = 0 line.
    • Third, right after the while loop's closing bracket, add this code:
    //Move the target
    target.x += 10;
    

    For your reference, the full code snippet of the update() method:

    function update ()
    {   
        //Declare constants for movement
        const arrowMoveAmt = 1500;
        this.player.setDrag(2000);
    
        //Rotation of the player
        if (this.cursors.up.isDown && this.player.angle > -45) {
            this.player.angle -= angleModifier;}
    
        if (this.cursors.down.isDown && this.player.angle < 0) {
            this.player.angle += angleModifier;}
    
        //Shooting with the spacebar
        if (Phaser.Input.Keyboard.JustDown(this.spacebar)) {
    
            //Animate the shooting
            this.player.anims.play('shoot', true);
    
            //Arrow shooting
            let arrow = this.physics.add.sprite(this.player.x, (this.player.y + 20), 'arrow');
    
            //Make sure the arrow has a hitbox
            arrow.enableBody = true;
            //Let the arrow move
            arrow.body.immovable = false;
            //Edit arrow hitbox 
            arrow.setSize(50, 15).setOffset(5, 50);
    
            arrow.setGravityY(3600); //Gravity will affect the arrows
            //Arrow speeds
            arrow.setVelocityX(arrowMoveAmt);
            arrow.setVelocityY((this.player.angle * 50));
    
            this.arrows.push(arrow); //Add arrow to the array created earlier
    
            this.arrowSound.play(); //Play the sound
    
            //Reset the angle modifier for added difficulty
            angleModifier = (Math.random() + .1) * 2;
        }
    
        else if(target.body.touching.left) {
    
            //Variable for loop
            let i = 0;
    
            //Set initial position of new medals
            let firstMedalX = 180;
    
            //Loop to create multiple arrows
            while (i < this.arrows.length) {
                newArrows = this.arrows[i];
                newArrows.setGravityY(0);
                newArrows.setVelocityX(0);
                newArrows.setVelocityY(0);
    
                //Add 30 to the new medal's x position
                firstMedalX += 40;
    
                //Increment for every arrow shot
                i++;
    
                //Reset the player angle for difficulty
                this.player.angle = 0;
    
                // Move the arrows
                newArrows.x += 10
    
            }
    
            //Move the target
            target.x += 10;
    
            //Call the function to determine medal and pass the variable
            if(this.arrows.length <= 5) {
                //Only track the first five arrows
                getMedal(firstMedalX);
            }
        }
    
        //Function to decide medal, and where it goes
        getMedal = (value) => {
            //Gold medal
            if (410 < newArrows.y && newArrows.y < 435) {
                this.add.image(value, 175, 'gold_medal');
                score += 5;
            }
            //Silver medal
            else if (395 < newArrows.y && newArrows.y < 450) {
                this.add.image(value, 175, 'silver_medal');
                score += 3;
            }
            //Bronze medal
            else if (380 < newArrows.y && newArrows.y < 460) {
                this.add.image(value, 175, 'bronze_medal');
                score += 1;
            }
            else {
                this.add.image(value, 175, 'no_medal');
            }
            //Set the scoreboard to the new score
            scoreBoard.setText('SCORE: ' + score);
        }
    }