Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/testbed/2d.rs
6592 views
1
//! 2d testbed
2
//!
3
//! You can switch scene by pressing the spacebar
4
5
mod helpers;
6
7
use bevy::prelude::*;
8
use helpers::Next;
9
10
fn main() {
11
let mut app = App::new();
12
app.add_plugins((DefaultPlugins,))
13
.init_state::<Scene>()
14
.add_systems(OnEnter(Scene::Shapes), shapes::setup)
15
.add_systems(OnEnter(Scene::Bloom), bloom::setup)
16
.add_systems(OnEnter(Scene::Text), text::setup)
17
.add_systems(OnEnter(Scene::Sprite), sprite::setup)
18
.add_systems(OnEnter(Scene::Gizmos), gizmos::setup)
19
.add_systems(Update, switch_scene)
20
.add_systems(Update, gizmos::draw_gizmos.run_if(in_state(Scene::Gizmos)));
21
22
#[cfg(feature = "bevy_ci_testing")]
23
app.add_systems(Update, helpers::switch_scene_in_ci::<Scene>);
24
25
app.run();
26
}
27
28
#[derive(Debug, Clone, Eq, PartialEq, Hash, States, Default)]
29
enum Scene {
30
#[default]
31
Shapes,
32
Bloom,
33
Text,
34
Sprite,
35
Gizmos,
36
}
37
38
impl Next for Scene {
39
fn next(&self) -> Self {
40
match self {
41
Scene::Shapes => Scene::Bloom,
42
Scene::Bloom => Scene::Text,
43
Scene::Text => Scene::Sprite,
44
Scene::Sprite => Scene::Gizmos,
45
Scene::Gizmos => Scene::Shapes,
46
}
47
}
48
}
49
50
fn switch_scene(
51
keyboard: Res<ButtonInput<KeyCode>>,
52
scene: Res<State<Scene>>,
53
mut next_scene: ResMut<NextState<Scene>>,
54
) {
55
if keyboard.just_pressed(KeyCode::Space) {
56
info!("Switching scene");
57
next_scene.set(scene.get().next());
58
}
59
}
60
61
mod shapes {
62
use bevy::prelude::*;
63
64
const X_EXTENT: f32 = 900.;
65
66
pub fn setup(
67
mut commands: Commands,
68
mut meshes: ResMut<Assets<Mesh>>,
69
mut materials: ResMut<Assets<ColorMaterial>>,
70
) {
71
commands.spawn((Camera2d, DespawnOnExit(super::Scene::Shapes)));
72
73
let shapes = [
74
meshes.add(Circle::new(50.0)),
75
meshes.add(CircularSector::new(50.0, 1.0)),
76
meshes.add(CircularSegment::new(50.0, 1.25)),
77
meshes.add(Ellipse::new(25.0, 50.0)),
78
meshes.add(Annulus::new(25.0, 50.0)),
79
meshes.add(Capsule2d::new(25.0, 50.0)),
80
meshes.add(Rhombus::new(75.0, 100.0)),
81
meshes.add(Rectangle::new(50.0, 100.0)),
82
meshes.add(RegularPolygon::new(50.0, 6)),
83
meshes.add(Triangle2d::new(
84
Vec2::Y * 50.0,
85
Vec2::new(-50.0, -50.0),
86
Vec2::new(50.0, -50.0),
87
)),
88
];
89
let num_shapes = shapes.len();
90
91
for (i, shape) in shapes.into_iter().enumerate() {
92
// Distribute colors evenly across the rainbow.
93
let color = Color::hsl(360. * i as f32 / num_shapes as f32, 0.95, 0.7);
94
95
commands.spawn((
96
Mesh2d(shape),
97
MeshMaterial2d(materials.add(color)),
98
Transform::from_xyz(
99
// Distribute shapes from -X_EXTENT/2 to +X_EXTENT/2.
100
-X_EXTENT / 2. + i as f32 / (num_shapes - 1) as f32 * X_EXTENT,
101
0.0,
102
0.0,
103
),
104
DespawnOnExit(super::Scene::Shapes),
105
));
106
}
107
}
108
}
109
110
mod bloom {
111
use bevy::{core_pipeline::tonemapping::Tonemapping, post_process::bloom::Bloom, prelude::*};
112
113
pub fn setup(
114
mut commands: Commands,
115
mut meshes: ResMut<Assets<Mesh>>,
116
mut materials: ResMut<Assets<ColorMaterial>>,
117
) {
118
commands.spawn((
119
Camera2d,
120
Tonemapping::TonyMcMapface,
121
Bloom::default(),
122
DespawnOnExit(super::Scene::Bloom),
123
));
124
125
commands.spawn((
126
Mesh2d(meshes.add(Circle::new(100.))),
127
MeshMaterial2d(materials.add(Color::srgb(7.5, 0.0, 7.5))),
128
Transform::from_translation(Vec3::new(-200., 0., 0.)),
129
DespawnOnExit(super::Scene::Bloom),
130
));
131
132
commands.spawn((
133
Mesh2d(meshes.add(RegularPolygon::new(100., 6))),
134
MeshMaterial2d(materials.add(Color::srgb(6.25, 9.4, 9.1))),
135
Transform::from_translation(Vec3::new(200., 0., 0.)),
136
DespawnOnExit(super::Scene::Bloom),
137
));
138
}
139
}
140
141
mod text {
142
use bevy::color::palettes;
143
use bevy::prelude::*;
144
use bevy::sprite::Anchor;
145
use bevy::text::TextBounds;
146
147
pub fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
148
commands.spawn((Camera2d, DespawnOnExit(super::Scene::Text)));
149
150
for (i, justify) in [
151
Justify::Left,
152
Justify::Right,
153
Justify::Center,
154
Justify::Justified,
155
]
156
.into_iter()
157
.enumerate()
158
{
159
let y = 230. - 150. * i as f32;
160
spawn_anchored_text(&mut commands, -300. * Vec3::X + y * Vec3::Y, justify, None);
161
spawn_anchored_text(
162
&mut commands,
163
300. * Vec3::X + y * Vec3::Y,
164
justify,
165
Some(TextBounds::new(150., 60.)),
166
);
167
}
168
169
let sans_serif = TextFont::from(asset_server.load("fonts/FiraSans-Bold.ttf"));
170
171
const NUM_ITERATIONS: usize = 10;
172
for i in 0..NUM_ITERATIONS {
173
let fraction = i as f32 / (NUM_ITERATIONS - 1) as f32;
174
175
commands.spawn((
176
Text2d::new("Bevy"),
177
sans_serif.clone(),
178
Transform::from_xyz(0.0, fraction * 200.0, i as f32)
179
.with_scale(1.0 + Vec2::splat(fraction).extend(1.))
180
.with_rotation(Quat::from_rotation_z(fraction * core::f32::consts::PI)),
181
TextColor(Color::hsla(fraction * 360.0, 0.8, 0.8, 0.8)),
182
DespawnOnExit(super::Scene::Text),
183
));
184
}
185
186
commands.spawn((
187
Text2d::new("This text is invisible."),
188
Visibility::Hidden,
189
DespawnOnExit(super::Scene::Text),
190
));
191
}
192
193
fn spawn_anchored_text(
194
commands: &mut Commands,
195
dest: Vec3,
196
justify: Justify,
197
bounds: Option<TextBounds>,
198
) {
199
commands.spawn((
200
Sprite {
201
color: palettes::css::YELLOW.into(),
202
custom_size: Some(5. * Vec2::ONE),
203
..Default::default()
204
},
205
Transform::from_translation(dest),
206
DespawnOnExit(super::Scene::Text),
207
));
208
209
for anchor in [
210
Anchor::TOP_LEFT,
211
Anchor::TOP_RIGHT,
212
Anchor::BOTTOM_RIGHT,
213
Anchor::BOTTOM_LEFT,
214
] {
215
let mut text = commands.spawn((
216
Text2d::new("L R\n"),
217
TextLayout::new_with_justify(justify),
218
Transform::from_translation(dest + Vec3::Z),
219
anchor,
220
DespawnOnExit(super::Scene::Text),
221
ShowAabbGizmo {
222
color: Some(palettes::tailwind::AMBER_400.into()),
223
},
224
children![
225
(
226
TextSpan::new(format!("{}, {}\n", anchor.x, anchor.y)),
227
TextFont::from_font_size(14.0),
228
TextColor(palettes::tailwind::BLUE_400.into()),
229
),
230
(
231
TextSpan::new(format!("{justify:?}")),
232
TextFont::from_font_size(14.0),
233
TextColor(palettes::tailwind::GREEN_400.into()),
234
),
235
],
236
));
237
if let Some(bounds) = bounds {
238
text.insert(bounds);
239
240
commands.spawn((
241
Sprite {
242
color: palettes::tailwind::GRAY_900.into(),
243
custom_size: Some(Vec2::new(bounds.width.unwrap(), bounds.height.unwrap())),
244
..Default::default()
245
},
246
Transform::from_translation(dest - Vec3::Z),
247
anchor,
248
DespawnOnExit(super::Scene::Text),
249
));
250
}
251
}
252
}
253
}
254
255
mod sprite {
256
use bevy::color::palettes::css::{BLUE, LIME, RED};
257
use bevy::prelude::*;
258
use bevy::sprite::Anchor;
259
260
pub fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
261
commands.spawn((Camera2d, DespawnOnExit(super::Scene::Sprite)));
262
for (anchor, flip_x, flip_y, color) in [
263
(Anchor::BOTTOM_LEFT, false, false, Color::WHITE),
264
(Anchor::BOTTOM_RIGHT, true, false, RED.into()),
265
(Anchor::TOP_LEFT, false, true, LIME.into()),
266
(Anchor::TOP_RIGHT, true, true, BLUE.into()),
267
] {
268
commands.spawn((
269
Sprite {
270
image: asset_server.load("branding/bevy_logo_dark.png"),
271
flip_x,
272
flip_y,
273
color,
274
..default()
275
},
276
anchor,
277
DespawnOnExit(super::Scene::Sprite),
278
));
279
}
280
}
281
}
282
283
mod gizmos {
284
use bevy::{color::palettes::css::*, prelude::*};
285
286
pub fn setup(mut commands: Commands) {
287
commands.spawn((Camera2d, DespawnOnExit(super::Scene::Gizmos)));
288
}
289
290
pub fn draw_gizmos(mut gizmos: Gizmos) {
291
gizmos.rect_2d(
292
Isometry2d::from_translation(Vec2::new(-200.0, 0.0)),
293
Vec2::new(200.0, 200.0),
294
RED,
295
);
296
gizmos
297
.circle_2d(
298
Isometry2d::from_translation(Vec2::new(-200.0, 0.0)),
299
200.0,
300
GREEN,
301
)
302
.resolution(64);
303
304
// 2d grids with all variations of outer edges on or off
305
for i in 0..4 {
306
let x = 200.0 * (1.0 + (i % 2) as f32);
307
let y = 150.0 * (0.5 - (i / 2) as f32);
308
let mut grid = gizmos.grid(
309
Vec3::new(x, y, 0.0),
310
UVec2::new(5, 4),
311
Vec2::splat(30.),
312
Color::WHITE,
313
);
314
if i & 1 > 0 {
315
grid = grid.outer_edges_x();
316
}
317
if i & 2 > 0 {
318
grid.outer_edges_y();
319
}
320
}
321
}
322
}
323
324