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 anImage, 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. ABalloonSkinsets the palette, andpixel: truedraws 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-offBarks. - A screen dialog box (
dialog_box): a Bevy UI surface skinned by the host’sDialogSkin, with a typewriter, a blinking caret, a name tag, a portrait and clickable, keyboard-navigable choices.Presenterpicks 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
Fontimplementor that wraps another concreteFont + 'statictype storing in anArc.