Week 18: Bypassing run-time physics, rewriting Time, and a new Choreography system

An animated GIF of a recording from Squirrel Away showing a new intro cutscene created using my new Choreographer class.
A fancy intro cutscene using my new Choreographer class and some simple auto-nav targets!
Also, I made some improvements to navigation trajectory styling.

tl;dr: I added support for bypassing run-time physics in Surfacer, I rewrote Time to track things differently, and I created a Choreography system to automate scripted player movement.

What happened last week?


  • I expanded my Time utility class to cover more ways of tracking time.
  • I created a new Choreography class, which I can use to play automated scripted player movement (like an intro cutscene).
  • I added another mode of operation for Surfacer in which it can entirely bypass Godot's physics system at run-time and simply update player movement to match expected state from the platform graph.

Laundry list

  • Fix a bug with walk acceleration and friction not accounting for the delta time of the current frame.
    • This was leading to inconsistent results for calculated trajectories vs run-time trajectories.
  • Add support for using the up/down keys to navigate between items in the level-select screen.
  • Fix an issue with hidden accordion overlays sometimes blocking mouse clicks in the level-select screen, due to tween-complete events not being captured correctly.
    • I switched to using Tween.tween_completed instead of Tween.tween_all_completed.
  • Add logic to configure which players may exist in each level.
    • This is important, since we don’t want to calculate the platform graph for a player if that player won’t make an appearance.
  • Add a slight smoothing factor to the camera movement.
  • Add support for conditionally bypassing Godot’s physics/collision engine at runtime:
    • Added a flag to MovementParams to toggle this.
    • Added logic in Edge classes to check edge playback duration for detecting edge-finished instead of current collision state.
    • Added logic to disable collision-checking in the Player (just clear the corresponding collision mask bits).
    • Updated Player surface-state calculations to work without relying on Godot's underlying collision state.
    • Started adding support for calculating the player’s impact surface and position given their current trajectory.
      • Abandoned this, and chose to just use the pre-existing find-closest-or-best-landing-position logic.
  • Create a new Choreographer system.
    • This supports configuring sequences of actions such as: disable user input, zoom in, navigate-to-x, cue player animation, zoom out, enable user input.
  • Add support for configuring intro “cut-scenes” per-level using the new Choreographer system.
  • Fix a regression with position-along-surface projection-onto-surface calculation.
  • Implement edge-completion detection when bypassing runtime physics.
  • Fix issues relating to the usage of actual vs modified time.
  • Consolidate some repeated navigation-state logic.
  • Move welcome-panel control from Squirrel Away to Scaffolder.
  • Update welcome-panel to show after finishing intro choreography.
  • Add a settings-screen item for toggling whether the welcome/controls overlay is shown when starting a level.
  • Add a settings-screen item for disabling the intro choreography.
  • Add settings-screen items for toggling active and preselection navigation trajectories.
  • Add a settings-screen item for toggling the navigation destination indicator.
  • Hide navigation trajectory and destination during intro choreography.
  • Fix issues with initial input and modified time.
  • Add support for skipping the intro choreography by tapping.
  • Add a function for calculating the intersection point of a line segment and a circle.
  • Update path-drawing logic to trim ends at a given radius.
  • Cleaned-up navigation trajectory annotations.
  • Add configurable SurfacerColors.
  • Add Scaffolder color defaults.
  • Fix player movement to use modified time correctly.
  • Fix a bug in my modified-play-time logic.
  • Update trajectory-matching to not re-sync if trajectory index hasn't changed over the current timestep.
    • This was causing some jitter as the trajectory-matching conflicted with the physics-based updating when the framerate was slowed.
  • Update recent-movement annotator to show actions even if no movement occurred.
  • Add logic to cancel in-progress navigation if the user presses a key.
  • Fix new path annotation end-trimming to not chop too much if the path intersects itself near the origin.
  • Fix recent regressions with camera zoom and ruler grid spacing.
  • Fix backwards jitter around fall-off-point in fall-from-floor-edge.
  • Refactor my custom Time utility.
  • Implement a custom Tween system that is configurable with our new time-tracking options.
  • Move TimeType enums into a separate file.
  • Use new ScaffolderTween in Player for dash.

Wibbly-wobbly, timey-wimey

Last week, I discovered even more edge-cases that I need to account for with different ways of tracking time. So I re-wrote my Time utility class, and I now support tracking twelve different versions of time. There was a lot to cover here, so I pulled it all out into a separate post!

What's next?

  • Show a time-slow-down effect when pressing down and seeing the planned navigation trajectory.
  • Show the expected future positions of computer players while showing planned navigation trajectories.

🎉 Cheers!

This is a simple icon representing my sabbatical.


  1. It's great that you keep these blog posts coming!

    1. :) Thanks! If nothing else, they really help me feel like I've actually done something the previous week. If I don't write something down now-a-days, I will completely forget it by the next day. Maybe next year I'll sleep more and be able to remember things...


Post a Comment