A downloadable tool

Get this tool and 3 more for $29.99 USD
View bundle
Buy Now$7.99 USD or more

The beating heart of your game!

Pulse - A simple to use, but powerful, signals manager.

Want damage events to update your health bar, play a sound, trigger screen shake, and annoy the save system... without you personally introducing every one of those systems like it's a forced networking event?

Pulse is a signals and events framework for GameMaker. Your game broadcasts what happened, and anything that cares can react...Without the sender needing to know who is listening. 


Get the Ignition Kit bundle, featuring Pulse, Catalyst AND Statement for a discount!

Or get the Full Suite Pass bundle to get all current and future tools for one low price (price will increase each time a new tool launches, so get in early for substantial savings!)


Why you need Pulse

Because at some point in every GameMaker project, you end up repeatedly wiring 400 things together over and over in different parts of your project:

"Ok, when X happens, also tell Y... and Z... and the thing I forgot about... and the UI... and the sound... and the particles... and the save system... and..."

Pulse is how you stop doing that.

A purchase of Pulse gives you a copy of Echo free!

Your game can just say what happened

Instead of manually calling five different references, you send out little signals like this:

  • "Player took damage."
  • "Enemy died."
  • "Quest updated."
  • "Door unlocked."

Then everything that cares can react on its own. No awkward hand wiring. No "who owns this responsibility?" existential crisis.

Stuff stops being glued together

Pulse is basically a decoupling machine.

The player doesn't need to know your UI exists. Your UI doesn't need a direct reference to the player. Your systems can be swapped, removed, or rewritten without touching gameplay code.

It's the difference between "my project is a web of spaghetti" and "my project is a bunch of polite little modules that mind their own business."


It's simple to use

You can live happily with just two calls:

  • Subscribe to a signal.
  • Send a signal.

That's it. You don't need to learn any more fancy stuff. That pattern alone will save you from the coupling nightmare. When you need to you can branch out into all the other more advanced features, like PulseQuery(), but at it's core, Pulse is always trying to stay as simple as possible to use.

Your game can talk back

Sometimes you don't want to broadcast "something happened", sometimes you just want to ask "Ok...Who knows the answer to this?" Pulse can do that too, with queries!

Send out a PulseQuery and get a packet back that contains the responses of everything that was listening to the query and wanted to answer, simple but extremely powerful.

When your project gets bigger, Pulse is ready

Pulse gives you escape hatches for all the nasty real-world problems:

  • Query signals: ask a question ("who wants to handle this?") and collect answers, instead of inventing a new bespoke manager every time.
  • Priorities: so the important listeners runs first.
  • Consumable signals: so one listener can say "sweet, I got this" and stop the rest of the listeners from reacting.
  • Sender filters: so you can listen to "damage" from that enemy, not every enemy.
  • Queued dispatch: post events now, flush them later when it's safe.
  • Subscription groups: bind a pile of listeners to a state/room/UI panel and clean them up in one go.
  • Multiple buses: keep gameplay events, UI events, and debug events from stepping on each other.

It is harder to shoot yourself in the foot

Pulse tries to stay out of your way, but it also tries to keep things tidy: It works with both instances and structs, uses weak references and prunes dead listeners with its garbage collector, and gives you result enums so you can actually tell what happened (instead of guessing).

Your code becomes easier to read

Pulse nudges you toward code that sounds like a story. "When the player takes damage, update the health bar," or "When an enemy dies, drop loot," or "When a quest completes, play a stinger and show the banner."

Not "Ok so obj_player calls obj_ui_manager which calls update_health() which calls..."

If you want a tiny, lightweight signal system, Pulse does that. If you want an event layer that can carry a whole game without collapsing into chaos, then Pulse does that too.


What Pulse does

Instead of directly calling every system yourself, you simply broadcast a signal:

// Somewhere in gameplay code:
PulseSend(SIG_DAMAGE_TAKEN, { amount: 10 }, id);

And then you let systems subscribe and react independently:

// UI:
PulseSubscribe(obj_hud, SIG_DAMAGE_TAKEN, function(_data) {
    hp_bar_target = hp_bar_target - _data.amount;
});
// Audio:
PulseSubscribe(obj_audio, SIG_DAMAGE_TAKEN, function(_data) {
    audio_play_sound(snd_hit, 0, false);
});
// VFX:
PulseSubscribe(obj_vfx, SIG_DAMAGE_TAKEN, function(_data) {
    fx_screen_shake(4);
});

Same event. Multiple listeners. No hard references. No "who calls who" mess.


Key features

  • Persistent and one-shot listeners (subscribe forever, or subscribe once and auto-remove).
  • Priority ordered dispatch so important listeners run first.
  • Consumable signals so one listener can cancel the rest when appropriate.
  • Sender filters (listen to this signal only when it came from that sender).
  • Queued dispatch (post now, flush later) for safer timing.
  • Query signals (broadcast a question, collect responses) for "pick a handler" and "gather offers" style problems.
  • Listener builder API when you want tags, priorities, once, sender filters, and custom buses without a pile of parameters.
  • Subscription groups to clean up a whole bundle of listeners in one call.
  • Introspection tools for debugging: counts, dumps, and per-signal inspection.
  • Multiple independent buses via PulseController, if you want strict isolation (UI vs gameplay vs debug, etc).
  • Safety features: weak refs, pruning of dead listeners, and result enums for error checking.

Documentation

As with all of my GameMaker based tools, Pulse comes with full online documentation, including an entire API reference page and multiple common patterns that you can add to your project straight away with minimal tweaking.

Pulse Documentation


Requirements

GameMaker 2.3 or later (as long as it has structs and methods)

Echo requires 2024.8+ (as it uses gpu_set_scissor())


Support and feedback

If you run into issues or have ideas for improvements:



Part of the RefresherTowel Games Toolkits

Part of a growing suite of GameMaker tools that are designed to play nicely together. If you like this style of tooling, you might also want:

  • Catalyst - makes modifiable numbers & statistics super easy.
  • Pulse - a signals and events framework (supporting queries that allow you to ask questions instead of just broadcast signals!)
  • Statement - a state machine framework (with a fully visual in-game debugger).
  • Echo - advanced debug logging (level filtering, tags, optional stack traces, history dumps) that now comes with an advanced, yet easy to use debug UI builder!

Get them in the Ignition Kit bundle for a discount! Or buy the Full Suite Pass bundle (get access to all past and future tools) in one go!

I have been dogfooding these tools across my own projects for a long time, and I hope they make your codebase calmer, cleaner, and harder to accidentally sabotage at 2am.

Updated 1 day ago
Published 23 days ago
StatusReleased
CategoryTool
Rating
Rated 5.0 out of 5 stars
(2 total ratings)
AuthorRefresherTowel
Made withGameMaker
Tagsevent-bus, events, GameMaker, gml, publisher, pub-sub, pulse, signals, subscriber, tool
LinksDocumentation, Discord

Purchase

Get this tool and 3 more for $29.99 USD
View bundle
Buy Now$7.99 USD or more

In order to download this tool you must purchase it at or above the minimum price of $7.99 USD. You will get access to the following files:

Pulse v1.1.1 2.8 MB
Pulse v1.1.0 2.8 MB
Pulse v1.0.0 2.8 MB

Development log