« Back to Blog

Phaser Platformer Series: 18 Question Mark Box

posted on 19 July 2021

In the previous tutorial we introduced mushroom power ups to super size our hero. In Super Mario, these appear when you hit a question mark box and you have to chase them before they disappear off screen. That’s what we’ll be adding this tutorial.

When our hero hits the question mark box from underneath, the mushroom power up will appear and then race off to the left or right (this will be random).

Here is what we’ll be making:

See the Pen
Phaser Platformer Series: 18 Question Mark Box
by Digitherium (@digitherium)
on CodePen.

If you are viewing on a mobile, you can open a version of it here without all the codepen chrome taking up screen space so you play it in landscape mode.

The idea is that the question mark box has to be hit from underneath. When this is done it will reveal a powerup which will then speed off. The question mark box then changes state to show it has been hit and can’t be hit again. The key thing is going to the relationship between the question mark box and the mushroom (its contents). We need a way of saying that the mushroom is linked to this box.

The first thing we do is add a new global variable for the question mark box:

questionMarkBlock,

We also have two new sprites to preload for the active and used state of the question mark box:

this.load.image('question-mark-block', 'question-mark-block.jpg');
this.load.image('empty-box', 'empty-box.jpg');

Then we need to change our mushroom code slightly. We’ll move where it’s placed to be where the box is. We’ll also add to it the game first so it sits behind the box:

//add mushroom powerup, set it to rotate around its center and tint it orange
mushroom = this.physics.add.sprite(520, 310, 'powerup');
mushroom.setOrigin(.5, .5);
mushroom.setTintFill(0xff9800);
//disable physics, hide and turn off gravity
mushroom.enableBody = false;
mushroom.visible = false;
mushroom.body.setAllowGravity(false);

The mushroom has its visible property set to false so we can’t see it. This just keeps it tidy incase it pokes out from behind the box. Next, we add our question mark box, in the same location as the mushroom so it sits on top:

questionMarkBlock = this.physics.add.sprite(520, 310, 'question-mark-block');
questionMarkBlock.body.setAllowGravity(false);
questionMarkBlock.setImmovable(true);
questionMarkBlock.powerup = mushroom;

We turn off the gravity and set it to be immovable so it’s fixed in place. It being a javascript object, we can just add extra properties, so we link the mushroom to this box by creating a powerup property and assigning the mushroom to it. This way, when we hit the box, we’ll easily be able to grab the mushroom in the code.

Our mushroom collection code is all setup with the overlap callback collectMushroom so we just need to add physics for our question mark box:

this.physics.add.collider(player, questionMarkBlock, hitQuestionMarkBlock, null, this);

We using a collider as it’s an immovable block, and the callback looks like this:

function hitQuestionMarkBlock(player, block) {
    //if the block has been hit from the bottom and is not already hit then...
    if (block.body.touching.down && !block.hit) {
        //mark block as hit
        block.hit = true;
        //make the mushroom visible
        block.powerup.visible = true;

        //animate the rising of the mushroom powerup
        var tween = this.tweens.add({
            targets: block.powerup,
            y: "-=24",
            ease: 'Linear',
            duration: 300,
            onComplete: function() {
                //when the animation completes call this function
                emptyQuestionBlock(block);
            },
        });

        //animate the box being hit and jumping up slightly
        var tween = this.tweens.add({
            targets: block,
            y: "-=5",
            ease: 'Linear',
            yoyo: true,
            duration: 100
        });
    }
}

The code will only fire is the question mark box is hit from the bottom (block.body.touching.down). If it is hit from the bottom then we can access the mushroom powerup through the powerup property we created earlier. We tween the mushroom so it rises up out of the box, and also tween the box moving up and down to show it’s hit. When the mushroom animation finishes the function emptyQuestionBlock is called:

function emptyQuestionBlock(block) {
    //change the sprite of the question mark box
    block.setTexture("empty-box");
    //enable physics on the mushroom powerup
    block.powerup.enableBody = true;
    //turn mushroom powerups gravity back on
    block.powerup.body.setAllowGravity(true);
    //randomly assign left or right direction to the powerup
    if (Math.floor(Math.random() * 1)) block.powerup.setVelocityX(-80);
    else block.powerup.setVelocityX(80);
}

Here we change the sprite to the used state (just a brown box in our case), and reenable the physics on the powerup. A direction is randomly assigned and then x velocity is applied to send it sideways.

And that’s that, a much more complete mushroom experience. Coming soon, one way platforms.

chromeless mobile version
view all the code on codepen
download the source on github.