Ledge "hop" effect over certain tiles with Tiled

I was trying to make an overworld game scene to emulate a Pokemon Gen I/II gameplay in Tiled.

I have the basic world building down, im just confused on how to achieve the ledge-jumping effect over certain tiles, as seen here (not including the pikachu)

is this another sprite on the spritesheet or some sort of collision or overlap function? Any and all help would be appreciated

:wave:

You could do this by disabling the collisions for the player (e.g. player.body.checkCollision.none = true) or by using a processCallback in the player–tile collider.

It will be tricky to move the player upward when he jumps. You may need to use a second, invisible sprite that stays on the ground for correct physics movement.

2 Likes

Wow thank you so much this was more than I was expecting!

so something like a separate “ledge” tile layer if I want to have the hops happen passively and only in 1 direction? like a .setTileLocationCallback() on the ledges and handle the ledge jump direction?

Ah I didn’t realized it was automatic :smiley:

You could use setTileLocationCallback(), or the collisionCallback handler. You can find the tile gid in collisionCallback so you may not need a separate tile layer.

1 Like

I have implemented the shadow and player attached to a playerBase zone as you did in your codepen

I am trying now to implement the passive jump down off the ledge

  • “hop down” ledge indices: [811, 815, 829]
  • when moving down and colliding with these tiles, execute the spacebar jump tween down

All that happens when my spite collides with the ledges is it logs the index, no jump, no moving down a tile. Any pointers?

i have:

this.worldLayer.setTileIndexCallback(
    [811, 815, 829],
    this.hopDown,
    this);

and hopDown():

hopDown(zone, tile) {
    console.log(tile.index);
    this.add.tween({
        targets: new Phaser.Math.Vector2(),
        props: { y: { from: 0, to: -32 } },
        duration: 300,
        ease: 'Power2',
        yoyo: true,
        onComplete: () => console.log('hopDown done')
    });
    this.moveDown(); //controls zone movement and sprite anims
}

You need to do something with the tween target value. By itself it has nothing to do with the character.

i have changed

    targets: this.playerBase.body.velocity

and now he bounces when he hits a ledge but he doesnt move down past it to the next tile

In the code pen above this is done with the processPlayerGroundCollision callback.

so as I get farther along in this, it looks like I am trying to get 2 tweens to happen.

  1. vertical bounce (zone.body.velocity.y)
  2. zone position change (zone.y) to move past the ledge

I am having trouble seeing the shadow and the timing of the animation, it just looks like its skips.

I have implemented a isJumping var and return false to not collide, correct? maybe i just need to play around with delays and durations?

hopDown(zone, tile) {
    this.isJumping = true;
    this.add.tween({
        targets: zone.body.velocity,
        props: { y: { from: 0, to: -32 } },
        duration: 300,
        ease: 'Power2',
        yoyo: true,
        onComplete: () => {
            targets: zone,
            props: {
                y: { from: zone.y, to: zone.y + 64 }
            },
            duration: 300,
            ease: 'Bounce.InOut',
        });
        this.isJumping = false;
    });
    return false;

}

You have to return false from a process callback (4th argument to the collider), not a collision callback (3rd argument).

I use only one tween, for the bounce (1). I wouldn’t tween the zone body velocity at all.

Thanks so much for following me along through this @samme

Ok i have simplified the hopDown() to:

hopDown(zone: Phaser.GameObjects.Zone, tile: Phaser.Tilemaps.Tile): boolean {
    const finishJump = () => this.isJumping = false;
    const animKey: string = this.player.anims.currentAnim.key;
    const direction: string = animKey.split('-')[1];

    if (direction !== 'down') return false;

    this.isJumping = true;
    this.add.tween({
        targets: zone,
        props: { y: '+= 80' },
        duration: 500,
        repeat: 0,
        ease: 'Bounce.Out',
        onComplete: finishJump
    });
    return false;
}

and this will run as (in create())

thisworldLayer.setTileIndexCallback(
    HOPDOWN_TILES, //tile array const
    this.hopDown,
    this
);

const processGroundCollision = () => return !this.isJumping;

this.physics.add.collider(
    this.playerZone,
    this.worldLayer,
    null,
    processGroundCollision,
    this
);

and this provides a pretty dang good animation, except that i still never see the shadow appear, even when i slow down the duration.

I’d love to eventually figure that out but this all more than enough to continue building mechanics. THANKS!!