Devlog 2021-03-07

  • Finished cliff hopping
  • Added gap jumping
  • Added block pushing
  • Added blocks being pushed off cliff kind of
  • Broke everything, rewrote collision handling/movement code
  • Shouted my frustration at the cold, uncaring universe

Different Events

There are two classic, straight-forward styles of events in RPGs: I call them “step events” and “triggers”.

Step events are your classic events (like Verge’s zones) where when the character enters the event area, some sort of effect happens. This is good for map boundaries, stair cases, triggering cut scenes when the player character steps in a particular place, etc. (Technically my step events have some configuration which mean I can differentiate between events that I want to happen when the character just touches the edge of the event area, or if their center-point has to be inside of it; which one I use will depend on how I want to tie it to the visuals of the world.)

A trigger is something where the character must face the event area, and press a button to trigger it. These are often solid (though they don’t necessarily have to be), and are used to model doors, switches, people to talk to, soemthing interesting lying on the ground, etc. They’re something that the player is choosing to interact with directly, by pressing a button, rather than something that just sort of happens to them because they stepped in the right (or wrong) place.

I decided to add a third event that seems to be most prevalent in Zelda games, that I’m calling a “push event”. The push event has to be solid, and when you bump into it at first it acts just like a wall. After you continue pressing against it, though, then I run the event code. It’s not rocket science, but it gives me some fun things I can do with it, like requiring you to commit to jumping off of a cliff before actually doing it, or adding weight to blocks you can push – things that are in between just moving around and intentional interaction. They can keep moving through the world with only a brief interruption but also where they won’t just be flinging themselves off of cliffs or kicking boxes out of the way just because they stepped a touch too close.

So, with that I have a couple of things working now…

Hopping Off of Cliffs

cliff_jump.png

I mentioned this last week, but it’s finished now. When you push against the top of the cliff polygon, it figures out where the bottom is and plays an animation of you hopping down. Right now the height can be arbitrarily tall, but it wouldn’t be difficult to add a check for height if I wanted to. If you push against any part of the cliff that doesn’t have a “bottom” below it (e.g. the bottom of the cliff) it ignores the push and just treats it as a wall.

Jumping Over Gaps

gap_jump.png

Similar to cliff jumping, you can also define a “gap” that can be jumped. Rather than jumping vertically to the bottom, it projects across the area instead and jumps you to the other side if it’s close enough. Similar to the cliff height caveat, the jumpable gap size is currently fixed (to one tile) but could be modified by an item or skill or whatever in the game.

Pushing Blocks

block_push.png

Entities can also be set up to receive pushes, and they work like a push event but can also be moved by the event handling. I haven’t tried it yet, but these could be set up to trigger (some) events when moving, so it should be pretty straightforward to make the classic “push a block onto a floor switch” kind of puzzle! I just need to make sure I don’t inadvertently create the “push a block out of the map and it’s gone forever” kind of puzzle. I could probably leverage this for general NPCs; there’s nothing more annoying than a villager standing in the way and you just kind of have to wait for them to decide to wander out of the way.

Pushing Blocks… Off of Cliffs

block_cliff.png

I said that I haven’t tried to set up a block “stepping” on a button yet, but I wanted to immediately tackle having blocks that are being pushed trigger other push events – specifically to have them trigger a cliff jump. It actually just kind of worked once I got everything hooked up! Except when it didn’t.

Sometimes, the push just wouldn’t register with the cliff. The player kept being able to trigger it, but the block was inconsistent. I narrowed it down a little – it seemed like the more “flat” the cliff edge was to the block, the less likely it was to trigger the event. It seemed like the issue was rooted in using Godot’s move_and_slide(), a built-in function for kinematic physics bodies which produces (close-ish to) the kind of movement I wanted out of the box… except that it for some reason it was now causing issues.

Rewriting Collision, Again

I hate writing collision and movement code. When I was building SimpleQuest I actually just kind of stopped working on it for weeks (maybe months) when I hit this wall. I didn’t want to ruin my streak of work so I just plowed in. Thankfully, things are a bit easier for me this time. But not much.

It turns out move_and_slide() is a wrapper around a lower-level movement function, move_and_collide(). I didn’t especially want to write all of my own collision detection code (since it would be an enormous waste and of time and it would almost certainly be slower than using the built-in facilities, and most importantly it came with the risk of just killing my forward momentum entirely) so realizing there was a lower-level thing to fall back to was a relief. I just need to deal with the collision resolution, not the detection.

So I re-wrote the resolution. Unfortunately, push events and push events triggered by pushed objects present a lot of issues. In particular, the sliding block will begin colliding with the player first, when squeezed between the player and a push event. This means the push event never really gets the collisions. I suspect this is what was happening internally within move_and_slide() as well. Maybe! Who knows?!

Anyway it was very frustrating but after a few hours of trial and error and reams of debug logging, I think I have it mostly working now. I’m sure I will (unfortunately) have to revisit it some day (I already know it’s not working exactly how I’d like), but at least it’s kind of there now, and I can move on to the next thing. Hopefully next week will be smoother sailing.