Raycast to check for bottom of block?

@RollinSafary : where does

this.currentDifY = this.player.y - this.__yellowBlock.y; 

go?

I’m sure that you know box’s and character’s positions and it’s origins. Any way this code will calculate it without knowing it.

var boxDistanceFromTop = box.originY * box.displayHeight;
var characterDistanceFromBottom = (1 - character.originY) * character.displayHeight;
this.normalDifY = boxDistanceFromTop + characterDistanceFromBottom;

where would i get currentDifY from & where should I place it?

this.__boxDistanceFromTop = this.__yellowBlock.originY * this.__yellowBlock.displayHeight;
this.__characterDistanceFromBottom = ( ( 1 - this.player.originY ) * this.player.displayHeight );
this.__normalDifY = ( this.__boxDistanceFromTop + this.__characterDistanceFromBottom );

if ( this.normalDifY - this.currentDifY > 0 ) {
	this.character.play ( 'fallAnimation' );
}

this is what i have in my update loop.

this.normalDifY can’t be calculated in update function, you need to calculate it out of it. Otherwise you’ll say to character to play animation on every update function execution when player will fail.
And it’s redundant calculation because it’s a constant value.
You need to skip this check if animation is already playing.

No, remove it. Tile has no blocked or touching so you have to check something else. Also you’ll need to check the sprite body blocked instead of touching.

this.physics.add.collider(
  char,
  tilemapLayer,
  function (_char, tile) {
    var charY = _char.body.center.y;
    var tileY = tile.getCenterY();

    if ((charY < tileY) && _char.body.blocked.up) {
      // Character hit tile from below.
    }
  });

So use this.player.anims.isPlaying to check if there is a playing animation. If you’ve idle animation, you can do this check based on playing animation name via this.player.animas.currentAnim.key
so in result you must have something like this in your update function.

// if you haven't idle animation
if ( this.normalDifY - this.currentDifY > 0 && !this.player.anims.isPlaying ) {
	this.character.play ( 'fallAnimation' );
}
 // if you have idle animation
if ( this.normalDifY - this.currentDifY > 0 && this.player.anims.currentAnim.key !== 'fallAnimation') {
	this.player.play ( 'fallAnimation' );
}

so I’ve come close to figuring out how to detect right before the player is about to fall off a block edge or ledge edge. But my player keeps shaking uncontrollably. How would I fix the following code to get the character to stop shaking on what should be a smooth transition to a falling animation on the way down :

State Machine / Play Animation functions :

this.ChangeState = function ( __objData ) {

	this.__objData = __objData;
	this.__player = this.__objData.player;
	this.__currentState = this.__objData.currentState;
	this.__newState = this.__objData.newState;
	this.__facing = this.__objData.facing;
	this.__idleWidth = this.__objData.idleWidth;
	this.__idleHeight = this.__objData.idleHeight;
	this.__walkWidth = this.__objData.walkWidth;
	this.__walkHeight = this.__objData.walkHeight;
	this.__jumpWidth = this.__objData.jumpWidth;
	this.__jumpHeight = this.__objData.jumpHeight;
	this.__offX = this.__objData.offX;
	this.__offY = this.__objData.offY;

	if ( this.__currentState !== this.__newState ) {

		this.__player.setState ( this.__newState );

		switch ( this.__newState ) {

			case 'idle' :

				// this.__player.body.setOffset ( this.__offX, this.__offY );
				this.__player.body.setSize ( this.__idleWidth, this.__idleHeight, false );

			break;

			case 'walk' :

				// this.__player.body.setOffset ( this.__offX, this.__offY );
				this.__player.body.setSize ( this.__walkWidth, this.__walkHeight, false );

			break;

			case 'jump' :

				// this.__player.body.setOffset ( this.__offX, this.__offY );
				this.__player.body.setSize ( this.__jumpWidth, this.__jumpHeight, false );

			break;

			case 'fall' :

				// this.__player.body.setOffset ( this.__offX, this.__offY );
				this.__player.body.setSize ( this.__jumpWidth, this.__jumpHeight, false );

			break;

		}

		return true;

	}

	return false;

}

