Chirp v0.4.2 - High-Performance RichText Typewriter & Dialogue Engine

Hello everyone,

I am pleased to share my first open-source resource with the Roblox developer community: Chirp (v0.4.0), a lightweight, high-performance RichText typewriter and dialogue engine built for modern Roblox experiences.

Many existing dialogue modules suffer from runtime performance stutters caused by frequent string allocations, broken XML tags mid-reveal, or rigid animation framework constraints. Chirp solves these challenges using a zero-GC table buffer architecture, frame-perfect grapheme rendering, and an extensible inline tag system.

Key Features

  • 60 FPS Grapheme Rendering: Leverages MaxVisibleGraphemes and RenderStepped. Unclosed RichText tags are safely handled during character reveals without exposing raw XML markup on screen.
  • Stacked Mathematical Effects: Allows developers to stack dynamic inline animation tags simultaneously (e.g., <shake><wave>text</wave></shake>) with smooth optical subpixel wave calculations.
  • Zero-GC Table Buffer Allocation: Employs pre-allocated memory buffers during render loops to eliminate Lua garbage collection frame hitches during long dialogue sequences.
  • Custom Effect API (Chirp.RegisterEffect): Enables dynamic registration of custom inline text animation tags at runtime without modifying core module files.
  • Inline Dialogue Commands: Provides control over dialogue flow mid-sentence using <pause=X>, <speed=X>, and <event=X> tags.
  • Multiplayer Synchronization: Accepts workspace:GetServerTimeNow() in the :Type() method to synchronize typewriter cutscenes across multiple client screens down to the millisecond.
  • UGC Security Sanitization: Includes a built-in Chirp.Sanitize() helper function to safeguard against RichText XML injection attacks when displaying player usernames or chat input.

Quick Setup & Code Example

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Chirp = require(ReplicatedStorage.Chirp)

-- 1. Register a custom inline effect tag
Chirp.RegisterEffect("pulse", function(index, time)
    local sizeOffset = math.sin(time * 8) * 3
    return sizeOffset, 0
end)

-- 2. Initialize a Chirp instance
local dialogue = Chirp.new(script.Parent.TextLabel, {
    Speed = 0.04,
    Preset = "Pop",
    ShowPrompt = true,
})

-- 3. Listen for inline cutscene events
dialogue.OnEventTriggered:Connect(function(eventName)
    print("Cutscene event triggered:", eventName)
end)

-- 4. Type line with stacked tags & commands
dialogue:Type("Welcome to <wave><pulse>Chirp Engine</pulse></wave>.<pause=0.5><event=camera_zoom>")

Links & Documentation

Feedback

As this is my first open-source release, I would greatly appreciate any feedback, suggestions, or bug reports in the replies below or directly on the GitHub repository.

Examples

7 Likes

I think you have a broken type file in init.luau

1 Like

Good catch! Thanks for pointing that out. Just pushed a patch closing the missing } in the type definition in v0.4.1 / latest GitHub commit. Thank you alot!

Looks promising, will try it out soon
Btw, how does this compare against Hypertext?

1 Like

Thanks for checking out Chirp! Hypertext is super clean for text animations, but Chirp was built specifically to be a full dialogue engine for RPGs and cutscenes rather than just a general text animation library.

The main difference is Chirp comes with built-in dialogue flow tags like <pause=X>, <speed=X>, and <event=X> so you can trigger cutscene events or camera shakes mid-sentence, plus procedural pitch-randomized typing sounds out of the box. It also has a simple custom effect API (Chirp.RegisterEffect) so you can write your own custom inline tags alongside nested Roblox RichText without breaking grapheme boundaries.

If you just need general rich text animations Hypertext is awesome, but if you want an all-in-one typewriter & dialogue engine for NPCs and cutscenes, that’s where Chirp shines! (jk its still on dev, but hopefully though :smiley:)

2 Likes

Chirp v0.4.2 Update is here!

Just pushed a new patch update focused on new visual presets and rendering fixes:

:sparkles: New Presets

  • Drop: Text drops down into place without pushing other letters around.
  • Elastic: Bouncy rubber-band effect that snaps in smoothly.
  • Neon: Flashes 9 bright neon colors really fast when letters appear.

:high_voltage: Fixes & Improvements

  • No More Text Shaking: Fixed letter sizes so text stays still and doesn’t jitter during wave or custom effects.
  • Looping Effects: Effects like <wave> and custom tags keep playing smoothly even after typing finishes.
  • Smoother Pop Effect: Cleaned up the animation curve so the bounce feels way better.

More information on GitHub. :smiling_face_with_three_hearts:

1 Like