How to make breakable blocks like in Mario with arcade physics and tilemaps

I want to make breakable blocks like the bricks in Super Mario Bros and I want the particle effect of the block breaking apart and flying off the screen.

So far I’ve tried this on my own by replacing the tile with a Phaser.Physics.Arcade.Image game object and it causes collision to be processed on the edges so if you jump and press against a column of blocks therefore stopping the player from jumping or the player gets caught on the edge of the block or something.

Then I thought why not check for collision against the tile directly? Then removing it when the play hits the bottom of the block. Which I haven’t implemented yet because I don’t know how to do it.

Then of course I’ve wondered: how am I supposed do the particle effect? What I want is the block to split into four corners (or split into any amount of squares) then fly off the screen just like in Super Mario Bros.

How would I do it?

Hi, you are asking quite a lot of things so I will help you with something

With this you can listen for collision between player and block
this.physics.add.collider(player, block, () => {
});

I already know how to do that. I’m more of an advanced Phaser 3 user.

My last answer is stupid sorry. I would actually make two blocks in one in order to detect the collision up and down and an animation for your mysterious effect.

That’s probably too brute force. I could just do that in code. I’m really looking for example code to solve the whole problem. Creating a check against a tile directly instead of creating a game object to go over it would be what I’m looking for.

How would I do that?

Hi,
Removing the tile after collision check is easy to do.
There is many way to do it, you can make the collision inactive and set the tile not visible, or just remove the tile if you don’t need it anymore

const isTileExplode = layer.getTileAt(tile.x, tile.y);

if (isTileExplode && isTileExplode.index !== -1)
{
    layer.removeTileAt(tile.x, tile.y);
}

For the tile particle, you need a spritesheet of the tile, in multiple parts. But this add more graphics work.

Another solution, perhaps a bit overkill for your needs, i use it to explode my enemies in parts.

Use the tileset as an atlas, with every size divided by 2. For this, you need each tile as an image, and use a tool like Texture Packer to generate the json. With this json you can generate a new similar json with smaller parts. Here an example with sprites divided by 100.

    private createExplodedSprites ()
    {
        const explodedFrames = [] as any[];
        const atlasJson = require('../assets/gameSceneAssets/atlas.json');
        // console.log(atlasJson);
        atlasJson.textures[0].frames.forEach((frame) =>
        {
                for (let i = 0; i < 10; i += 1)
                {
                    for (let j = 0; j < 10; j += 1)
                    {
                        const newFrame = {
                            filename: `${frame.filename}_explode_${i}${j}`,
                            frame: {
                                h: Math.round(frame.frame.h / 10),
                                w: Math.round(frame.frame.w / 10),
                                x: Math.round(frame.frame.x + (i * frame.frame.w / 10)),
                                y: Math.round(frame.frame.y + (j * frame.frame.h / 10)),
                            },
                            rotated: frame.frame.rotated,
                            sourceSize: {
                                h: Math.round(frame.frame.h / 10),
                                w: Math.round(frame.frame.w / 10)
                            },
                            spriteSourceSize: {
                                h: Math.round(frame.frame.h / 10),
                                w: Math.round(frame.frame.w / 10),
                                x: 0,
                                y: 0
                            },
                            trimmed: frame.frame.trimmed
                        };
                        explodedFrames.push(newFrame);
                    }
                }
        });
        atlasJson.textures[0].frames.length = 0;
        atlasJson.textures[0].frames = explodedFrames;
        console.log(JSON.stringify(atlasJson));
    }

You can now use this frames for particles

1 Like

See removeTileAt() in the tile callbacks example.

If you convert tiles to sprites you should use overlap() instead of collider().

For the emitter I think you have to make a texture for the chunks and then fire one particle at a time, something like

// The tile rectangle in world coordinates
const bounds = tile.getBounds();

emitter.setFrame(1).setSpeed(-16, -16).emitParticleAt(bounds.x + 0.25 * bounds.width, bounds.y + 0.25 * bounds.height);
emitter.setFrame(2).setSpeed(16, -16).emitParticleAt(bounds.x + 0.75 * bounds.width, bounds.y + 0.25 * bounds.height);
// etc.
1 Like