Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/2d/text2d.rs
9324 views
1
//! Shows text rendering with moving, rotating and scaling text.
2
//!
3
//! Note that this uses [`Text2d`] to display text alongside your other entities in a 2D scene.
4
//!
5
//! For an example on how to render text as part of a user interface, independent from the world
6
//! viewport, you may want to look at `games/contributors.rs` or `ui/text.rs`.
7
8
use bevy::{
9
color::palettes::css::*,
10
math::ops,
11
prelude::*,
12
sprite::{Anchor, Text2dShadow},
13
text::{FontSmoothing, LineBreak, TextBounds},
14
};
15
16
fn main() {
17
App::new()
18
.add_plugins(DefaultPlugins)
19
.add_systems(Startup, setup)
20
.add_systems(
21
Update,
22
(animate_translation, animate_rotation, animate_scale),
23
)
24
.run();
25
}
26
27
#[derive(Component)]
28
struct AnimateTranslation;
29
30
#[derive(Component)]
31
struct AnimateRotation;
32
33
#[derive(Component)]
34
struct AnimateScale;
35
36
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
37
let font = asset_server.load("fonts/FiraSans-Bold.ttf");
38
let text_font = TextFont {
39
font: font.clone().into(),
40
font_size: FontSize::Px(50.0),
41
..default()
42
};
43
let text_justification = Justify::Center;
44
commands.spawn(Camera2d);
45
// Demonstrate changing translation
46
commands.spawn((
47
Text2d::new(" translation "),
48
text_font.clone(),
49
TextLayout::new_with_justify(text_justification),
50
TextBackgroundColor(Color::BLACK.with_alpha(0.5)),
51
Text2dShadow::default(),
52
AnimateTranslation,
53
));
54
// Demonstrate changing rotation
55
commands.spawn((
56
Text2d::new(" rotation "),
57
text_font.clone(),
58
TextLayout::new_with_justify(text_justification),
59
TextBackgroundColor(Color::BLACK.with_alpha(0.5)),
60
Text2dShadow::default(),
61
AnimateRotation,
62
));
63
// Demonstrate changing scale
64
commands.spawn((
65
Text2d::new(" scale "),
66
text_font,
67
TextLayout::new_with_justify(text_justification),
68
Transform::from_translation(Vec3::new(400.0, 0.0, 0.0)),
69
TextBackgroundColor(Color::BLACK.with_alpha(0.5)),
70
Text2dShadow::default(),
71
AnimateScale,
72
));
73
// Demonstrate text wrapping
74
let slightly_smaller_text_font = TextFont {
75
font: font.into(),
76
font_size: FontSize::Px(35.0),
77
..default()
78
};
79
let box_size = Vec2::new(300.0, 200.0);
80
let box_position = Vec2::new(0.0, -250.0);
81
let box_color = Color::srgb(0.25, 0.25, 0.55);
82
let text_shadow_color = box_color.darker(0.05);
83
commands.spawn((
84
Sprite::from_color(Color::srgb(0.25, 0.25, 0.55), box_size),
85
Transform::from_translation(box_position.extend(0.0)),
86
children![(
87
Text2d::new("this text wraps in the box\n(Unicode linebreaks)"),
88
slightly_smaller_text_font.clone(),
89
TextLayout::new(Justify::Left, LineBreak::WordBoundary),
90
// Wrap text in the rectangle
91
TextBounds::from(box_size),
92
// Ensure the text is drawn on top of the box
93
Transform::from_translation(Vec3::Z),
94
// Add a shadow to the text
95
Text2dShadow {
96
color: text_shadow_color,
97
..default()
98
},
99
Underline,
100
)],
101
));
102
103
let other_box_size = Vec2::new(300.0, 200.0);
104
let other_box_position = Vec2::new(320.0, -250.0);
105
commands.spawn((
106
Sprite::from_color(Color::srgb(0.25, 0.25, 0.55), other_box_size),
107
Transform::from_translation(other_box_position.extend(0.0)),
108
children![(
109
Text2d::new("this text wraps in the box\n(AnyCharacter linebreaks)"),
110
slightly_smaller_text_font.clone(),
111
TextLayout::new(Justify::Left, LineBreak::AnyCharacter),
112
// Wrap text in the rectangle
113
TextBounds::from(other_box_size),
114
// Ensure the text is drawn on top of the box
115
Transform::from_translation(Vec3::Z),
116
// Add a shadow to the text
117
Text2dShadow {
118
color: text_shadow_color,
119
..default()
120
}
121
)],
122
));
123
124
// Demonstrate font smoothing off
125
commands.spawn((
126
Text2d::new("This text has\nFontSmoothing::None\nAnd Justify::Center"),
127
slightly_smaller_text_font
128
.clone()
129
.with_font_smoothing(FontSmoothing::None),
130
TextLayout::new_with_justify(Justify::Center),
131
Transform::from_translation(Vec3::new(-400.0, -250.0, 0.0)),
132
// Add a black shadow to the text
133
Text2dShadow::default(),
134
));
135
136
let make_child = move |(text_anchor, color): (Anchor, Color)| {
137
(
138
Text2d::new(" Anchor".to_string()),
139
slightly_smaller_text_font.clone(),
140
text_anchor,
141
TextBackgroundColor(Color::WHITE.darker(0.8)),
142
Transform::from_translation(-1. * Vec3::Z),
143
children![
144
(
145
TextSpan("::".to_string()),
146
slightly_smaller_text_font.clone(),
147
TextColor(LIGHT_GREY.into()),
148
TextBackgroundColor(DARK_BLUE.into()),
149
),
150
(
151
TextSpan(format!("{text_anchor:?} ")),
152
slightly_smaller_text_font.clone(),
153
TextColor(color),
154
TextBackgroundColor(color.darker(0.3)),
155
)
156
],
157
)
158
};
159
160
commands.spawn((
161
Sprite {
162
color: Color::Srgba(LIGHT_CYAN),
163
custom_size: Some(Vec2::new(10., 10.)),
164
..Default::default()
165
},
166
Transform::from_translation(250. * Vec3::Y),
167
children![
168
make_child((Anchor::TOP_LEFT, Color::Srgba(LIGHT_SALMON))),
169
make_child((Anchor::TOP_RIGHT, Color::Srgba(LIGHT_GREEN))),
170
make_child((Anchor::BOTTOM_RIGHT, Color::Srgba(LIGHT_BLUE))),
171
make_child((Anchor::BOTTOM_LEFT, Color::Srgba(LIGHT_YELLOW))),
172
],
173
));
174
}
175
176
fn animate_translation(
177
time: Res<Time>,
178
mut query: Query<&mut Transform, (With<Text2d>, With<AnimateTranslation>)>,
179
) {
180
for mut transform in &mut query {
181
transform.translation.x = 100.0 * ops::sin(time.elapsed_secs()) - 400.0;
182
transform.translation.y = 100.0 * ops::cos(time.elapsed_secs());
183
}
184
}
185
186
fn animate_rotation(
187
time: Res<Time>,
188
mut query: Query<&mut Transform, (With<Text2d>, With<AnimateRotation>)>,
189
) {
190
for mut transform in &mut query {
191
transform.rotation = Quat::from_rotation_z(ops::cos(time.elapsed_secs()));
192
}
193
}
194
195
fn animate_scale(
196
time: Res<Time>,
197
mut query: Query<&mut Transform, (With<Text2d>, With<AnimateScale>)>,
198
) {
199
// Consider changing font-size instead of scaling the transform. Scaling a Text2D will scale the
200
// rendered quad, resulting in a pixellated look.
201
for mut transform in &mut query {
202
let scale = (ops::sin(time.elapsed_secs()) + 1.1) * 2.0;
203
transform.scale.x = scale;
204
transform.scale.y = scale;
205
}
206
}
207
208