this.__StateMachineIdle = function ( sprite, __facing ){

	this.__facing = __facing;

	if ( this.__facing === 4 ) {
		this.ChangeState ({
			player : sprite,
			currentState : this.player.sprite.state,
			newState : 'idle',
			facing : this.__facing,
			idleWidth : 84,
			idleHeight : 145,
			walkWidth : 84,
			walkHeight : 145,
			jumpWidth : 84,
			jumpHeight : 145,
			offX : 0,
			offY : 0,
		});
	}

	if ( this.__facing === 6 ) {
		this.ChangeState ({
			player : sprite,
			currentState : this.player.sprite.state,
			newState : 'idle',
			facing : this.__facing,
			idleWidth : 84,
			idleHeight : 145,
			walkWidth : 84,
			walkHeight : 145,
			jumpWidth : 84,
			jumpHeight : 145,
			offX : 0,
			offY : 0,
		});
	}

}

this.__StateMachineWalk = function ( sprite, __facing ) {

	this.__facing = __facing;

	if ( this.__facing === 4 ) {
		this.ChangeState ({
			player : sprite,
			currentState : 'idle',
			newState : 'walk',
			facing : this.__facing,
			idleWidth : 84,
			idleHeight : 145,
			walkWidth : 84,
			walkHeight : 145,
			jumpWidth : 84,
			jumpHeight : 145,
			offX : 0,
			offY : 0,
		});
	}

	if ( this.__facing === 6 ) {
		this.ChangeState ({
			player : sprite,
			currentState : 'idle',
			newState : 'walk',
			facing : this.__facing,
			idleWidth : 84,
			idleHeight : 145,
			walkWidth : 84,
			walkHeight : 145,
			jumpWidth : 84,
			jumpHeight : 145,
			offX : 0,
			offY : 0,
		})
	}

}

this.__StateMachineJump = function ( sprite, __facing ) {

	this.__facing = __facing;

	this.ChangeState
	({
		player : sprite,
		currentState : this.player.sprite.state,
		newState : 'jump',
		facing : this.__facing,
		idleWidth : 84,
		idleHeight : 145,
		walkWidth : 84,
		walkHeight : 145,
		jumpWidth : 84,
		jumpHeight : 145,
		offX : 0,  
		offY : 0,
	});

}

this.__StateMachineFall = function ( sprite, __lastVelValue ) {

	this.__lastVelValue = __lastVelValue;

	this.ChangeState
	({
		player : sprite,
		currentState : this.player.sprite.state,
		newState : 'fall',
		facing : this.__facing,
		idleWidth : 84,
		idleHeight : 145,
		walkWidth : 84,
		walkHeight : 145,
		jumpWidth : 84,
		jumpHeight : 145,
		offX : 0,
		offY : 0,
	});

}

this.__PlayIdleAnimation = function ( sprite  ) {

	// Set `Player` Animation to `idle`
	sprite.anims.play ( 'idle', true );

}

this.__PlayWalkAnimation = function ( sprite  ) {

	// Set `Player` Animation to `walk`
	sprite.anims.play ( 'walk', true );

}

this.__PlayJumpAnimation = function ( sprite  ) {

	// Set `Player` Animation to `jump`
	sprite.anims.play ( 'jump', false );

}

this.__PlayFallAnimation = function ( sprite  ) {

	// Set `Player` Animation to `fall` ( same thing as `jump )
	sprite.anims.play ( 'jump', false );

}

Main Loop :

// Player can jump while walking any direction by
// pressing the `w` key or the `up` key
if ( this.keys.w.isDown || this.keys.up.isDown ) {

	// When on `ground`
	if ( sprite.body.onFloor ( ) && sprite.anims.getCurrentKey ( ) !== "jump" ) ) {
		anims.__StateMachineJump ( sprite, this.__facing );
		anims.__CreateJump ( sprite, this.__facing, this.__velocityY, delta );
	}

}
// If not pressing `jump` key{s}
else {

	// Get `fuzzy` Y-Velocity
	this.__yFuzz = (
		Phaser.Math.Fuzzy.GreaterThan
		(
			sprite.body.velocity.y, this.__lastVelValue, 50
		)
	);

	// If on very edge of block
	if ( this.__yFuzz ) {
		// When in air
		if ( ! sprite.body.onFloor ( ) ) {
			// If the current Animation is `idle`
			if ( sprite.anims.currentAnim.key === 'idle' ) {
				// If current Animation is `playing`
				if ( sprite.anims.isPlaying ) {
					// Stop Animation{s}
					sprite.anims.stop ( );
					// Set new state to `fall`
					anims.__StateMachineFall ( sprite, this.__facing );
					// Play `fall` Animation
					anims.__PlayFallAnimation ( sprite );
				}
			}
		}
	}

}