In this lesson we:
Since a check already exists in the movement system to apply the environmental effect of downward pressure, that same conditional can be leveraged for jumping.
First we modify the overarching comment to include the new functionality.
//only jump while player on ground or in water (prevent multiple air jumps)
Then the conditional that checked for water can be expanded.
else if place_meeting(x, y, obj_water) {
//allows multiple jumps while in water
if keyboard_check_pressed(vk_space) {
vspeed = -6
}
//accelerates the player downward when interacting with water
vspeed += 2 * v_acceleration
}
Exiting horizontal overlaps were addressed prior by considering two scenarios, 1) where the player moved into an solid, and 2) where the solid moved into the player.
The solution provided below was to assume the player was at fault, and reverse the player's direction and movement until free of the solid. This only considered horizontal overlap scenarios.
// Smoothly exit overlapping scenarios
if place_meeting(x, y, par_solids) {
//check if hspeed is non zero
if hspeed != 0 {
//Scenario 1: Player is moving into object
//continually increase hspeed until free from instance overlap
//repeat until free from overlap
while place_meeting(x + hspeed, y, par_solids) {
hspeed = (abs(hspeed) + h_acceleration) * - sign(hspeed)
}
}
//executes if hspeed is zero
else if hspeed == 0 {
collision_obj = instance_place(x, y, par_solids)
//Scenario 2: Object is moving into stationary playe
hspeed = collision_obj.hspeed
}
}
It was discovered that the overlap is usually not the player's fault, since the player's collision code reduces speed to avoid any overlap. Instead, overlaps were caused when the player assumed every other solid was stationary when in fact the platform were not.
Therefore, attempting to exit an overlap by reversing the player's speed proved ineffective in most cases. Sometimes even causing the player to shoot out of the solid in unexpected ways. For example, when extending the above solution approach to also check for vertical speed, if a player was moving left on top a verical platform that moved up overlapping the player, the player would shoot out to the right.
To address this, the solution approach was reversed. The overlapping solid was assumed to be the cause and therefore, its movement was appied in the same direction to the player. So if the player was moving left on a platform that moved up into the player, the player would detect the overlapping solid's direction, and move in that same direction until free of the obstacle.
Scenarios numbering kept from first approach to showcase change in ordering.
// Smoothly exit overlapping scennarios by first moving with the overlapping solid or reversing direction prior
if place_meeting(x, y, par_solids) {
// Get overlapping solid
// Scenario 2: Solid is moving into player
// If overlapping solid was moving horizontally, move horizontally to escape
// If overlapping solid was moving vertically, move horizontally to escape
// Scenario 1: Player is moving into stationary solid
// If overlapping solid stationary and was moving horizontally, reverse to escape
// If overlapping solid stationary and was moving vertically, reverse to escape
}
Then to flesh out the approach
// Smoothly exit overlapping scennarios by first moving with the overlapping solid or reversing direction prior
if place_meeting(x, y, par_solids) {
// Get overlapping solid
collision_obj = instance_place(x, y, par_solids)
// Scenario 2: Solid is moving into player
// If overlapping solid was moving horizontally, move horizontally to escape
if collision_obj.hspeed != 0 {
// Continually modify position until free from instance overlap
}
// If overlapping solid was moving vertically, move horizontally to escape
else if collision_obj.vspeed != 0 {
// Continually modify position until free from instance overlap
}
// Scenario 1: Player is moving into stationary solid
// If overlapping solid stationary and was moving horizontally, reverse to escape
else if hspeed != 0 {
// Continually modify position until free from instance overlap
}
// If overlapping solid stationary and was moving vertically, reverse to escape
else if vspeed != 0 {
// Continually modify position until free from instance overlap
}
}
And finally...
// Smoothly exit overlapping scennarios by first moving with the overlapping solid or reversing direction prior
if place_meeting(x, y, par_solids) {
// Get overlapping solid
collision_obj = instance_place(x, y, par_solids)
// Scenario 2: Solid is moving into player
// If overlapping solid was moving horizontally, move horizontally to escape
if collision_obj.hspeed != 0 {
// Continually modify position until free from instance overlap
while place_meeting(x, y, par_solids) {
x = x + (abs(collision_obj.hspeed) + h_acceleration) * sign(collision_obj.hspeed)
}
}
// If overlapping solid was moving vertically, move horizontally to escape
else if collision_obj.vspeed != 0 {
// Continually modify position until free from instance overlap
while place_meeting(x, y, par_solids) {
y = y + (abs(collision_obj.vspeed) + v_acceleration) * sign(collision_obj.vspeed)
}
}
// Scenario 1: Player is moving into stationary solid
// If overlapping solid stationary and was moving horizontally, reverse to escape
else if hspeed != 0 {
// Continually modify position until free from instance overlap
while place_meeting(x, y, par_solids) {
x = x + (abs(hspeed) + h_acceleration) * - sign(hspeed)
}
}
// If overlapping solid stationary and was moving vertically, reverse to escape
else if vspeed != 0 {
// Continually modify position until free from instance overlap
while place_meeting(x, y, par_solids) {
y = y + (abs(vspeed) + v_acceleration) * - sign(vspeed)
}
}
}