Updated the 2D examples to make them uniform (#17237)

# Objective

Make the examples look more uniform and more polished.
following the issue #17167

## Solution

- [x] Added a minimal UI explaining how to interact with the examples
only when needed.
- [x] Used the same notation for interactions ex : "Up Arrow: Move
Forward \nLeft / Right Arrow: Turn"
- [x] Set the color to
[GRAY](https://github.com/bevyengine/bevy/pull/17237#discussion_r1907560092)
when it's not visible enough
- [x] Changed some colors to be easy on the eyes
- [x] removed the //camera comment
- [x] Unified the use of capital letters in the examples.
- [x] Simplified the mesh2d_arc offset calculations.

...

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Rob Parrett <robparrett@gmail.com>
This commit is contained in:
Radislav Myasnikov 2025-01-23 17:46:58 +01:00 committed by GitHub
parent 9bc0ae33c3
commit 94e0e1f031
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 167 additions and 141 deletions

View File

@ -31,4 +31,15 @@ fn draw_cursor(
fn setup(mut commands: Commands) {
commands.spawn(Camera2d);
// Create a minimal UI explaining how to interact with the example
commands.spawn((
Text::new("Move the mouse to see the circle follow your cursor."),
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),
..default()
},
));
}

View File

@ -63,7 +63,7 @@ fn setup(
Text::default(),
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
top: Val::Px(12.0),
left: Val::Px(12.0),
..default()
},

View File

@ -201,6 +201,7 @@ const OFFSET_Y: f32 = 75.;
fn setup(mut commands: Commands) {
commands.spawn(Camera2d);
commands.spawn((
Transform::from_xyz(-OFFSET_X, OFFSET_Y, 0.),
Shape::Circle(Circle::new(45.)),
@ -259,7 +260,7 @@ fn setup(mut commands: Commands) {
Text::default(),
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
top: Val::Px(12.0),
left: Val::Px(12.0),
..default()
},

View File

@ -38,10 +38,9 @@ struct MyProcGenImage(Handle<Image>);
struct SeededRng(ChaCha8Rng);
fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
// spawn a camera
commands.spawn(Camera2d);
// create an image that we are going to draw into
// Create an image that we are going to draw into
let mut image = Image::new_fill(
// 2D image of size 256x256
Extent3d {
@ -57,8 +56,8 @@ fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD,
);
// to make it extra fancy, we can set the Alpha of each pixel
// so that it fades out in a circular fashion
// To make it extra fancy, we can set the Alpha of each pixel,
// so that it fades out in a circular fashion.
for y in 0..IMAGE_HEIGHT {
for x in 0..IMAGE_WIDTH {
let center = Vec2::new(IMAGE_WIDTH as f32 / 2.0, IMAGE_HEIGHT as f32 / 2.0);
@ -66,22 +65,22 @@ fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
let r = Vec2::new(x as f32, y as f32).distance(center);
let a = 1.0 - (r / max_radius).clamp(0.0, 1.0);
// here we will set the A value by accessing the raw data bytes
// Here we will set the A value by accessing the raw data bytes.
// (it is the 4th byte of each pixel, as per our `TextureFormat`)
// find our pixel by its coordinates
// Find our pixel by its coordinates
let pixel_bytes = image.pixel_bytes_mut(UVec3::new(x, y, 0)).unwrap();
// convert our f32 to u8
// Convert our f32 to u8
pixel_bytes[3] = (a * u8::MAX as f32) as u8;
}
}
// add it to Bevy's assets, so it can be used for rendering
// Add it to Bevy's assets, so it can be used for rendering
// this will give us a handle we can use
// (to display it in a sprite, or as part of UI, etc.)
let handle = images.add(image);
// create a sprite entity using our image
// Create a sprite entity using our image
commands.spawn(Sprite::from_image(handle.clone()));
commands.insert_resource(MyProcGenImage(handle));
@ -95,7 +94,7 @@ fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
fn draw(
my_handle: Res<MyProcGenImage>,
mut images: ResMut<Assets<Image>>,
// used to keep track of where we are
// Used to keep track of where we are
mut i: Local<u32>,
mut draw_color: Local<Color>,
mut seeded_rng: ResMut<SeededRng>,

View File

@ -63,7 +63,6 @@ fn setup(
Transform::from_scale(150.0 * Vec3::ONE),
));
// Add a camera
commands.spawn(Camera2d);
}

View File

@ -15,6 +15,7 @@ fn setup(
mut materials: ResMut<Assets<ColorMaterial>>,
) {
commands.spawn(Camera2d);
commands.spawn((
Mesh2d(meshes.add(Rectangle::default())),
MeshMaterial2d(materials.add(Color::from(PURPLE))),

View File

@ -5,7 +5,7 @@
use std::f32::consts::FRAC_PI_2;
use bevy::{
color::palettes::css::{BLUE, DARK_SLATE_GREY, RED},
color::palettes::css::{BLUE, GRAY, RED},
math::{
bounding::{Bounded2d, BoundingVolume},
Isometry2d,
@ -42,16 +42,14 @@ fn setup(
commands.spawn((
Camera2d,
Camera {
clear_color: ClearColorConfig::Custom(DARK_SLATE_GREY.into()),
clear_color: ClearColorConfig::Custom(GRAY.into()),
..default()
},
));
const UPPER_Y: f32 = 50.0;
const LOWER_Y: f32 = -50.0;
const FIRST_X: f32 = -450.0;
const OFFSET: f32 = 100.0;
const NUM_SLICES: i32 = 8;
const SPACING_X: f32 = 100.0;
const OFFSET_X: f32 = SPACING_X * (NUM_SLICES - 1) as f32 / 2.0;
// This draws NUM_SLICES copies of the Bevy logo as circular sectors and segments,
// with successively larger angles up to a complete circle.
@ -70,7 +68,7 @@ fn setup(
Mesh2d(meshes.add(sector_mesh)),
MeshMaterial2d(material.clone()),
Transform {
translation: Vec3::new(FIRST_X + OFFSET * i as f32, 2.0 * UPPER_Y, 0.0),
translation: Vec3::new(SPACING_X * i as f32 - OFFSET_X, 50.0, 0.0),
rotation: Quat::from_rotation_z(sector_angle),
..default()
},
@ -94,7 +92,7 @@ fn setup(
Mesh2d(meshes.add(segment_mesh)),
MeshMaterial2d(material.clone()),
Transform {
translation: Vec3::new(FIRST_X + OFFSET * i as f32, LOWER_Y, 0.0),
translation: Vec3::new(SPACING_X * i as f32 - OFFSET_X, -50.0, 0.0),
rotation: Quat::from_rotation_z(segment_angle),
..default()
},

View File

@ -115,7 +115,6 @@ fn star(
Mesh2d(meshes.add(star)),
));
// Spawn the camera
commands.spawn(Camera2d);
}
@ -126,7 +125,7 @@ pub struct ColoredMesh2d;
/// Custom pipeline for 2d meshes with vertex colors
#[derive(Resource)]
pub struct ColoredMesh2dPipeline {
/// this pipeline wraps the standard [`Mesh2dPipeline`]
/// This pipeline wraps the standard [`Mesh2dPipeline`]
mesh2d_pipeline: Mesh2dPipeline,
}

View File

@ -32,7 +32,6 @@ fn setup(
let mesh_handle = meshes.add(mesh);
// Spawn camera
commands.spawn(Camera2d);
// Spawn the quad with vertex colors

View File

@ -12,16 +12,17 @@ fn main() {
#[derive(Component)]
enum Direction {
Up,
Down,
Left,
Right,
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2d);
commands.spawn((
Sprite::from_image(asset_server.load("branding/icon.png")),
Transform::from_xyz(100., 0., 0.),
Direction::Up,
Transform::from_xyz(0., 0., 0.),
Direction::Right,
));
}
@ -30,14 +31,14 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
fn sprite_movement(time: Res<Time>, mut sprite_position: Query<(&mut Direction, &mut Transform)>) {
for (mut logo, mut transform) in &mut sprite_position {
match *logo {
Direction::Up => transform.translation.y += 150. * time.delta_secs(),
Direction::Down => transform.translation.y -= 150. * time.delta_secs(),
Direction::Right => transform.translation.x += 150. * time.delta_secs(),
Direction::Left => transform.translation.x -= 150. * time.delta_secs(),
}
if transform.translation.y > 200. {
*logo = Direction::Down;
} else if transform.translation.y < -200. {
*logo = Direction::Up;
if transform.translation.x > 200. {
*logo = Direction::Left;
} else if transform.translation.x < -200. {
*logo = Direction::Right;
}
}
}

View File

@ -1,6 +1,7 @@
//! Shows how to create graphics that snap to the pixel grid by rendering to a texture in 2D
use bevy::{
color::palettes::css::GRAY,
prelude::*,
render::{
camera::RenderTarget,
@ -50,18 +51,18 @@ struct OuterCamera;
struct Rotate;
fn setup_sprite(mut commands: Commands, asset_server: Res<AssetServer>) {
// the sample sprite that will be rendered to the pixel-perfect canvas
// The sample sprite that will be rendered to the pixel-perfect canvas
commands.spawn((
Sprite::from_image(asset_server.load("pixel/bevy_pixel_dark.png")),
Transform::from_xyz(-40., 20., 2.),
Transform::from_xyz(-45., 20., 2.),
Rotate,
PIXEL_PERFECT_LAYERS,
));
// the sample sprite that will be rendered to the high-res "outer world"
// The sample sprite that will be rendered to the high-res "outer world"
commands.spawn((
Sprite::from_image(asset_server.load("pixel/bevy_pixel_light.png")),
Transform::from_xyz(-40., -20., 2.),
Transform::from_xyz(-45., -20., 2.),
Rotate,
HIGH_RES_LAYERS,
));
@ -76,7 +77,7 @@ fn setup_mesh(
commands.spawn((
Mesh2d(meshes.add(Capsule2d::default())),
MeshMaterial2d(materials.add(Color::BLACK)),
Transform::from_xyz(40., 0., 2.).with_scale(Vec3::splat(32.)),
Transform::from_xyz(25., 0., 2.).with_scale(Vec3::splat(32.)),
Rotate,
PIXEL_PERFECT_LAYERS,
));
@ -89,7 +90,7 @@ fn setup_camera(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
..default()
};
// this Image serves as a canvas representing the low-resolution game screen
// This Image serves as a canvas representing the low-resolution game screen
let mut canvas = Image {
texture_descriptor: TextureDescriptor {
label: None,
@ -106,18 +107,19 @@ fn setup_camera(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
..default()
};
// fill image.data with zeroes
// Fill image.data with zeroes
canvas.resize(canvas_size);
let image_handle = images.add(canvas);
// this camera renders whatever is on `PIXEL_PERFECT_LAYERS` to the canvas
// This camera renders whatever is on `PIXEL_PERFECT_LAYERS` to the canvas
commands.spawn((
Camera2d,
Camera {
// render before the "main pass" camera
// Render before the "main pass" camera
order: -1,
target: RenderTarget::Image(image_handle.clone().into()),
clear_color: ClearColorConfig::Custom(GRAY.into()),
..default()
},
Msaa::Off,
@ -125,10 +127,10 @@ fn setup_camera(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
PIXEL_PERFECT_LAYERS,
));
// spawn the canvas
// Spawn the canvas
commands.spawn((Sprite::from_image(image_handle), Canvas, HIGH_RES_LAYERS));
// the "outer" camera renders whatever is on `HIGH_RES_LAYERS` to the screen.
// The "outer" camera renders whatever is on `HIGH_RES_LAYERS` to the screen.
// here, the canvas and one of the sample sprites will be rendered by this camera
commands.spawn((Camera2d, Msaa::Off, OuterCamera, HIGH_RES_LAYERS));
}

View File

@ -20,23 +20,23 @@ fn main() {
.run();
}
/// player component
/// Player component
#[derive(Component)]
struct Player {
/// linear speed in meters per second
/// Linear speed in meters per second
movement_speed: f32,
/// rotation speed in radians per second
/// Rotation speed in radians per second
rotation_speed: f32,
}
/// snap to player ship behavior
/// Snap to player ship behavior
#[derive(Component)]
struct SnapToPlayer;
/// rotate to face player ship behavior
/// Rotate to face player ship behavior
#[derive(Component)]
struct RotateToPlayer {
/// rotation speed in radians per second
/// Rotation speed in radians per second
rotation_speed: f32,
}
@ -54,22 +54,32 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
let enemy_a_handle = asset_server.load("textures/simplespace/enemy_A.png");
let enemy_b_handle = asset_server.load("textures/simplespace/enemy_B.png");
// 2D orthographic camera
commands.spawn(Camera2d);
// Create a minimal UI explaining how to interact with the example
commands.spawn((
Text::new("Up Arrow: Move Forward\nLeft / Right Arrow: Turn"),
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),
..default()
},
));
let horizontal_margin = BOUNDS.x / 4.0;
let vertical_margin = BOUNDS.y / 4.0;
// player controlled ship
// Player controlled ship
commands.spawn((
Sprite::from_image(ship_handle),
Player {
movement_speed: 500.0, // meters per second
rotation_speed: f32::to_radians(360.0), // degrees per second
movement_speed: 500.0, // Meters per second
rotation_speed: f32::to_radians(360.0), // Degrees per second
},
));
// enemy that snaps to face the player spawns on the bottom and left
// Enemy that snaps to face the player spawns on the bottom and left
commands.spawn((
Sprite::from_image(enemy_a_handle.clone()),
Transform::from_xyz(0.0 - horizontal_margin, 0.0, 0.0),
@ -81,19 +91,19 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
SnapToPlayer,
));
// enemy that rotates to face the player enemy spawns on the top and right
// Enemy that rotates to face the player enemy spawns on the top and right
commands.spawn((
Sprite::from_image(enemy_b_handle.clone()),
Transform::from_xyz(0.0 + horizontal_margin, 0.0, 0.0),
RotateToPlayer {
rotation_speed: f32::to_radians(45.0), // degrees per second
rotation_speed: f32::to_radians(45.0), // Degrees per second
},
));
commands.spawn((
Sprite::from_image(enemy_b_handle),
Transform::from_xyz(0.0, 0.0 + vertical_margin, 0.0),
RotateToPlayer {
rotation_speed: f32::to_radians(90.0), // degrees per second
rotation_speed: f32::to_radians(90.0), // Degrees per second
},
));
}
@ -121,21 +131,21 @@ fn player_movement_system(
movement_factor += 1.0;
}
// update the ship rotation around the Z axis (perpendicular to the 2D plane of the screen)
// Update the ship rotation around the Z axis (perpendicular to the 2D plane of the screen)
transform.rotate_z(rotation_factor * ship.rotation_speed * time.delta_secs());
// get the ship's forward vector by applying the current rotation to the ships initial facing
// Get the ship's forward vector by applying the current rotation to the ships initial facing
// vector
let movement_direction = transform.rotation * Vec3::Y;
// get the distance the ship will move based on direction, the ship's movement speed and delta
// Get the distance the ship will move based on direction, the ship's movement speed and delta
// time
let movement_distance = movement_factor * ship.movement_speed * time.delta_secs();
// create the change in translation using the new movement direction and distance
// Create the change in translation using the new movement direction and distance
let translation_delta = movement_direction * movement_distance;
// update the ship translation with our new translation delta
// Update the ship translation with our new translation delta
transform.translation += translation_delta;
// bound the ship within the invisible level bounds
// Bound the ship within the invisible level bounds
let extents = Vec3::from((BOUNDS / 2.0, 0.0));
transform.translation = transform.translation.min(extents).max(-extents);
}
@ -145,18 +155,18 @@ fn snap_to_player_system(
mut query: Query<&mut Transform, (With<SnapToPlayer>, Without<Player>)>,
player_transform: Single<&Transform, With<Player>>,
) {
// get the player translation in 2D
// Get the player translation in 2D
let player_translation = player_transform.translation.xy();
for mut enemy_transform in &mut query {
// get the vector from the enemy ship to the player ship in 2D and normalize it.
// Get the vector from the enemy ship to the player ship in 2D and normalize it.
let to_player = (player_translation - enemy_transform.translation.xy()).normalize();
// get the quaternion to rotate from the initial enemy facing direction to the direction
// Get the quaternion to rotate from the initial enemy facing direction to the direction
// facing the player
let rotate_to_player = Quat::from_rotation_arc(Vec3::Y, to_player.extend(0.));
// rotate the enemy to face the player
// Rotate the enemy to face the player
enemy_transform.rotation = rotate_to_player;
}
}
@ -187,50 +197,50 @@ fn rotate_to_player_system(
mut query: Query<(&RotateToPlayer, &mut Transform), Without<Player>>,
player_transform: Single<&Transform, With<Player>>,
) {
// get the player translation in 2D
// Get the player translation in 2D
let player_translation = player_transform.translation.xy();
for (config, mut enemy_transform) in &mut query {
// get the enemy ship forward vector in 2D (already unit length)
// Get the enemy ship forward vector in 2D (already unit length)
let enemy_forward = (enemy_transform.rotation * Vec3::Y).xy();
// get the vector from the enemy ship to the player ship in 2D and normalize it.
// Get the vector from the enemy ship to the player ship in 2D and normalize it.
let to_player = (player_translation - enemy_transform.translation.xy()).normalize();
// get the dot product between the enemy forward vector and the direction to the player.
// Get the dot product between the enemy forward vector and the direction to the player.
let forward_dot_player = enemy_forward.dot(to_player);
// if the dot product is approximately 1.0 then the enemy is already facing the player and
// If the dot product is approximately 1.0 then the enemy is already facing the player and
// we can early out.
if (forward_dot_player - 1.0).abs() < f32::EPSILON {
continue;
}
// get the right vector of the enemy ship in 2D (already unit length)
// Get the right vector of the enemy ship in 2D (already unit length)
let enemy_right = (enemy_transform.rotation * Vec3::X).xy();
// get the dot product of the enemy right vector and the direction to the player ship.
// if the dot product is negative them we need to rotate counter clockwise, if it is
// Get the dot product of the enemy right vector and the direction to the player ship.
// If the dot product is negative them we need to rotate counter clockwise, if it is
// positive we need to rotate clockwise. Note that `copysign` will still return 1.0 if the
// dot product is 0.0 (because the player is directly behind the enemy, so perpendicular
// with the right vector).
let right_dot_player = enemy_right.dot(to_player);
// determine the sign of rotation from the right dot player. We need to negate the sign
// Determine the sign of rotation from the right dot player. We need to negate the sign
// here as the 2D bevy co-ordinate system rotates around +Z, which is pointing out of the
// screen. Due to the right hand rule, positive rotation around +Z is counter clockwise and
// negative is clockwise.
let rotation_sign = -f32::copysign(1.0, right_dot_player);
// limit rotation so we don't overshoot the target. We need to convert our dot product to
// Limit rotation so we don't overshoot the target. We need to convert our dot product to
// an angle here so we can get an angle of rotation to clamp against.
let max_angle = ops::acos(forward_dot_player.clamp(-1.0, 1.0)); // clamp acos for safety
let max_angle = ops::acos(forward_dot_player.clamp(-1.0, 1.0)); // Clamp acos for safety
// calculate angle of rotation with limit
// Calculate angle of rotation with limit
let rotation_angle =
rotation_sign * (config.rotation_speed * time.delta_secs()).min(max_angle);
// rotate the enemy to face the player
// Rotate the enemy to face the player
enemy_transform.rotate_z(rotation_angle);
}
}

View File

@ -11,6 +11,7 @@ fn main() {
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2d);
commands.spawn(Sprite::from_image(
asset_server.load("branding/bevy_bird_dark.png"),
));

View File

@ -14,9 +14,9 @@ fn main() {
.add_systems(
Update,
(
// press the right arrow key to animate the right sprite
// Press the right arrow key to animate the right sprite
trigger_animation::<RightSprite>.run_if(input_just_pressed(KeyCode::ArrowRight)),
// press the left arrow key to animate the left sprite
// Press the left arrow key to animate the left sprite
trigger_animation::<LeftSprite>.run_if(input_just_pressed(KeyCode::ArrowLeft)),
),
)
@ -25,7 +25,7 @@ fn main() {
// This system runs when the user clicks the left arrow key or right arrow key
fn trigger_animation<S: Component>(mut animation: Single<&mut AnimationConfig, With<S>>) {
// we create a new timer when the animation is triggered
// We create a new timer when the animation is triggered
animation.frame_timer = AnimationConfig::timer_from_fps(animation.fps);
}
@ -56,7 +56,7 @@ impl AnimationConfig {
// `last_sprite_index` (both defined in `AnimationConfig`).
fn execute_animations(time: Res<Time>, mut query: Query<(&mut AnimationConfig, &mut Sprite)>) {
for (mut config, mut sprite) in &mut query {
// we track how long the current sprite has been displayed for
// We track how long the current sprite has been displayed for
config.frame_timer.tick(time.delta());
// If it has been displayed for the user-defined amount of time (fps)...
@ -89,17 +89,28 @@ fn setup(
) {
commands.spawn(Camera2d);
// load the sprite sheet using the `AssetServer`
// Create a minimal UI explaining how to interact with the example
commands.spawn((
Text::new("Left Arrow: Animate Left Sprite\nRight Arrow: Animate Right Sprite"),
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),
..default()
},
));
// Load the sprite sheet using the `AssetServer`
let texture = asset_server.load("textures/rpg/chars/gabe/gabe-idle-run.png");
// the sprite sheet has 7 sprites arranged in a row, and they are all 24px x 24px
// The sprite sheet has 7 sprites arranged in a row, and they are all 24px x 24px
let layout = TextureAtlasLayout::from_grid(UVec2::splat(24), 7, 1, None, None);
let texture_atlas_layout = texture_atlas_layouts.add(layout);
// the first (left-hand) sprite runs at 10 FPS
// The first (left-hand) sprite runs at 10 FPS
let animation_config_1 = AnimationConfig::new(1, 6, 10);
// create the first (left-hand) sprite
// Create the first (left-hand) sprite
commands.spawn((
Sprite {
image: texture.clone(),
@ -109,15 +120,15 @@ fn setup(
}),
..default()
},
Transform::from_scale(Vec3::splat(6.0)).with_translation(Vec3::new(-50.0, 0.0, 0.0)),
Transform::from_scale(Vec3::splat(6.0)).with_translation(Vec3::new(-70.0, 0.0, 0.0)),
LeftSprite,
animation_config_1,
));
// the second (right-hand) sprite runs at 20 FPS
// The second (right-hand) sprite runs at 20 FPS
let animation_config_2 = AnimationConfig::new(1, 6, 20);
// create the second (right-hand) sprite
// Create the second (right-hand) sprite
commands.spawn((
Sprite {
image: texture.clone(),
@ -127,19 +138,8 @@ fn setup(
}),
..Default::default()
},
Transform::from_scale(Vec3::splat(6.0)).with_translation(Vec3::new(50.0, 0.0, 0.0)),
Transform::from_scale(Vec3::splat(6.0)).with_translation(Vec3::new(70.0, 0.0, 0.0)),
RightSprite,
animation_config_2,
));
// create a minimal UI explaining how to interact with the example
commands.spawn((
Text::new("Left Arrow Key: Animate Left Sprite\nRight Arrow Key: Animate Right Sprite"),
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),
..default()
},
));
}

View File

@ -11,6 +11,7 @@ fn main() {
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2d);
commands.spawn(Sprite {
image: asset_server.load("branding/bevy_bird_dark.png"),
// Flip the logo to the left

View File

@ -49,7 +49,9 @@ fn setup(
let texture_atlas_layout = texture_atlas_layouts.add(layout);
// Use only the subset of sprites in the sheet that make up the run animation
let animation_indices = AnimationIndices { first: 1, last: 6 };
commands.spawn(Camera2d);
commands.spawn((
Sprite::from_atlas_image(
texture,

View File

@ -107,6 +107,7 @@ fn spawn_sprites(
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2d);
let font = asset_server.load("fonts/FiraSans-Bold.ttf");
let style = TextFont {
font: font.clone(),
@ -120,7 +121,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
spawn_sprites(
&mut commands,
handle_1,
Vec3::new(-600.0, 200.0, 0.0),
Vec3::new(-600.0, 150.0, 0.0),
200.0,
style.clone(),
40.,
@ -129,7 +130,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
spawn_sprites(
&mut commands,
handle_2,
Vec3::new(-600.0, -200.0, 0.0),
Vec3::new(-600.0, -150.0, 0.0),
80.0,
style,
40.,

View File

@ -20,6 +20,7 @@ struct AnimationState {
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2d);
commands.insert_resource(AnimationState {
min: 128.0,
max: 512.0,

View File

@ -41,7 +41,6 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
..default()
};
let text_justification = JustifyText::Center;
// 2d camera
commands.spawn(Camera2d);
// Demonstrate changing translation
commands.spawn((
@ -75,7 +74,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
let box_position = Vec2::new(0.0, -250.0);
commands
.spawn((
Sprite::from_color(Color::srgb(0.25, 0.25, 0.75), box_size),
Sprite::from_color(Color::srgb(0.25, 0.25, 0.55), box_size),
Transform::from_translation(box_position.extend(0.0)),
))
.with_children(|builder| {
@ -85,7 +84,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
TextLayout::new(JustifyText::Left, LineBreak::WordBoundary),
// Wrap text in the rectangle
TextBounds::from(box_size),
// ensure the text is drawn on top of the box
// Ensure the text is drawn on top of the box
Transform::from_translation(Vec3::Z),
));
});
@ -94,7 +93,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
let other_box_position = Vec2::new(320.0, -250.0);
commands
.spawn((
Sprite::from_color(Color::srgb(0.20, 0.3, 0.70), other_box_size),
Sprite::from_color(Color::srgb(0.25, 0.25, 0.55), other_box_size),
Transform::from_translation(other_box_position.extend(0.0)),
))
.with_children(|builder| {
@ -104,7 +103,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
TextLayout::new(JustifyText::Left, LineBreak::AnyCharacter),
// Wrap text in the rectangle
TextBounds::from(other_box_size),
// ensure the text is drawn on top of the box
// Ensure the text is drawn on top of the box
Transform::from_translation(Vec3::Z),
));
});
@ -130,10 +129,10 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
))
.with_children(|commands| {
for (text_anchor, color) in [
(Anchor::TopLeft, Color::Srgba(RED)),
(Anchor::TopRight, Color::Srgba(LIME)),
(Anchor::BottomRight, Color::Srgba(BLUE)),
(Anchor::BottomLeft, Color::Srgba(YELLOW)),
(Anchor::TopLeft, Color::Srgba(LIGHT_SALMON)),
(Anchor::TopRight, Color::Srgba(LIGHT_GREEN)),
(Anchor::BottomRight, Color::Srgba(LIGHT_BLUE)),
(Anchor::BottomLeft, Color::Srgba(LIGHT_YELLOW)),
] {
commands
.spawn((

View File

@ -30,7 +30,7 @@ enum AppState {
struct RpgSpriteFolder(Handle<LoadedFolder>);
fn load_textures(mut commands: Commands, asset_server: Res<AssetServer>) {
// load multiple, individual sprites from a folder
// Load multiple, individual sprites from a folder
commands.insert_resource(RpgSpriteFolder(asset_server.load_folder("textures/rpg")));
}
@ -57,7 +57,7 @@ fn setup(
) {
let loaded_folder = loaded_folders.get(&rpg_sprite_handles.0).unwrap();
// create texture atlases with different padding and sampling
// Create texture atlases with different padding and sampling
let (texture_atlas_linear, linear_sources, linear_texture) = create_texture_atlas(
loaded_folder,
@ -93,59 +93,58 @@ fn setup(
);
let atlas_nearest_padded_handle = texture_atlases.add(texture_atlas_nearest_padded);
// setup 2d scene
commands.spawn(Camera2d);
// padded textures are to the right, unpadded to the left
// Padded textures are to the right, unpadded to the left
// draw unpadded texture atlas
// Draw unpadded texture atlas
commands.spawn((
Sprite::from_image(linear_texture.clone()),
Transform {
translation: Vec3::new(-250.0, -130.0, 0.0),
scale: Vec3::splat(0.8),
translation: Vec3::new(-250.0, -160.0, 0.0),
scale: Vec3::splat(0.5),
..default()
},
));
// draw padded texture atlas
// Draw padded texture atlas
commands.spawn((
Sprite::from_image(linear_padded_texture.clone()),
Transform {
translation: Vec3::new(250.0, -130.0, 0.0),
scale: Vec3::splat(0.8),
translation: Vec3::new(250.0, -160.0, 0.0),
scale: Vec3::splat(0.5),
..default()
},
));
let font = asset_server.load("fonts/FiraSans-Bold.ttf");
// padding label text style
// Padding label text style
let text_style: TextFont = TextFont {
font: font.clone(),
font_size: 42.0,
..default()
};
// labels to indicate padding
// Labels to indicate padding
// No padding
create_label(
&mut commands,
(-250.0, 330.0, 0.0),
(-250.0, 250.0, 0.0),
"No padding",
text_style.clone(),
);
// Padding
create_label(&mut commands, (250.0, 330.0, 0.0), "Padding", text_style);
create_label(&mut commands, (250.0, 250.0, 0.0), "Padding", text_style);
// get handle to a sprite to render
// Get handle to a sprite to render
let vendor_handle: Handle<Image> = asset_server
.get_handle("textures/rpg/chars/vendor/generic-rpg-vendor.png")
.unwrap();
// configuration array to render sprites through iteration
// Configuration array to render sprites through iteration
let configurations: [(
&str,
Handle<TextureAtlasLayout>,
@ -183,17 +182,17 @@ fn setup(
),
];
// label text style
// Label text style
let sampling_label_style = TextFont {
font,
font_size: 25.0,
..default()
};
let base_y = 170.0; // y position of the sprites
let base_y = 80.0; // y position of the sprites
for (sampling, atlas_handle, atlas_sources, atlas_texture, x) in configurations {
// render a sprite from the texture_atlas
// Render a sprite from the texture_atlas
create_sprite_from_atlas(
&mut commands,
(x, base_y, 0.0),
@ -203,10 +202,10 @@ fn setup(
&vendor_handle,
);
// render a label to indicate the sampling setting
// Render a label to indicate the sampling setting
create_label(
&mut commands,
(x, base_y + 110.0, 0.0), // offset to y position of the sprite
(x, base_y + 110.0, 0.0), // Offset to y position of the sprite
sampling,
sampling_label_style.clone(),
);

View File

@ -15,7 +15,10 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
let sprite_handle = asset_server.load("branding/icon.png");
commands.spawn(Sprite::from_image(sprite_handle.clone()));
commands.spawn((
Sprite::from_image(sprite_handle.clone()),
Transform::from_xyz(-100.0, 0.0, 0.0),
));
commands.spawn((
Sprite {
image: sprite_handle.clone(),
@ -23,7 +26,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
color: Color::srgba(0.0, 0.0, 1.0, 0.7),
..default()
},
Transform::from_xyz(100.0, 0.0, 0.1),
Transform::from_xyz(0.0, 0.0, 0.1),
));
commands.spawn((
Sprite {
@ -31,6 +34,6 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
color: Color::srgba(0.0, 1.0, 0.0, 0.3),
..default()
},
Transform::from_xyz(200.0, 0.0, 0.2),
Transform::from_xyz(100.0, 0.0, 0.2),
));
}

View File

@ -84,7 +84,6 @@ fn setup(
},
));
// Camera
commands.spawn(Camera2d);
// Text used to show controls