Hiding parts of the map on Phaser JS - Game Devlog #21
Written in July 6, 2021 - 🕒 3 min. readFor those of you that don’t know, Metroidvania is probably my favorite game genre, so I decided to add a feature from Metroidvania games to Super Ollie, hidden stage parts that show up when you get close to them. Check the gif below.
For this, I will need 2 new layer properties on Tiled
, one called hideOrShowOnContact
to flag if that layer should be hidden/displayed when the player interacts with it, and one called isHidden
to flag if that layer should start hidden or not.
Now I need to loop through all my map layers to check if any of them contains these properties, something like:
// dynamicLayers is an array of Phaser.GameObjects.Group
const { dynamicLayers } = this.mapData;
Object.values(dynamicLayers).forEach((dynamicLayerGroup) => {
const layers = dynamicLayerGroup.getChildren();
layers.forEach((layer) => {
// Check layers that should be hidden/shown on contact
if (layer.hideOrShowOnContact) {
// TODO
}
});
});
With that in place, I need to create a trigger to hide/show that layer, and the best way to do it is when creating the map and the custom colliders, which I explained in my devlog #3, and since I want to create the stages on Tiled
and let the code figure out where these colliders need to be, I will create a loop that goes through all tiles to create colliders for the entire area of the layer, like the image below.
There are many tutorials on how to do this, just search for JavaScript get area 2d array and you will see some results. After creating these custom colliders, I will save them into a new property in the layer called hideOrShowOnContactTriggers
so I can use them later in the game scene.
dynamicLayer.layer.properties.forEach((property) => {
const { value, name } = property;
const customColliders = generateCustomCollidersForAreaOf2DLayer(dynamicLayer);
dynamicLayer.hideOrShowOnContactTriggers = new GameGroup({
scene,
children: customColliders,
name: dynamicLayer.layer.name,
});
// if the layer is supposed to start the game hidden, then set it's alpha to 0
if (name === 'isHidden') {
dynamicLayer.setAlpha(0);
}
});
With that logic in place, I can go back to my main loop and start the logic of the collision with the hero. First I will get all the tiles from the layer that is in the same position as the hero, if the hero is actually in contact with any of these tiles, it means that I need to trigger the layer to be hidden if the hero isn’t in contact with any of the layer’s tile, then the layer will be displayed.
// dynamicLayers is an array of Phaser.GameObjects.Group
const { dynamicLayers } = this.mapData;
Object.values(dynamicLayers).forEach((dynamicLayerGroup) => {
const layers = dynamicLayerGroup.getChildren();
layers.forEach((layer) => {
// Check layers that should be hidden/shown on contact
if (layer.hideOrShowOnContact) {
this.physics.add.overlap(layer.hideOrShowOnContactTriggers, this.player, () => {
const tiles = layer.getTilesWithinWorldXY(
this.player.body.x,
this.player.body.y,
this.player.body.width,
this.player.body.height
);
const tile = tiles.find((t) =>
t?.index >= 0
&& t.layer.name === layer.layer.name);
if (tile) {
this.tweens.add({
targets: layer,
alpha: 0,
duration: 300,
ease: 'Power2',
});
} else {
this.tweens.add({
targets: layer,
alpha: 1,
duration: 300,
ease: 'Power2',
});
}
});
}
});
});
That’s pretty much it. You can tweak the tween numbers to your liking, but the result with these numbers is quite good I think.
I’m on a perfect development spree lately, full of good ideas for game features, but I’m struggling big time into making a nice level design, please let me know if you have resources on how to get good at level design because damn, it’s hard.
See you in the next one.
Tags:
- coding
- games
- javascript
- phaser
- phaser 3
- game devlog
- gamedev
- skate platformer
- super ollie vs pebble corp
- webpack
- tiled
- metroidvania
Related posts
Post a comment
Comments
No comments yet.