Skip to main content

Crate bevy_speech_bubbles

Crate bevy_speech_bubbles 

Source
Expand description

A dialog kit for Bevy.

Three things a game says words with, on one conversation model:

  • World balloons (balloon): text rasterized on the CPU into an Image, put on a unit quad as an unlit alpha-blended material, anchored above an owner entity and turned to face a camera. No 2D camera, no UI layer — the balloon lives in the world, occludes and is occluded like anything else, and moves with the thing that said it. A BalloonSkin sets the palette, and pixel: true draws it without anti-aliasing for pixel-art games.
  • A conversation graph (conversation): authored lines and choices (DialogueScript, serde-loadable from YAML or RON), a runtime that walks them (StartConversation, ChoicePicked, ConversationEnded, DialogueNodeEntered, ConversationLock), and paced one-off Barks.
  • A screen dialog box (dialog_box): a Bevy UI surface skinned by the host’s DialogSkin, with a typewriter, a blinking caret, a name tag, a portrait and clickable, keyboard-navigable choices. Presenter picks balloons or box for conversations; barks are always balloons.

Add SpeechBubblesPlugin and the three are wired. The crate knows no game: speakers are strings the host resolves through Speakers, and it never names a game’s camera.

§Why the balloon text is rasterized here

Bevy’s text stack has no public “rasterize this string into a standalone Image” API, and a world-space balloon has no 2D camera to host a Text2d. So the glyphs go through ab_glyph into an RGBA buffer, once per line rather than per frame, and the buffer becomes a texture.

§Name your camera

SpeechBubblesPlugin and track_bubbles are generic over a camera marker component, and that is deliberate. Bevy’s Single<..> silently skips its system when the query does not match exactly one entity — so a system filtered on With<Camera3d> works perfectly until the day something spawns a second 3D camera, at which point every balloon quietly stops tracking and nothing errors. Being generic makes it impossible for this crate to express that filter.

ⓘ
app.add_plugins(bevy_speech_bubbles::SpeechBubblesPlugin::<MyMainCamera>::default());

§The font is yours to load

BubbleAssets holds a quad mesh and a FontArc, and the crate never reads a file: a library that assumed an asset path would be assuming your project layout. The dialog box takes its fonts as TextFonts in the DialogSkin.

§Cosmetic by construction

Everything runs on Time<Real>, so balloons still expire and the typewriter still types while the simulation is paused — a modal conversation that zeroed virtual time would otherwise freeze its own dialogue on screen forever. Hosts pause on ConversationLock.

The conversation runtime (input, node walking, presenting, barks) runs in PreUpdate after InputSystems, in DialogInputSet, and consumes the presses it uses with clear_just_pressed: the Space that ends a line is gone for any host system ordered .after(DialogInputSet), so it cannot also throw a stone. The cosmetic systems (typewriter, caret, pop animation, balloon tracking and expiry) stay in Update, after the host’s movement.

Re-exports§

pub use balloon::BUBBLE_ANCHOR_Y;
pub use balloon::BalloonScale;
pub use balloon::BalloonSkin;
pub use balloon::Bubble;
pub use balloon::BubbleAssets;
pub use balloon::BubbleOffsetPx;
pub use balloon::BubblePx;
pub use balloon::BubbleStyle;
pub use balloon::BubbleTtl;
pub use balloon::DefaultBalloonSkin;
pub use balloon::RenderedBubble;
pub use balloon::build_bubble;
pub use balloon::dwell_secs;
pub use balloon::expire_bubbles;
pub use balloon::track_bubbles;
pub use conversation::Bark;
pub use conversation::BarkQueue;
pub use conversation::BarkSettings;
pub use conversation::Choice;
pub use conversation::ChoicePicked;
pub use conversation::Conversation;
pub use conversation::ConversationEnded;
pub use conversation::ConversationLock;
pub use conversation::DialogueNodeEntered;
pub use conversation::DialogueScript;
pub use conversation::Node;
pub use conversation::Presenter;
pub use conversation::Speaker;
pub use conversation::Speakers;
pub use conversation::StartConversation;
pub use conversation::validate_script;
pub use dialog_box::ChoiceFocus;
pub use dialog_box::DEFAULT_CHARS_PER_SECOND;
pub use dialog_box::DIALOG_Z;
pub use dialog_box::DialogSkin;
pub use plugin::DialogInputSet;
pub use plugin::SpeechBubblesPlugin;
pub use style::BubbleKind;
pub use style::Emotion;

Modules§

balloon
World-space balloons: the CPU rasterizer, the quad tracking and expiry.
conversation
The conversation kit: an authored graph of lines and choices, the runtime that walks it, and barks.
dialog_box
The screen dialog box: a Bevy UI surface skinned by the host’s DialogSkin.
plugin
The one plugin: registers the messages and resources and schedules every system, generic over the camera marker the balloons face.
style
What a balloon looks like: its shape channel, and the affect that tints it.

Structs§

FontArc
Font implementor that wraps another concrete Font + 'static type storing in an Arc.