The Keyboard
Eight chapters of things moving on their own. Now you get to interfere.
update has always taken a second argument you've been ignoring:
keys is a dictionary telling you what is held down right now:
Two keys, that's all there is. It's enough — some of the most-played games ever made use one button.
Height, not row
Games measure a character's height upward from the ground, not downward from the top of the screen. From here on:
Bigger y now means higher, which is the opposite of everything you did in
Chapters 2 to 8. It reads better once you're jumping — "y is how high I am" is
easier to hold in your head than "y is how far down the screen I am".
Your grid still counts rows downward, so convert when you draw:
At y = 0 that's GROUND — standing on the ground line. At y = 5 it's five
rows higher up the picture. One line, in draw, and the rest of your code gets
to think in heights.
Gravity, upside down
Because y now means height, gravity subtracts:
A jump sets vy to a positive number. Gravity eats one off it every frame, so
vy goes 3, 2, 1, 0, -1, -2 — the hero rises, slows, hangs for a moment, and
comes back down. That hang at the top is not something you code. It's what
happens when a number passes through zero.
Note the order here: move first, then apply gravity. Chapter 4 did it the other way. Both work — this is the order Coin Quest uses, so it's the one we'll use from now on.
Only jump when you can
Without and state["y"] == 0, holding space lets the hero fly. Sometimes
that's the game you want. Usually it isn't.