Skip to content

Instantly share code, notes, and snippets.

@rparrett
Last active June 6, 2024 21:33
Show Gist options
  • Save rparrett/3aa4761a43e70bd99c69c26dd3000df1 to your computer and use it in GitHub Desktop.
Save rparrett/3aa4761a43e70bd99c69c26dd3000df1 to your computer and use it in GitHub Desktop.
Bevy 0.13 Typewriter Effect
//! Bevy 0.13 Typewriter Effect
//!
//! License: Apache-2.0 / MIT
use bevy::prelude::*;
const TEXT: &str = "This is some text that runs on for quite a while and occupies multiple lines. \
Let's add even more so we'll wrap onto a third line.";
#[derive(Component)]
struct Typewriter(Timer);
impl Typewriter {
fn new(delay: f32) -> Self {
Self(Timer::from_seconds(delay, TimerMode::Repeating))
}
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, typewriter)
.run();
}
fn typewriter(time: Res<Time>, mut query: Query<(&mut Text, &mut Typewriter), With<Typewriter>>) {
for (mut text, mut typewriter) in query.iter_mut() {
if !typewriter.0.tick(time.delta()).just_finished() {
return;
}
while !text.sections[1].value.is_empty() {
// Remove a char from the section containing hidden characters and place
// it in the section for visible characters.
let first_hidden = text.sections[1].value.remove(0);
text.sections[0].value.push(first_hidden);
if first_hidden != ' ' {
break;
}
}
}
}
fn setup(mut commands: Commands) {
commands.spawn(Camera2dBundle::default());
let container = commands
.spawn(NodeBundle {
style: Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
..default()
})
.id();
let bg = commands
.spawn(NodeBundle {
style: Style {
width: Val::Px(680.0),
height: Val::Px(300.0),
align_items: AlignItems::FlexStart,
justify_content: JustifyContent::Center,
padding: UiRect::all(Val::Px(10.)),
..default()
},
background_color: Color::rgb(0.2, 0.2, 0.2).into(),
..default()
})
.id();
let typewriter = commands
.spawn((
TextBundle {
style: Style {
width: Val::Percent(100.),
..default()
},
text: Text::from_sections([
// The (initially empty) section that will contain visible text.
TextSection {
value: "".to_string(),
style: TextStyle::default(),
},
// The section that contains hidden text.
TextSection {
value: TEXT.into(),
style: TextStyle {
color: Color::NONE,
..default()
},
},
]),
..default()
},
Typewriter::new(0.1),
))
.id();
commands.entity(container).push_children(&[bg]);
commands.entity(bg).push_children(&[typewriter]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment