Using A Custom Block To Fix Our Landing
Credit: This mechanic was inspired by this amazing series by griffpatch.
Falling Without Falling Through the Ground
Okay, so we’re going to start with our falling mechanic again. We’re going to create a variable called velocity y
. And we’ll put a game loop in having our character call until it reaches the color of the ground.
when @greenFlag clicked
set [velocity y v] to [0]
forever
change [velocity y v] by (-1)
change y by (velocity y)
if <touching color [#63a1ff]?> then
set [velocity y v] to [0]
end
end
So, we still have that issue where we fall through the floor, but this time, we can’t just hard-code in a y value for where the floor is because there could be more than one floor.
We need a new approach. Make a new block called fix landing and make sure that you check Run without screen refresh.
when @greenFlag clicked
set [velocity y v] to [0]
forever
change [velocity y v] by (-1)
change y by (velocity y)
if <touching color [#63a1ff]?> then
fix landing::custom // This will run without a refresh.
end
end
define fix landing
repeat until <not <touching color [#63a1ff]?>>
change y by (1) // Inch back up until we're not touching the ground anymore.
end
set [velocity y v] to [0]
Putting the Jumping Motion Back In
Putting the jumping motion back in is prertty straight forward at this point.
when @greenFlag clicked
set [velocity y v] to [0]
forever
if <key [space v] pressed?> then
set [velocity y v] to [10]
end
change [velocity y v] by (-1)
change y by (velocity y)
if <touching color [#63a1ff]?> then
fix landing::custom
end
end
define fix landing
repeat until <not <touching color [#63a1ff]?>>
change y by (1)
end
set [velocity y v] to [0]
Improving Our Block
This works, but it’s not perfect in a lot of ways. We keep inching our hero up. Here is the plan:
- Instead of letting Scratch move the character 10 steps, we’re going to write a block that moves the character slowly.
- It will keep track of the last position that it moved the character to.
- If on the next movement, we’ve gone too far,
- then move it back to the last position known to be good,
- set velocity y to 0,
- and be done with it.
Let’s see how that looks in code.
when @greenFlag clicked
set [velocity y v] to [0]
go to x: (-195) y: (-94)
forever
change [velocity y v] by (-1)
if <key [space v] pressed?> then
set [velocity y v] to [10]
end
move steps ([abs v] of (velocity y)::operators)::custom // We want to divide by a positive number, even if we're going down.
end
define move steps (steps)
repeat (steps::custom)
set [last y v] to (y position) // Keep track of where we just was.
change y by ((velocity y) / (steps::custom)) // Break it apart unto the total number of steps.
if <touching color [#63a1ff]?> then
set y to (last y) // Go back to the last known good place.
set [velocity y v] to [0] // End the jumping.
end
end
Moving Left and Right
Okay, this is similar to what we did earlier, but it’s going to be a bit more problematic this time.
when @greenFlag clicked
set [velocity y v] to [0]
set [velocity x v] to [0] // Return the x movement to 0.
go to x: (-195) y: (-94)
forever
set [velocity x v] to ((velocity x) * (0.8)) // Slow it down every tick.
change [velocity y v] by (-1)
if <key [space v] pressed?> then
set [velocity y v] to [10]
end
if <key [right arrow v] pressed?> then
change [velocity x v] by (1.5) // Start propelling them right.
end
if <key [left arrow v] pressed?> then
change [velocity x v] by (-1.5) // Start propelling them left.
end
change x by (velocity x) // Move them.
move steps ([abs v] of (velocity y)::operators)::custom
end
define move steps (steps)
repeat (steps::custom)
set [last y v] to (y position)
change y by ((velocity y) / (steps::custom))
if <touching color [#63a1ff]?> then
set y to (last y)
set [velocity y v] to [0]
end
end
Our hero is going to end up going through the walls. We need something similar here.
when @greenFlag clicked
set [velocity y v] to [0]
set [velocity x v] to [0]
go to x: (-195) y: (-94)
forever
set [velocity x v] to ((velocity x) * (0.8))
change [velocity y v] by (-1)
if <key [space v] pressed?> then
set [velocity y v] to [10]
end
if <key [right arrow v] pressed?> then
change [velocity x v] by (1.5)
end
if <key [left arrow v] pressed?> then
change [velocity x v] by (-1.5)
end
move steps (([abs v] of (velocity y)::operators) + ([abs v] of (velocity x) ::operators))::custom // We need the total number of steps both horizontal and vertical.
end
define move steps (steps)
repeat (steps::custom)
set [last x v] to (x position) // Make sure you do all of the horizontal movement first.
change x by ((velocity x) / (steps::custom))
if <touching color [#63a1ff]?> then
set x to (last x)
set [velocity x v] to [0]
end
set [last y v] to (y position)
change y by ((velocity y) / (steps::custom))
if <touching color [#63a1ff]?> then
set y to (last y)
set [velocity y v] to [0]
end
end
Okay, now things are a lot more smooth.
Removing the Ability to Jump While Jumping
This isn’t Kirby.
when @greenFlag clicked
set [velocity y v] to [0]
set [velocity x v] to [0]
go to x: (-195) y: (-94)
forever
set [velocity x v] to ((velocity x) * (0.8))
change [velocity y v] by (-1)
if <key [space v] pressed?> then
if <(jumping) = [0]> then // Make sure we're not already jumping.
set [velocity y v] to [15]
set [jumping v] to [1] // Say that we're currently jumping.
end
end
if <key [right arrow v] pressed?> then
change [velocity x v] by (1.5)
end
if <key [left arrow v] pressed?> then
change [velocity x v] by (-1.5)
end
move steps (([abs v] of (velocity y)::operators) + ([abs v] of (velocity x)::operators))::custom
end
define move steps (steps)
repeat (steps::custom)
set [last x v] to (x position)
change x by ((velocity x) / (steps::custom))
if <touching color [#63a1ff]?> then
set x to (last x)
set [velocity x v] to [0]
end
set [last y v] to (y position)
change y by ((velocity y) / (steps::custom))
if <touching color [#63a1ff]?> then
set y to (last y)
set [jumping v] to [0] // Say that we've landing on solid ground.
set [velocity y v] to [0]
end
end
Here is what it looks like now.