Week 81: Barrier bot, go!

An animated GIF of a recording from Meteor Power showing the new barrier blocking meteors.
YOU SHALL NOT PASS!


tl;dr: Last week I implemented most of the logic for meteor-blocking barriers, and I worked through a bizarre bug with inconsistent touch-event sequencing. Alas, it was another short week for me!


What happened last week?

Highlights

  • I implemented most of the logic for meteor-blocking barriers.
  • I debugged and found a work-around for a bizarre bug involving touch events triggering inconsistently (on some machines!).

Laundry list

  • Barriers:
    • Decouple selection, control, health, and highlight logic from the Station class so it can be shared by the new BarrierPylon class.
    • Create command definitions and art for barrier-pylon-creation, barrier-pylon-move, barrier-connect, barrier-disconnect.
    • Start adding logic for selecting barrier-pylon placements and triggering build commands.
    • Enable overriding the PlayerTouchListener class.
    • Cancel the normal implicit-player-navigation command when triggering an explicit barrier-pylon-build command.
    • Update command logic to support non-station-based commands.
    • Add support for creating and recycling barrier-pylons.
    • Add support for disabling barrier-pylon-activation when there isn't more than one pylon.
    • Add barrier-activation status to the info-panel.
    • Add new CommandTypes for barrier-pylon recycling and info.
    • Hook-up most of the plumbing for barrier-pylon radial-menu buttons.
    • Hook-up the barrier-energy animation.
    • Add support for tracking barrier-pylon health and destroying them when depleted.
    • Add support for destroying meteors when colliding with barrier pylons or energy.
    • Polish the barrier-energy animation.
    • Randomize barrier-energy start frame.
  • Miscellaneous:
    • Automatically limit the window size to the monitor's size.
    • Force LevelControlPressController to use consistent event sequencing by using a separate LevelControl to capture all events within the viewport, and then only trigger digests from this control using the CollisionObject2D.input_event API.
    • Update LevelTouchListener to only process unhandled events after LevelControlPressController runs a digest.
An animated GIF of a recording from Meteor Power showing the new barrier gameplay.
The barrier bot doing his thing.

A bizarre bug involving touch events triggering inconsistently

  • I ran into a bizarre issue involving touch events triggering inconsistently.
  • I still don't fully understand why the engine was behaving the way I was seeing.
  • So I wanted to document it here, in case something similar comes up again.
  • Background:
    • I have a complex system for tracking touch events both globally and within the bounds of individual interactable regions within the level.
    • Sometimes I want to treat a global touch event differently depending on whether it also occurred within the bounds of one of the interactable regions.
    • However, Godot’s event sequencing causes the region-intersected touch events to happen later than the global touch events.
    • I previously had been relying on Godot’s `call_deferred` API to reconcile this difference between the two different event systems.
      • `call_deferred` lets you schedule a callback to run at the end of the current frame.
      • This meant that I could digest all events from either source in one consolidated place per frame, and I could assume that all event sources had resolved by then.
    • Specifically, Godot’s `CollisionObject2D.input_event` API is processed much later than the `Node._input` API for the same event.
      • https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-input
      • https://docs.godotengine.org/en/stable/classes/class_collisionobject2d.html#class-collisionobject2d-method-input-event
  • The problem:
    • The problem is that I started seeing these events happening with inconsistent sequencing!
      • I used to consistently see events happening with the following sequence:
        • Global event 1
        • Local event 1
        • Digest
        • Global event 2
        • Local event 2
        • Digest
        • ...
      • However, I started seeing events sometimes happening with an extra digest after the global event and before the corresponding local event, so it would look like this.
        • Global event 1
        • Digest     # Bad!
        • Local event 1
        • Digest
        • Global event 2
        • Local event 2
        • Digest     # Good!
        • Global event 3
        • Digest     # Bad!
        • Local event 3
        • Digest
        • ...
    • Also, for whatever reason, I only started noticing this when I switched to using my laptop.
    • This seems to indicate that either Godot sometimes processes `CollisionObject2D.input_event` on the frame after the touch occurs, or Godot sometimes triggers `call_deferred` at a different time in a frame’s lifecycle.
      • I assume neither of these are intended!
  • The solution:
    • I forced my system  to use consistent event sequencing by using a separate LevelControl to capture all events within the viewport, and then only trigger digests from this control using the CollisionObject2D.input_event API.

What's next?

  • My last week of sabbatical before going back to a real job!
  • Review my backlogs, and try to put any significant lingering framework issues into a somewhat stable state!  


🎉 Cheers!


This is a simple icon representing my sabbatical.

Comments