mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
Migrate bevy_sprite to required components (#15489)
# Objective Continue migration of bevy APIs to required components, following guidance of https://hackmd.io/@bevy/required_components/ ## Solution - Make `Sprite` require `Transform` and `Visibility` and `SyncToRenderWorld` - move image and texture atlas handles into `Sprite` - deprecate `SpriteBundle` - remove engine uses of `SpriteBundle` ## Testing ran cargo tests on bevy_sprite and tested several sprite examples. --- ## Migration Guide Replace all uses of `SpriteBundle` with `Sprite`. There are several new convenience constructors: `Sprite::from_image`, `Sprite::from_atlas_image`, `Sprite::from_color`. WARNING: use of `Handle<Image>` and `TextureAtlas` as components on sprite entities will NO LONGER WORK. Use the fields on `Sprite` instead. I would have removed the `Component` impls from `TextureAtlas` and `Handle<Image>` except it is still used within ui. We should fix this moving forward with the migration.
This commit is contained in:
parent
219b5930f1
commit
7d40e3ec87
53 changed files with 456 additions and 676 deletions
|
@ -77,8 +77,6 @@ use core::{any::TypeId, ptr::NonNull};
|
||||||
/// Additionally, [Tuples](`tuple`) of bundles are also [`Bundle`] (with up to 15 bundles).
|
/// Additionally, [Tuples](`tuple`) of bundles are also [`Bundle`] (with up to 15 bundles).
|
||||||
/// These bundles contain the items of the 'inner' bundles.
|
/// These bundles contain the items of the 'inner' bundles.
|
||||||
/// This is a convenient shorthand which is primarily used when spawning entities.
|
/// This is a convenient shorthand which is primarily used when spawning entities.
|
||||||
/// For example, spawning an entity using the bundle `(SpriteBundle {...}, PlayerMarker)`
|
|
||||||
/// will spawn an entity with components required for a 2d sprite, and the `PlayerMarker` component.
|
|
||||||
///
|
///
|
||||||
/// [`unit`], otherwise known as [`()`](`unit`), is a [`Bundle`] containing no components (since it
|
/// [`unit`], otherwise known as [`()`](`unit`), is a [`Bundle`] containing no components (since it
|
||||||
/// can also be considered as the empty tuple).
|
/// can also be considered as the empty tuple).
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![expect(deprecated)]
|
||||||
use crate::Sprite;
|
use crate::Sprite;
|
||||||
use bevy_asset::Handle;
|
use bevy_asset::Handle;
|
||||||
use bevy_ecs::bundle::Bundle;
|
use bevy_ecs::bundle::Bundle;
|
||||||
|
@ -16,6 +17,10 @@ use bevy_transform::components::{GlobalTransform, Transform};
|
||||||
/// - [`ImageScaleMode`](crate::ImageScaleMode) to enable either slicing or tiling of the texture
|
/// - [`ImageScaleMode`](crate::ImageScaleMode) to enable either slicing or tiling of the texture
|
||||||
/// - [`TextureAtlas`](crate::TextureAtlas) to draw a specific section of the texture
|
/// - [`TextureAtlas`](crate::TextureAtlas) to draw a specific section of the texture
|
||||||
#[derive(Bundle, Clone, Debug, Default)]
|
#[derive(Bundle, Clone, Debug, Default)]
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.15.0",
|
||||||
|
note = "Use the `Sprite` component instead. Inserting it will now also insert `Transform` and `Visibility` automatically."
|
||||||
|
)]
|
||||||
pub struct SpriteBundle {
|
pub struct SpriteBundle {
|
||||||
/// Specifies the rendering properties of the sprite, such as color tint and flip.
|
/// Specifies the rendering properties of the sprite, such as color tint and flip.
|
||||||
pub sprite: Sprite,
|
pub sprite: Sprite,
|
||||||
|
|
|
@ -185,9 +185,9 @@ pub fn calculate_bounds_2d(
|
||||||
atlases: Res<Assets<TextureAtlasLayout>>,
|
atlases: Res<Assets<TextureAtlasLayout>>,
|
||||||
meshes_without_aabb: Query<(Entity, &Mesh2d), (Without<Aabb>, Without<NoFrustumCulling>)>,
|
meshes_without_aabb: Query<(Entity, &Mesh2d), (Without<Aabb>, Without<NoFrustumCulling>)>,
|
||||||
sprites_to_recalculate_aabb: Query<
|
sprites_to_recalculate_aabb: Query<
|
||||||
(Entity, &Sprite, &Handle<Image>, Option<&TextureAtlas>),
|
(Entity, &Sprite),
|
||||||
(
|
(
|
||||||
Or<(Without<Aabb>, Changed<Sprite>, Changed<TextureAtlas>)>,
|
Or<(Without<Aabb>, Changed<Sprite>)>,
|
||||||
Without<NoFrustumCulling>,
|
Without<NoFrustumCulling>,
|
||||||
),
|
),
|
||||||
>,
|
>,
|
||||||
|
@ -199,13 +199,13 @@ pub fn calculate_bounds_2d(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (entity, sprite, texture_handle, atlas) in &sprites_to_recalculate_aabb {
|
for (entity, sprite) in &sprites_to_recalculate_aabb {
|
||||||
if let Some(size) = sprite
|
if let Some(size) = sprite
|
||||||
.custom_size
|
.custom_size
|
||||||
.or_else(|| sprite.rect.map(|rect| rect.size()))
|
.or_else(|| sprite.rect.map(|rect| rect.size()))
|
||||||
.or_else(|| match atlas {
|
.or_else(|| match &sprite.texture_atlas {
|
||||||
// We default to the texture size for regular sprites
|
// We default to the texture size for regular sprites
|
||||||
None => images.get(texture_handle).map(Image::size_f32),
|
None => images.get(&sprite.image).map(Image::size_f32),
|
||||||
// We default to the drawn rect for atlas sprites
|
// We default to the drawn rect for atlas sprites
|
||||||
Some(atlas) => atlas
|
Some(atlas) => atlas
|
||||||
.texture_rect(&atlases)
|
.texture_rect(&atlases)
|
||||||
|
@ -259,10 +259,7 @@ mod test {
|
||||||
app.add_systems(Update, calculate_bounds_2d);
|
app.add_systems(Update, calculate_bounds_2d);
|
||||||
|
|
||||||
// Add entities
|
// Add entities
|
||||||
let entity = app
|
let entity = app.world_mut().spawn(Sprite::from_image(image_handle)).id();
|
||||||
.world_mut()
|
|
||||||
.spawn((Sprite::default(), image_handle))
|
|
||||||
.id();
|
|
||||||
|
|
||||||
// Verify that the entity does not have an AABB
|
// Verify that the entity does not have an AABB
|
||||||
assert!(!app
|
assert!(!app
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use core::cmp::Reverse;
|
use core::cmp::Reverse;
|
||||||
|
|
||||||
use crate::{Sprite, TextureAtlas, TextureAtlasLayout};
|
use crate::{Sprite, TextureAtlasLayout};
|
||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
use bevy_asset::prelude::*;
|
use bevy_asset::prelude::*;
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
|
@ -32,8 +32,6 @@ pub fn sprite_picking(
|
||||||
sprite_query: Query<(
|
sprite_query: Query<(
|
||||||
Entity,
|
Entity,
|
||||||
&Sprite,
|
&Sprite,
|
||||||
Option<&TextureAtlas>,
|
|
||||||
&Handle<Image>,
|
|
||||||
&GlobalTransform,
|
&GlobalTransform,
|
||||||
Option<&PickingBehavior>,
|
Option<&PickingBehavior>,
|
||||||
&ViewVisibility,
|
&ViewVisibility,
|
||||||
|
@ -42,9 +40,9 @@ pub fn sprite_picking(
|
||||||
) {
|
) {
|
||||||
let mut sorted_sprites: Vec<_> = sprite_query
|
let mut sorted_sprites: Vec<_> = sprite_query
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|x| !x.4.affine().is_nan())
|
.filter(|x| !x.2.affine().is_nan())
|
||||||
.collect();
|
.collect();
|
||||||
sorted_sprites.sort_by_key(|x| Reverse(FloatOrd(x.4.translation().z)));
|
sorted_sprites.sort_by_key(|x| Reverse(FloatOrd(x.2.translation().z)));
|
||||||
|
|
||||||
let primary_window = primary_window.get_single().ok();
|
let primary_window = primary_window.get_single().ok();
|
||||||
|
|
||||||
|
@ -77,82 +75,79 @@ pub fn sprite_picking(
|
||||||
.iter()
|
.iter()
|
||||||
.copied()
|
.copied()
|
||||||
.filter(|(.., visibility)| visibility.get())
|
.filter(|(.., visibility)| visibility.get())
|
||||||
.filter_map(
|
.filter_map(|(entity, sprite, sprite_transform, picking_behavior, ..)| {
|
||||||
|(entity, sprite, atlas, image, sprite_transform, picking_behavior, ..)| {
|
if blocked {
|
||||||
if blocked {
|
return None;
|
||||||
return None;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Hit box in sprite coordinate system
|
// Hit box in sprite coordinate system
|
||||||
let extents = match (sprite.custom_size, atlas) {
|
let extents = match (sprite.custom_size, &sprite.texture_atlas) {
|
||||||
(Some(custom_size), _) => custom_size,
|
(Some(custom_size), _) => custom_size,
|
||||||
(None, None) => images.get(image)?.size().as_vec2(),
|
(None, None) => images.get(&sprite.image)?.size().as_vec2(),
|
||||||
(None, Some(atlas)) => texture_atlas_layout
|
(None, Some(atlas)) => texture_atlas_layout
|
||||||
.get(&atlas.layout)
|
.get(&atlas.layout)
|
||||||
.and_then(|layout| layout.textures.get(atlas.index))
|
.and_then(|layout| layout.textures.get(atlas.index))
|
||||||
// Dropped atlas layouts and indexes out of bounds are rendered as a sprite
|
// Dropped atlas layouts and indexes out of bounds are rendered as a sprite
|
||||||
.map_or(images.get(image)?.size().as_vec2(), |rect| {
|
.map_or(images.get(&sprite.image)?.size().as_vec2(), |rect| {
|
||||||
rect.size().as_vec2()
|
rect.size().as_vec2()
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
let anchor = sprite.anchor.as_vec();
|
let anchor = sprite.anchor.as_vec();
|
||||||
let center = -anchor * extents;
|
let center = -anchor * extents;
|
||||||
let rect = Rect::from_center_half_size(center, extents / 2.0);
|
let rect = Rect::from_center_half_size(center, extents / 2.0);
|
||||||
|
|
||||||
// Transform cursor line segment to sprite coordinate system
|
// Transform cursor line segment to sprite coordinate system
|
||||||
let world_to_sprite = sprite_transform.affine().inverse();
|
let world_to_sprite = sprite_transform.affine().inverse();
|
||||||
let cursor_start_sprite =
|
let cursor_start_sprite = world_to_sprite.transform_point3(cursor_ray_world.origin);
|
||||||
world_to_sprite.transform_point3(cursor_ray_world.origin);
|
let cursor_end_sprite = world_to_sprite.transform_point3(cursor_ray_end);
|
||||||
let cursor_end_sprite = world_to_sprite.transform_point3(cursor_ray_end);
|
|
||||||
|
|
||||||
// Find where the cursor segment intersects the plane Z=0 (which is the sprite's
|
// Find where the cursor segment intersects the plane Z=0 (which is the sprite's
|
||||||
// plane in sprite-local space). It may not intersect if, for example, we're
|
// plane in sprite-local space). It may not intersect if, for example, we're
|
||||||
// viewing the sprite side-on
|
// viewing the sprite side-on
|
||||||
if cursor_start_sprite.z == cursor_end_sprite.z {
|
if cursor_start_sprite.z == cursor_end_sprite.z {
|
||||||
// Cursor ray is parallel to the sprite and misses it
|
// Cursor ray is parallel to the sprite and misses it
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let lerp_factor =
|
let lerp_factor =
|
||||||
f32::inverse_lerp(cursor_start_sprite.z, cursor_end_sprite.z, 0.0);
|
f32::inverse_lerp(cursor_start_sprite.z, cursor_end_sprite.z, 0.0);
|
||||||
if !(0.0..=1.0).contains(&lerp_factor) {
|
if !(0.0..=1.0).contains(&lerp_factor) {
|
||||||
// Lerp factor is out of range, meaning that while an infinite line cast by
|
// Lerp factor is out of range, meaning that while an infinite line cast by
|
||||||
// the cursor would intersect the sprite, the sprite is not between the
|
// the cursor would intersect the sprite, the sprite is not between the
|
||||||
// camera's near and far planes
|
// camera's near and far planes
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
// Otherwise we can interpolate the xy of the start and end positions by the
|
// Otherwise we can interpolate the xy of the start and end positions by the
|
||||||
// lerp factor to get the cursor position in sprite space!
|
// lerp factor to get the cursor position in sprite space!
|
||||||
let cursor_pos_sprite = cursor_start_sprite
|
let cursor_pos_sprite = cursor_start_sprite
|
||||||
.lerp(cursor_end_sprite, lerp_factor)
|
.lerp(cursor_end_sprite, lerp_factor)
|
||||||
.xy();
|
.xy();
|
||||||
|
|
||||||
let is_cursor_in_sprite = rect.contains(cursor_pos_sprite);
|
let is_cursor_in_sprite = rect.contains(cursor_pos_sprite);
|
||||||
|
|
||||||
blocked = is_cursor_in_sprite
|
blocked = is_cursor_in_sprite
|
||||||
&& picking_behavior.map(|p| p.should_block_lower) != Some(false);
|
&& picking_behavior.map(|p| p.should_block_lower) != Some(false);
|
||||||
|
|
||||||
is_cursor_in_sprite.then(|| {
|
is_cursor_in_sprite.then(|| {
|
||||||
let hit_pos_world =
|
let hit_pos_world =
|
||||||
sprite_transform.transform_point(cursor_pos_sprite.extend(0.0));
|
sprite_transform.transform_point(cursor_pos_sprite.extend(0.0));
|
||||||
// Transform point from world to camera space to get the Z distance
|
// Transform point from world to camera space to get the Z distance
|
||||||
let hit_pos_cam = cam_transform
|
let hit_pos_cam = cam_transform
|
||||||
.affine()
|
.affine()
|
||||||
.inverse()
|
.inverse()
|
||||||
.transform_point3(hit_pos_world);
|
.transform_point3(hit_pos_world);
|
||||||
// HitData requires a depth as calculated from the camera's near clipping plane
|
// HitData requires a depth as calculated from the camera's near clipping plane
|
||||||
let depth = -cam_ortho.near - hit_pos_cam.z;
|
let depth = -cam_ortho.near - hit_pos_cam.z;
|
||||||
(
|
(
|
||||||
entity,
|
entity,
|
||||||
HitData::new(
|
HitData::new(
|
||||||
cam_entity,
|
cam_entity,
|
||||||
depth,
|
depth,
|
||||||
Some(hit_pos_world),
|
Some(hit_pos_world),
|
||||||
Some(*sprite_transform.back()),
|
Some(*sprite_transform.back()),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
},
|
})
|
||||||
)
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let order = camera.order as f32;
|
let order = camera.order as f32;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use core::ops::Range;
|
use core::ops::Range;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
texture_atlas::{TextureAtlas, TextureAtlasLayout},
|
texture_atlas::TextureAtlasLayout, ComputedTextureSlices, Sprite, WithSprite,
|
||||||
ComputedTextureSlices, Sprite, WithSprite, SPRITE_SHADER_HANDLE,
|
SPRITE_SHADER_HANDLE,
|
||||||
};
|
};
|
||||||
use bevy_asset::{AssetEvent, AssetId, Assets, Handle};
|
use bevy_asset::{AssetEvent, AssetId, Assets};
|
||||||
use bevy_color::{ColorToComponents, LinearRgba};
|
use bevy_color::{ColorToComponents, LinearRgba};
|
||||||
use bevy_core_pipeline::{
|
use bevy_core_pipeline::{
|
||||||
core_2d::{Transparent2d, CORE_2D_DEPTH_FORMAT},
|
core_2d::{Transparent2d, CORE_2D_DEPTH_FORMAT},
|
||||||
|
@ -377,15 +377,12 @@ pub fn extract_sprites(
|
||||||
&ViewVisibility,
|
&ViewVisibility,
|
||||||
&Sprite,
|
&Sprite,
|
||||||
&GlobalTransform,
|
&GlobalTransform,
|
||||||
&Handle<Image>,
|
|
||||||
Option<&TextureAtlas>,
|
|
||||||
Option<&ComputedTextureSlices>,
|
Option<&ComputedTextureSlices>,
|
||||||
)>,
|
)>,
|
||||||
>,
|
>,
|
||||||
) {
|
) {
|
||||||
extracted_sprites.sprites.clear();
|
extracted_sprites.sprites.clear();
|
||||||
for (original_entity, entity, view_visibility, sprite, transform, handle, sheet, slices) in
|
for (original_entity, entity, view_visibility, sprite, transform, slices) in sprite_query.iter()
|
||||||
sprite_query.iter()
|
|
||||||
{
|
{
|
||||||
if !view_visibility.get() {
|
if !view_visibility.get() {
|
||||||
continue;
|
continue;
|
||||||
|
@ -394,12 +391,14 @@ pub fn extract_sprites(
|
||||||
if let Some(slices) = slices {
|
if let Some(slices) = slices {
|
||||||
extracted_sprites.sprites.extend(
|
extracted_sprites.sprites.extend(
|
||||||
slices
|
slices
|
||||||
.extract_sprites(transform, original_entity, sprite, handle)
|
.extract_sprites(transform, original_entity, sprite)
|
||||||
.map(|e| (commands.spawn(TemporaryRenderEntity).id(), e)),
|
.map(|e| (commands.spawn(TemporaryRenderEntity).id(), e)),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let atlas_rect =
|
let atlas_rect = sprite
|
||||||
sheet.and_then(|s| s.texture_rect(&texture_atlases).map(|r| r.as_rect()));
|
.texture_atlas
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|s| s.texture_rect(&texture_atlases).map(|r| r.as_rect()));
|
||||||
let rect = match (atlas_rect, sprite.rect) {
|
let rect = match (atlas_rect, sprite.rect) {
|
||||||
(None, None) => None,
|
(None, None) => None,
|
||||||
(None, Some(sprite_rect)) => Some(sprite_rect),
|
(None, Some(sprite_rect)) => Some(sprite_rect),
|
||||||
|
@ -423,7 +422,7 @@ pub fn extract_sprites(
|
||||||
custom_size: sprite.custom_size,
|
custom_size: sprite.custom_size,
|
||||||
flip_x: sprite.flip_x,
|
flip_x: sprite.flip_x,
|
||||||
flip_y: sprite.flip_y,
|
flip_y: sprite.flip_y,
|
||||||
image_handle_id: handle.id(),
|
image_handle_id: sprite.image.id(),
|
||||||
anchor: sprite.anchor.as_vec(),
|
anchor: sprite.anchor.as_vec(),
|
||||||
original_entity: Some(original_entity),
|
original_entity: Some(original_entity),
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,16 +1,22 @@
|
||||||
|
use bevy_asset::Handle;
|
||||||
use bevy_color::Color;
|
use bevy_color::Color;
|
||||||
use bevy_ecs::{component::Component, reflect::ReflectComponent};
|
use bevy_ecs::{component::Component, reflect::ReflectComponent};
|
||||||
use bevy_math::{Rect, Vec2};
|
use bevy_math::{Rect, Vec2};
|
||||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||||
|
use bevy_render::{sync_world::SyncToRenderWorld, texture::Image, view::Visibility};
|
||||||
|
use bevy_transform::components::Transform;
|
||||||
|
|
||||||
use crate::TextureSlicer;
|
use crate::{TextureAtlas, TextureSlicer};
|
||||||
|
|
||||||
/// Specifies the rendering properties of a sprite.
|
/// Describes a sprite to be rendered to a 2D camera
|
||||||
///
|
|
||||||
/// This is commonly used as a component within [`SpriteBundle`](crate::bundle::SpriteBundle).
|
|
||||||
#[derive(Component, Debug, Default, Clone, Reflect)]
|
#[derive(Component, Debug, Default, Clone, Reflect)]
|
||||||
|
#[require(Transform, Visibility, SyncToRenderWorld)]
|
||||||
#[reflect(Component, Default, Debug)]
|
#[reflect(Component, Default, Debug)]
|
||||||
pub struct Sprite {
|
pub struct Sprite {
|
||||||
|
/// The image used to render the sprite
|
||||||
|
pub image: Handle<Image>,
|
||||||
|
/// The (optional) texture atlas used to render the sprite
|
||||||
|
pub texture_atlas: Option<TextureAtlas>,
|
||||||
/// The sprite's color tint
|
/// The sprite's color tint
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
/// Flip the sprite along the `X` axis
|
/// Flip the sprite along the `X` axis
|
||||||
|
@ -21,9 +27,9 @@ pub struct Sprite {
|
||||||
/// of the sprite's image
|
/// of the sprite's image
|
||||||
pub custom_size: Option<Vec2>,
|
pub custom_size: Option<Vec2>,
|
||||||
/// An optional rectangle representing the region of the sprite's image to render, instead of rendering
|
/// An optional rectangle representing the region of the sprite's image to render, instead of rendering
|
||||||
/// the full image. This is an easy one-off alternative to using a [`TextureAtlas`](crate::TextureAtlas).
|
/// the full image. This is an easy one-off alternative to using a [`TextureAtlas`].
|
||||||
///
|
///
|
||||||
/// When used with a [`TextureAtlas`](crate::TextureAtlas), the rect
|
/// When used with a [`TextureAtlas`], the rect
|
||||||
/// is offset by the atlas's minimal (top-left) corner position.
|
/// is offset by the atlas's minimal (top-left) corner position.
|
||||||
pub rect: Option<Rect>,
|
pub rect: Option<Rect>,
|
||||||
/// [`Anchor`] point of the sprite in the world
|
/// [`Anchor`] point of the sprite in the world
|
||||||
|
@ -38,6 +44,38 @@ impl Sprite {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a sprite from an image
|
||||||
|
pub fn from_image(image: Handle<Image>) -> Self {
|
||||||
|
Self {
|
||||||
|
image,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a sprite from an image, with an associated texture atlas
|
||||||
|
pub fn from_atlas_image(image: Handle<Image>, atlas: TextureAtlas) -> Self {
|
||||||
|
Self {
|
||||||
|
image,
|
||||||
|
texture_atlas: Some(atlas),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a sprite from a solid color
|
||||||
|
pub fn from_color(color: impl Into<Color>, size: Vec2) -> Self {
|
||||||
|
Self {
|
||||||
|
color: color.into(),
|
||||||
|
custom_size: Some(size),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Handle<Image>> for Sprite {
|
||||||
|
fn from(image: Handle<Image>) -> Self {
|
||||||
|
Self::from_image(image)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Controls how the image is altered when scaled.
|
/// Controls how the image is altered when scaled.
|
||||||
|
@ -58,7 +96,7 @@ pub enum ImageScaleMode {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// How a sprite is positioned relative to its [`Transform`](bevy_transform::components::Transform).
|
/// How a sprite is positioned relative to its [`Transform`].
|
||||||
/// It defaults to `Anchor::Center`.
|
/// It defaults to `Anchor::Center`.
|
||||||
#[derive(Component, Debug, Clone, Copy, PartialEq, Default, Reflect)]
|
#[derive(Component, Debug, Clone, Copy, PartialEq, Default, Reflect)]
|
||||||
#[reflect(Component, Default, Debug, PartialEq)]
|
#[reflect(Component, Default, Debug, PartialEq)]
|
||||||
|
|
|
@ -190,10 +190,7 @@ impl<'a> TextureAtlasBuilder<'a> {
|
||||||
/// let texture = textures.add(texture);
|
/// let texture = textures.add(texture);
|
||||||
/// let layout = layouts.add(atlas_layout);
|
/// let layout = layouts.add(atlas_layout);
|
||||||
/// // Spawn your sprite
|
/// // Spawn your sprite
|
||||||
/// commands.spawn((
|
/// commands.spawn(Sprite::from_atlas_image(texture, TextureAtlas::from(layout)));
|
||||||
/// SpriteBundle { texture, ..Default::default() },
|
|
||||||
/// TextureAtlas::from(layout),
|
|
||||||
/// ));
|
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{ExtractedSprite, ImageScaleMode, Sprite, TextureAtlas, TextureAtlasLayout};
|
use crate::{ExtractedSprite, ImageScaleMode, Sprite, TextureAtlasLayout};
|
||||||
|
|
||||||
use super::TextureSlice;
|
use super::TextureSlice;
|
||||||
use bevy_asset::{AssetEvent, Assets, Handle};
|
use bevy_asset::{AssetEvent, Assets};
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
use bevy_math::{Rect, Vec2};
|
use bevy_math::{Rect, Vec2};
|
||||||
use bevy_render::texture::Image;
|
use bevy_render::texture::Image;
|
||||||
|
@ -29,7 +29,6 @@ impl ComputedTextureSlices {
|
||||||
transform: &'a GlobalTransform,
|
transform: &'a GlobalTransform,
|
||||||
original_entity: Entity,
|
original_entity: Entity,
|
||||||
sprite: &'a Sprite,
|
sprite: &'a Sprite,
|
||||||
handle: &'a Handle<Image>,
|
|
||||||
) -> impl ExactSizeIterator<Item = ExtractedSprite> + 'a {
|
) -> impl ExactSizeIterator<Item = ExtractedSprite> + 'a {
|
||||||
let mut flip = Vec2::ONE;
|
let mut flip = Vec2::ONE;
|
||||||
let [mut flip_x, mut flip_y] = [false; 2];
|
let [mut flip_x, mut flip_y] = [false; 2];
|
||||||
|
@ -52,7 +51,7 @@ impl ComputedTextureSlices {
|
||||||
custom_size: Some(slice.draw_size),
|
custom_size: Some(slice.draw_size),
|
||||||
flip_x,
|
flip_x,
|
||||||
flip_y,
|
flip_y,
|
||||||
image_handle_id: handle.id(),
|
image_handle_id: sprite.image.id(),
|
||||||
anchor: Self::redepend_anchor_from_sprite_to_slice(sprite, slice),
|
anchor: Self::redepend_anchor_from_sprite_to_slice(sprite, slice),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -88,12 +87,10 @@ impl ComputedTextureSlices {
|
||||||
fn compute_sprite_slices(
|
fn compute_sprite_slices(
|
||||||
sprite: &Sprite,
|
sprite: &Sprite,
|
||||||
scale_mode: &ImageScaleMode,
|
scale_mode: &ImageScaleMode,
|
||||||
image_handle: &Handle<Image>,
|
|
||||||
images: &Assets<Image>,
|
images: &Assets<Image>,
|
||||||
atlas: Option<&TextureAtlas>,
|
|
||||||
atlas_layouts: &Assets<TextureAtlasLayout>,
|
atlas_layouts: &Assets<TextureAtlasLayout>,
|
||||||
) -> Option<ComputedTextureSlices> {
|
) -> Option<ComputedTextureSlices> {
|
||||||
let (image_size, texture_rect) = match atlas {
|
let (image_size, texture_rect) = match &sprite.texture_atlas {
|
||||||
Some(a) => {
|
Some(a) => {
|
||||||
let layout = atlas_layouts.get(&a.layout)?;
|
let layout = atlas_layouts.get(&a.layout)?;
|
||||||
(
|
(
|
||||||
|
@ -102,7 +99,7 @@ fn compute_sprite_slices(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let image = images.get(image_handle)?;
|
let image = images.get(&sprite.image)?;
|
||||||
let size = Vec2::new(
|
let size = Vec2::new(
|
||||||
image.texture_descriptor.size.width as f32,
|
image.texture_descriptor.size.width as f32,
|
||||||
image.texture_descriptor.size.height as f32,
|
image.texture_descriptor.size.height as f32,
|
||||||
|
@ -139,13 +136,7 @@ pub(crate) fn compute_slices_on_asset_event(
|
||||||
mut events: EventReader<AssetEvent<Image>>,
|
mut events: EventReader<AssetEvent<Image>>,
|
||||||
images: Res<Assets<Image>>,
|
images: Res<Assets<Image>>,
|
||||||
atlas_layouts: Res<Assets<TextureAtlasLayout>>,
|
atlas_layouts: Res<Assets<TextureAtlasLayout>>,
|
||||||
sprites: Query<(
|
sprites: Query<(Entity, &ImageScaleMode, &Sprite)>,
|
||||||
Entity,
|
|
||||||
&ImageScaleMode,
|
|
||||||
&Sprite,
|
|
||||||
&Handle<Image>,
|
|
||||||
Option<&TextureAtlas>,
|
|
||||||
)>,
|
|
||||||
) {
|
) {
|
||||||
// We store the asset ids of added/modified image assets
|
// We store the asset ids of added/modified image assets
|
||||||
let added_handles: HashSet<_> = events
|
let added_handles: HashSet<_> = events
|
||||||
|
@ -159,18 +150,11 @@ pub(crate) fn compute_slices_on_asset_event(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// We recompute the sprite slices for sprite entities with a matching asset handle id
|
// We recompute the sprite slices for sprite entities with a matching asset handle id
|
||||||
for (entity, scale_mode, sprite, image_handle, atlas) in &sprites {
|
for (entity, scale_mode, sprite) in &sprites {
|
||||||
if !added_handles.contains(&image_handle.id()) {
|
if !added_handles.contains(&sprite.image.id()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(slices) = compute_sprite_slices(
|
if let Some(slices) = compute_sprite_slices(sprite, scale_mode, &images, &atlas_layouts) {
|
||||||
sprite,
|
|
||||||
scale_mode,
|
|
||||||
image_handle,
|
|
||||||
&images,
|
|
||||||
atlas,
|
|
||||||
&atlas_layouts,
|
|
||||||
) {
|
|
||||||
commands.entity(entity).insert(slices);
|
commands.entity(entity).insert(slices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,30 +167,12 @@ pub(crate) fn compute_slices_on_sprite_change(
|
||||||
images: Res<Assets<Image>>,
|
images: Res<Assets<Image>>,
|
||||||
atlas_layouts: Res<Assets<TextureAtlasLayout>>,
|
atlas_layouts: Res<Assets<TextureAtlasLayout>>,
|
||||||
changed_sprites: Query<
|
changed_sprites: Query<
|
||||||
(
|
(Entity, &ImageScaleMode, &Sprite),
|
||||||
Entity,
|
Or<(Changed<ImageScaleMode>, Changed<Sprite>)>,
|
||||||
&ImageScaleMode,
|
|
||||||
&Sprite,
|
|
||||||
&Handle<Image>,
|
|
||||||
Option<&TextureAtlas>,
|
|
||||||
),
|
|
||||||
Or<(
|
|
||||||
Changed<ImageScaleMode>,
|
|
||||||
Changed<Handle<Image>>,
|
|
||||||
Changed<Sprite>,
|
|
||||||
Changed<TextureAtlas>,
|
|
||||||
)>,
|
|
||||||
>,
|
>,
|
||||||
) {
|
) {
|
||||||
for (entity, scale_mode, sprite, image_handle, atlas) in &changed_sprites {
|
for (entity, scale_mode, sprite) in &changed_sprites {
|
||||||
if let Some(slices) = compute_sprite_slices(
|
if let Some(slices) = compute_sprite_slices(sprite, scale_mode, &images, &atlas_layouts) {
|
||||||
sprite,
|
|
||||||
scale_mode,
|
|
||||||
image_handle,
|
|
||||||
&images,
|
|
||||||
atlas,
|
|
||||||
&atlas_layouts,
|
|
||||||
) {
|
|
||||||
commands.entity(entity).insert(slices);
|
commands.entity(entity).insert(slices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,13 +33,10 @@ fn setup(
|
||||||
));
|
));
|
||||||
|
|
||||||
// Sprite
|
// Sprite
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn(Sprite {
|
||||||
texture: asset_server.load("branding/bevy_bird_dark.png"),
|
image: asset_server.load("branding/bevy_bird_dark.png"),
|
||||||
sprite: Sprite {
|
color: Color::srgb(5.0, 5.0, 5.0), // 4. Put something bright in a dark environment to see the effect
|
||||||
color: Color::srgb(5.0, 5.0, 5.0), // 4. Put something bright in a dark environment to see the effect
|
custom_size: Some(Vec2::splat(160.0)),
|
||||||
custom_size: Some(Vec2::splat(160.0)),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -78,11 +78,7 @@ fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
|
||||||
let handle = images.add(image);
|
let handle = images.add(image);
|
||||||
|
|
||||||
// create a sprite entity using our image
|
// create a sprite entity using our image
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn(Sprite::from_image(handle.clone()));
|
||||||
texture: handle.clone(),
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
|
|
||||||
commands.insert_resource(MyProcGenImage(handle));
|
commands.insert_resource(MyProcGenImage(handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,11 +19,8 @@ enum Direction {
|
||||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
commands.spawn(Camera2d);
|
commands.spawn(Camera2d);
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite::from_image(asset_server.load("branding/icon.png")),
|
||||||
texture: asset_server.load("branding/icon.png"),
|
Transform::from_xyz(100., 0., 0.),
|
||||||
transform: Transform::from_xyz(100., 0., 0.),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
Direction::Up,
|
Direction::Up,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,22 +52,16 @@ struct Rotate;
|
||||||
fn setup_sprite(mut commands: Commands, asset_server: Res<AssetServer>) {
|
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((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite::from_image(asset_server.load("pixel/bevy_pixel_dark.png")),
|
||||||
texture: asset_server.load("pixel/bevy_pixel_dark.png"),
|
Transform::from_xyz(-40., 20., 2.),
|
||||||
transform: Transform::from_xyz(-40., 20., 2.),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
Rotate,
|
Rotate,
|
||||||
PIXEL_PERFECT_LAYERS,
|
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((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite::from_image(asset_server.load("pixel/bevy_pixel_light.png")),
|
||||||
texture: asset_server.load("pixel/bevy_pixel_light.png"),
|
Transform::from_xyz(-40., -20., 2.),
|
||||||
transform: Transform::from_xyz(-40., -20., 2.),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
Rotate,
|
Rotate,
|
||||||
HIGH_RES_LAYERS,
|
HIGH_RES_LAYERS,
|
||||||
));
|
));
|
||||||
|
@ -132,14 +126,7 @@ fn setup_camera(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
|
||||||
));
|
));
|
||||||
|
|
||||||
// spawn the canvas
|
// spawn the canvas
|
||||||
commands.spawn((
|
commands.spawn((Sprite::from_image(image_handle), Canvas, HIGH_RES_LAYERS));
|
||||||
SpriteBundle {
|
|
||||||
texture: image_handle,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
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
|
// here, the canvas and one of the sample sprites will be rendered by this camera
|
||||||
|
|
|
@ -62,10 +62,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
|
|
||||||
// player controlled ship
|
// player controlled ship
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite::from_image(ship_handle),
|
||||||
texture: ship_handle,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
Player {
|
Player {
|
||||||
movement_speed: 500.0, // meters per second
|
movement_speed: 500.0, // meters per second
|
||||||
rotation_speed: f32::to_radians(360.0), // degrees per second
|
rotation_speed: f32::to_radians(360.0), // degrees per second
|
||||||
|
@ -74,39 +71,27 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
|
|
||||||
// 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((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite::from_image(enemy_a_handle.clone()),
|
||||||
texture: enemy_a_handle.clone(),
|
Transform::from_xyz(0.0 - horizontal_margin, 0.0, 0.0),
|
||||||
transform: Transform::from_xyz(0.0 - horizontal_margin, 0.0, 0.0),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
SnapToPlayer,
|
SnapToPlayer,
|
||||||
));
|
));
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite::from_image(enemy_a_handle),
|
||||||
texture: enemy_a_handle,
|
Transform::from_xyz(0.0, 0.0 - vertical_margin, 0.0),
|
||||||
transform: Transform::from_xyz(0.0, 0.0 - vertical_margin, 0.0),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
SnapToPlayer,
|
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((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite::from_image(enemy_b_handle.clone()),
|
||||||
texture: enemy_b_handle.clone(),
|
Transform::from_xyz(0.0 + horizontal_margin, 0.0, 0.0),
|
||||||
transform: Transform::from_xyz(0.0 + horizontal_margin, 0.0, 0.0),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
RotateToPlayer {
|
RotateToPlayer {
|
||||||
rotation_speed: f32::to_radians(45.0), // degrees per second
|
rotation_speed: f32::to_radians(45.0), // degrees per second
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite::from_image(enemy_b_handle),
|
||||||
texture: enemy_b_handle,
|
Transform::from_xyz(0.0, 0.0 + vertical_margin, 0.0),
|
||||||
transform: Transform::from_xyz(0.0, 0.0 + vertical_margin, 0.0),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
RotateToPlayer {
|
RotateToPlayer {
|
||||||
rotation_speed: f32::to_radians(90.0), // degrees per second
|
rotation_speed: f32::to_radians(90.0), // degrees per second
|
||||||
},
|
},
|
||||||
|
|
|
@ -11,8 +11,7 @@ fn main() {
|
||||||
|
|
||||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
commands.spawn(Camera2d);
|
commands.spawn(Camera2d);
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn(Sprite::from_image(
|
||||||
texture: asset_server.load("branding/bevy_bird_dark.png"),
|
asset_server.load("branding/bevy_bird_dark.png"),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,24 +56,23 @@ impl AnimationConfig {
|
||||||
|
|
||||||
// This system loops through all the sprites in the `TextureAtlas`, from `first_sprite_index` to
|
// This system loops through all the sprites in the `TextureAtlas`, from `first_sprite_index` to
|
||||||
// `last_sprite_index` (both defined in `AnimationConfig`).
|
// `last_sprite_index` (both defined in `AnimationConfig`).
|
||||||
fn execute_animations(
|
fn execute_animations(time: Res<Time>, mut query: Query<(&mut AnimationConfig, &mut Sprite)>) {
|
||||||
time: Res<Time>,
|
for (mut config, mut sprite) in &mut query {
|
||||||
mut query: Query<(&mut AnimationConfig, &mut TextureAtlas)>,
|
|
||||||
) {
|
|
||||||
for (mut config, mut atlas) 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());
|
config.frame_timer.tick(time.delta());
|
||||||
|
|
||||||
// If it has been displayed for the user-defined amount of time (fps)...
|
// If it has been displayed for the user-defined amount of time (fps)...
|
||||||
if config.frame_timer.just_finished() {
|
if config.frame_timer.just_finished() {
|
||||||
if atlas.index == config.last_sprite_index {
|
if let Some(atlas) = &mut sprite.texture_atlas {
|
||||||
// ...and it IS the last frame, then we move back to the first frame and stop.
|
if atlas.index == config.last_sprite_index {
|
||||||
atlas.index = config.first_sprite_index;
|
// ...and it IS the last frame, then we move back to the first frame and stop.
|
||||||
} else {
|
atlas.index = config.first_sprite_index;
|
||||||
// ...and it is NOT the last frame, then we move to the next frame...
|
} else {
|
||||||
atlas.index += 1;
|
// ...and it is NOT the last frame, then we move to the next frame...
|
||||||
// ...and reset the frame timer to start counting all over again
|
atlas.index += 1;
|
||||||
config.frame_timer = AnimationConfig::timer_from_fps(config.fps);
|
// ...and reset the frame timer to start counting all over again
|
||||||
|
config.frame_timer = AnimationConfig::timer_from_fps(config.fps);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,16 +103,15 @@ fn setup(
|
||||||
|
|
||||||
// create the first (left-hand) sprite
|
// create the first (left-hand) sprite
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite {
|
||||||
transform: Transform::from_scale(Vec3::splat(6.0))
|
image: texture.clone(),
|
||||||
.with_translation(Vec3::new(-50.0, 0.0, 0.0)),
|
texture_atlas: Some(TextureAtlas {
|
||||||
texture: texture.clone(),
|
layout: texture_atlas_layout.clone(),
|
||||||
|
index: animation_config_1.first_sprite_index,
|
||||||
|
}),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
TextureAtlas {
|
Transform::from_scale(Vec3::splat(6.0)).with_translation(Vec3::new(-50.0, 0.0, 0.0)),
|
||||||
layout: texture_atlas_layout.clone(),
|
|
||||||
index: animation_config_1.first_sprite_index,
|
|
||||||
},
|
|
||||||
LeftSprite,
|
LeftSprite,
|
||||||
animation_config_1,
|
animation_config_1,
|
||||||
));
|
));
|
||||||
|
@ -123,15 +121,13 @@ fn setup(
|
||||||
|
|
||||||
// create the second (right-hand) sprite
|
// create the second (right-hand) sprite
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite {
|
||||||
transform: Transform::from_scale(Vec3::splat(6.0))
|
image: texture.clone(),
|
||||||
.with_translation(Vec3::new(50.0, 0.0, 0.0)),
|
texture_atlas: Some(TextureAtlas {
|
||||||
texture: texture.clone(),
|
layout: texture_atlas_layout.clone(),
|
||||||
..default()
|
index: animation_config_2.first_sprite_index,
|
||||||
},
|
}),
|
||||||
TextureAtlas {
|
..Default::default()
|
||||||
layout: texture_atlas_layout.clone(),
|
|
||||||
index: animation_config_2.first_sprite_index,
|
|
||||||
},
|
},
|
||||||
RightSprite,
|
RightSprite,
|
||||||
animation_config_2,
|
animation_config_2,
|
||||||
|
|
|
@ -11,15 +11,12 @@ fn main() {
|
||||||
|
|
||||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
commands.spawn(Camera2d);
|
commands.spawn(Camera2d);
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn(Sprite {
|
||||||
texture: asset_server.load("branding/bevy_bird_dark.png"),
|
image: asset_server.load("branding/bevy_bird_dark.png"),
|
||||||
sprite: Sprite {
|
// Flip the logo to the left
|
||||||
// Flip the logo to the left
|
flip_x: true,
|
||||||
flip_x: true,
|
// And don't flip it upside-down ( the default )
|
||||||
// And don't flip it upside-down ( the default )
|
flip_y: false,
|
||||||
flip_y: false,
|
..Default::default()
|
||||||
..default()
|
|
||||||
},
|
|
||||||
..default()
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,16 +22,19 @@ struct AnimationTimer(Timer);
|
||||||
|
|
||||||
fn animate_sprite(
|
fn animate_sprite(
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
mut query: Query<(&AnimationIndices, &mut AnimationTimer, &mut TextureAtlas)>,
|
mut query: Query<(&AnimationIndices, &mut AnimationTimer, &mut Sprite)>,
|
||||||
) {
|
) {
|
||||||
for (indices, mut timer, mut atlas) in &mut query {
|
for (indices, mut timer, mut sprite) in &mut query {
|
||||||
timer.tick(time.delta());
|
timer.tick(time.delta());
|
||||||
|
|
||||||
if timer.just_finished() {
|
if timer.just_finished() {
|
||||||
atlas.index = if atlas.index == indices.last {
|
if let Some(atlas) = &mut sprite.texture_atlas {
|
||||||
indices.first
|
atlas.index = if atlas.index == indices.last {
|
||||||
} else {
|
indices.first
|
||||||
atlas.index + 1
|
} else {
|
||||||
};
|
atlas.index + 1
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,15 +51,14 @@ fn setup(
|
||||||
let animation_indices = AnimationIndices { first: 1, last: 6 };
|
let animation_indices = AnimationIndices { first: 1, last: 6 };
|
||||||
commands.spawn(Camera2d);
|
commands.spawn(Camera2d);
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite::from_atlas_image(
|
||||||
transform: Transform::from_scale(Vec3::splat(6.0)),
|
|
||||||
texture,
|
texture,
|
||||||
..default()
|
TextureAtlas {
|
||||||
},
|
layout: texture_atlas_layout,
|
||||||
TextureAtlas {
|
index: animation_indices.first,
|
||||||
layout: texture_atlas_layout,
|
},
|
||||||
index: animation_indices.first,
|
),
|
||||||
},
|
Transform::from_scale(Vec3::splat(6.0)),
|
||||||
animation_indices,
|
animation_indices,
|
||||||
AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
|
AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
|
||||||
));
|
));
|
||||||
|
|
|
@ -73,15 +73,14 @@ fn spawn_sprites(
|
||||||
|
|
||||||
for (label, text_style, size, scale_mode) in cases {
|
for (label, text_style, size, scale_mode) in cases {
|
||||||
position.x += 0.5 * size.x;
|
position.x += 0.5 * size.x;
|
||||||
let mut cmd = commands.spawn(SpriteBundle {
|
let mut cmd = commands.spawn((
|
||||||
transform: Transform::from_translation(position),
|
Sprite {
|
||||||
texture: texture_handle.clone(),
|
image: texture_handle.clone(),
|
||||||
sprite: Sprite {
|
|
||||||
custom_size: Some(size),
|
custom_size: Some(size),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
..default()
|
Transform::from_translation(position),
|
||||||
});
|
));
|
||||||
if let Some(scale_mode) = scale_mode {
|
if let Some(scale_mode) = scale_mode {
|
||||||
cmd.insert(scale_mode);
|
cmd.insert(scale_mode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
speed: 50.0,
|
speed: 50.0,
|
||||||
});
|
});
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite::from_image(asset_server.load("branding/icon.png")),
|
||||||
texture: asset_server.load("branding/icon.png"),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
ImageScaleMode::Tiled {
|
ImageScaleMode::Tiled {
|
||||||
tile_x: true,
|
tile_x: true,
|
||||||
tile_y: true,
|
tile_y: true,
|
||||||
|
|
|
@ -79,15 +79,10 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
let box_size = Vec2::new(300.0, 200.0);
|
let box_size = Vec2::new(300.0, 200.0);
|
||||||
let box_position = Vec2::new(0.0, -250.0);
|
let box_position = Vec2::new(0.0, -250.0);
|
||||||
commands
|
commands
|
||||||
.spawn(SpriteBundle {
|
.spawn((
|
||||||
sprite: Sprite {
|
Sprite::from_color(Color::srgb(0.25, 0.25, 0.75), box_size),
|
||||||
color: Color::srgb(0.25, 0.25, 0.75),
|
Transform::from_translation(box_position.extend(0.0)),
|
||||||
custom_size: Some(Vec2::new(box_size.x, box_size.y)),
|
))
|
||||||
..default()
|
|
||||||
},
|
|
||||||
transform: Transform::from_translation(box_position.extend(0.0)),
|
|
||||||
..default()
|
|
||||||
})
|
|
||||||
.with_children(|builder| {
|
.with_children(|builder| {
|
||||||
builder.spawn(Text2dBundle {
|
builder.spawn(Text2dBundle {
|
||||||
text: Text {
|
text: Text {
|
||||||
|
@ -110,15 +105,10 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
let other_box_size = Vec2::new(300.0, 200.0);
|
let other_box_size = Vec2::new(300.0, 200.0);
|
||||||
let other_box_position = Vec2::new(320.0, -250.0);
|
let other_box_position = Vec2::new(320.0, -250.0);
|
||||||
commands
|
commands
|
||||||
.spawn(SpriteBundle {
|
.spawn((
|
||||||
sprite: Sprite {
|
Sprite::from_color(Color::srgb(0.20, 0.3, 0.70), other_box_size),
|
||||||
color: Color::srgb(0.20, 0.3, 0.70),
|
Transform::from_translation(other_box_position.extend(0.0)),
|
||||||
custom_size: Some(Vec2::new(other_box_size.x, other_box_size.y)),
|
))
|
||||||
..default()
|
|
||||||
},
|
|
||||||
transform: Transform::from_translation(other_box_position.extend(0.0)),
|
|
||||||
..default()
|
|
||||||
})
|
|
||||||
.with_children(|builder| {
|
.with_children(|builder| {
|
||||||
builder.spawn(Text2dBundle {
|
builder.spawn(Text2dBundle {
|
||||||
text: Text {
|
text: Text {
|
||||||
|
|
|
@ -99,26 +99,24 @@ fn setup(
|
||||||
// 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(SpriteBundle {
|
commands.spawn((
|
||||||
texture: linear_texture.clone(),
|
Sprite::from_image(linear_texture.clone()),
|
||||||
transform: Transform {
|
Transform {
|
||||||
translation: Vec3::new(-250.0, -130.0, 0.0),
|
translation: Vec3::new(-250.0, -130.0, 0.0),
|
||||||
scale: Vec3::splat(0.8),
|
scale: Vec3::splat(0.8),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
|
|
||||||
// draw padded texture atlas
|
// draw padded texture atlas
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn((
|
||||||
texture: linear_padded_texture.clone(),
|
Sprite::from_image(linear_padded_texture.clone()),
|
||||||
transform: Transform {
|
Transform {
|
||||||
translation: Vec3::new(250.0, -130.0, 0.0),
|
translation: Vec3::new(250.0, -130.0, 0.0),
|
||||||
scale: Vec3::splat(0.8),
|
scale: Vec3::splat(0.8),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
|
|
||||||
let font = asset_server.load("fonts/FiraSans-Bold.ttf");
|
let font = asset_server.load("fonts/FiraSans-Bold.ttf");
|
||||||
|
|
||||||
|
@ -260,16 +258,15 @@ fn create_sprite_from_atlas(
|
||||||
vendor_handle: &Handle<Image>,
|
vendor_handle: &Handle<Image>,
|
||||||
) {
|
) {
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Transform {
|
||||||
transform: Transform {
|
translation: Vec3::new(translation.0, translation.1, translation.2),
|
||||||
translation: Vec3::new(translation.0, translation.1, translation.2),
|
scale: Vec3::splat(3.0),
|
||||||
scale: Vec3::splat(3.0),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
texture: atlas_texture,
|
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
atlas_sources.handle(atlas_handle, vendor_handle).unwrap(),
|
Sprite::from_atlas_image(
|
||||||
|
atlas_texture,
|
||||||
|
atlas_sources.handle(atlas_handle, vendor_handle).unwrap(),
|
||||||
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,27 +15,22 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
|
|
||||||
let sprite_handle = asset_server.load("branding/icon.png");
|
let sprite_handle = asset_server.load("branding/icon.png");
|
||||||
|
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn(Sprite::from_image(sprite_handle.clone()));
|
||||||
texture: sprite_handle.clone(),
|
commands.spawn((
|
||||||
..default()
|
Sprite {
|
||||||
});
|
image: sprite_handle.clone(),
|
||||||
commands.spawn(SpriteBundle {
|
|
||||||
sprite: Sprite {
|
|
||||||
// Alpha channel of the color controls transparency.
|
// Alpha channel of the color controls transparency.
|
||||||
color: Color::srgba(0.0, 0.0, 1.0, 0.7),
|
color: Color::srgba(0.0, 0.0, 1.0, 0.7),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
texture: sprite_handle.clone(),
|
Transform::from_xyz(100.0, 0.0, 0.0),
|
||||||
transform: Transform::from_xyz(100.0, 0.0, 0.0),
|
));
|
||||||
..default()
|
commands.spawn((
|
||||||
});
|
Sprite {
|
||||||
commands.spawn(SpriteBundle {
|
image: sprite_handle,
|
||||||
sprite: Sprite {
|
|
||||||
color: Color::srgba(0.0, 1.0, 0.0, 0.3),
|
color: Color::srgba(0.0, 1.0, 0.0, 0.3),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
texture: sprite_handle,
|
Transform::from_xyz(200.0, 0.0, 0.0),
|
||||||
transform: Transform::from_xyz(200.0, 0.0, 0.0),
|
));
|
||||||
..default()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,28 +70,16 @@ fn setup(mut commands: Commands) {
|
||||||
|
|
||||||
fn spawn_curve_sprite<T: CurveColor>(commands: &mut Commands, y: f32, points: [T; 4]) {
|
fn spawn_curve_sprite<T: CurveColor>(commands: &mut Commands, y: f32, points: [T; 4]) {
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite::sized(Vec2::new(75., 75.)),
|
||||||
transform: Transform::from_xyz(0., y, 0.),
|
Transform::from_xyz(0., y, 0.),
|
||||||
sprite: Sprite {
|
|
||||||
custom_size: Some(Vec2::new(75., 75.)),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
Curve(CubicBezier::new([points]).to_curve().unwrap()),
|
Curve(CubicBezier::new([points]).to_curve().unwrap()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_mixed_sprite<T: MixedColor>(commands: &mut Commands, y: f32, colors: [T; 4]) {
|
fn spawn_mixed_sprite<T: MixedColor>(commands: &mut Commands, y: f32, colors: [T; 4]) {
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Transform::from_xyz(0., y, 0.),
|
||||||
transform: Transform::from_xyz(0., y, 0.),
|
Sprite::sized(Vec2::new(75., 75.)),
|
||||||
sprite: Sprite {
|
|
||||||
custom_size: Some(Vec2::new(75., 75.)),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
Mixed(colors),
|
Mixed(colors),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,24 +82,14 @@ fn setup(mut commands: Commands) {
|
||||||
SelectedEaseFunction(*function, color),
|
SelectedEaseFunction(*function, color),
|
||||||
))
|
))
|
||||||
.with_children(|p| {
|
.with_children(|p| {
|
||||||
p.spawn(SpriteBundle {
|
p.spawn((
|
||||||
sprite: Sprite {
|
Sprite::from_color(color, Vec2::splat(5.0)),
|
||||||
custom_size: Some(Vec2::new(5.0, 5.0)),
|
Transform::from_xyz(SIZE_PER_FUNCTION + 5.0, 15.0, 0.0),
|
||||||
color,
|
));
|
||||||
..default()
|
p.spawn((
|
||||||
},
|
Sprite::from_color(color, Vec2::splat(4.0)),
|
||||||
transform: Transform::from_xyz(SIZE_PER_FUNCTION + 5.0, 15.0, 0.0),
|
Transform::from_xyz(0.0, 0.0, 0.0),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
p.spawn(SpriteBundle {
|
|
||||||
sprite: Sprite {
|
|
||||||
custom_size: Some(Vec2::new(4.0, 4.0)),
|
|
||||||
color,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
transform: Transform::from_xyz(0.0, 0.0, 0.0),
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,23 +75,16 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
// This marker component ensures we can easily find either of the Birds by using With and
|
// This marker component ensures we can easily find either of the Birds by using With and
|
||||||
// Without query filters.
|
// Without query filters.
|
||||||
Left,
|
Left,
|
||||||
SpriteBundle {
|
Sprite::from_image(texture_left),
|
||||||
texture: texture_left,
|
Transform::from_xyz(-200.0, 0.0, 0.0),
|
||||||
transform: Transform::from_xyz(-200.0, 0.0, 0.0),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
bird_left,
|
bird_left,
|
||||||
));
|
));
|
||||||
|
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
Name::new("Bird Right"),
|
Name::new("Bird Right"),
|
||||||
SpriteBundle {
|
// In contrast to the above, here we rely on the default `RenderAssetUsages` loader setting
|
||||||
// In contrast to the above, here we rely on the default `RenderAssetUsages` loader
|
Sprite::from_image(asset_server.load(bird_right.get_texture_path())),
|
||||||
// setting.
|
Transform::from_xyz(200.0, 0.0, 0.0),
|
||||||
texture: asset_server.load(bird_right.get_texture_path()),
|
|
||||||
transform: Transform::from_xyz(200.0, 0.0, 0.0),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
bird_right,
|
bird_right,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,25 +99,20 @@ fn main() {
|
||||||
.init_asset::<GzAsset>()
|
.init_asset::<GzAsset>()
|
||||||
.init_asset_loader::<GzAssetLoader>()
|
.init_asset_loader::<GzAssetLoader>()
|
||||||
.add_systems(Startup, setup)
|
.add_systems(Startup, setup)
|
||||||
.add_systems(Update, decompress::<Image>)
|
.add_systems(Update, decompress::<Sprite, Image>)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
commands.spawn(Camera2d);
|
commands.spawn(Camera2d);
|
||||||
|
|
||||||
commands.spawn((
|
commands.spawn(Compressed::<Image> {
|
||||||
Compressed::<Image> {
|
compressed: asset_server.load("data/compressed_image.png.gz"),
|
||||||
compressed: asset_server.load("data/compressed_image.png.gz"),
|
..default()
|
||||||
..default()
|
});
|
||||||
},
|
|
||||||
Sprite::default(),
|
|
||||||
Transform::default(),
|
|
||||||
Visibility::default(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decompress<A: Asset>(
|
fn decompress<T: Component + From<Handle<A>>, A: Asset>(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
mut compressed_assets: ResMut<Assets<GzAsset>>,
|
mut compressed_assets: ResMut<Assets<GzAsset>>,
|
||||||
|
@ -133,6 +128,6 @@ fn decompress<A: Asset>(
|
||||||
commands
|
commands
|
||||||
.entity(entity)
|
.entity(entity)
|
||||||
.remove::<Compressed<A>>()
|
.remove::<Compressed<A>>()
|
||||||
.insert(asset_server.add(uncompressed));
|
.insert(T::from(asset_server.add(uncompressed)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,15 +23,14 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
// If you are using a very small image and rendering it larger like seen here, the default linear filtering will result in a blurry image.
|
// If you are using a very small image and rendering it larger like seen here, the default linear filtering will result in a blurry image.
|
||||||
// Useful note: The default sampler specified by the ImagePlugin is *not* the same as the default implementation of sampler. This is why
|
// Useful note: The default sampler specified by the ImagePlugin is *not* the same as the default implementation of sampler. This is why
|
||||||
// everything uses linear by default but if you look at the default of sampler, it uses nearest.
|
// everything uses linear by default but if you look at the default of sampler, it uses nearest.
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn((
|
||||||
texture: asset_server.load("bevy_pixel_dark.png"),
|
Sprite {
|
||||||
sprite: Sprite {
|
image: asset_server.load("bevy_pixel_dark.png"),
|
||||||
custom_size: Some(Vec2 { x: 160.0, y: 120.0 }),
|
custom_size: Some(Vec2 { x: 160.0, y: 120.0 }),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
transform: Transform::from_xyz(-100.0, 0.0, 0.0),
|
Transform::from_xyz(-100.0, 0.0, 0.0),
|
||||||
..Default::default()
|
));
|
||||||
});
|
|
||||||
|
|
||||||
// When a .meta file is added with the same name as the asset and a '.meta' extension
|
// When a .meta file is added with the same name as the asset and a '.meta' extension
|
||||||
// you can (and must) specify all fields of the asset loader's settings for that
|
// you can (and must) specify all fields of the asset loader's settings for that
|
||||||
|
@ -42,15 +41,14 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
// A good reference when filling this out is to check out [ImageLoaderSettings::default()]
|
// A good reference when filling this out is to check out [ImageLoaderSettings::default()]
|
||||||
// and follow to the default implementation of each fields type.
|
// and follow to the default implementation of each fields type.
|
||||||
// https://docs.rs/bevy/latest/bevy/render/texture/struct.ImageLoaderSettings.html#
|
// https://docs.rs/bevy/latest/bevy/render/texture/struct.ImageLoaderSettings.html#
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn((
|
||||||
texture: asset_server.load("bevy_pixel_dark_with_meta.png"),
|
Sprite {
|
||||||
sprite: Sprite {
|
image: asset_server.load("bevy_pixel_dark_with_meta.png"),
|
||||||
custom_size: Some(Vec2 { x: 160.0, y: 120.0 }),
|
custom_size: Some(Vec2 { x: 160.0, y: 120.0 }),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
transform: Transform::from_xyz(100.0, 0.0, 0.0),
|
Transform::from_xyz(100.0, 0.0, 0.0),
|
||||||
..Default::default()
|
));
|
||||||
});
|
|
||||||
|
|
||||||
// Another option is to use the AssetServers load_with_settings function.
|
// Another option is to use the AssetServers load_with_settings function.
|
||||||
// With this you can specify the same settings upon loading your asset with a
|
// With this you can specify the same settings upon loading your asset with a
|
||||||
|
@ -62,20 +60,19 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
// settings changes from any loads after the first of the same asset will be ignored.
|
// settings changes from any loads after the first of the same asset will be ignored.
|
||||||
// This is why this one loads a differently named copy of the asset instead of using
|
// This is why this one loads a differently named copy of the asset instead of using
|
||||||
// same one as without a .meta file.
|
// same one as without a .meta file.
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn((
|
||||||
texture: asset_server.load_with_settings(
|
Sprite {
|
||||||
"bevy_pixel_dark_with_settings.png",
|
image: asset_server.load_with_settings(
|
||||||
|settings: &mut ImageLoaderSettings| {
|
"bevy_pixel_dark_with_settings.png",
|
||||||
settings.sampler = ImageSampler::nearest();
|
|settings: &mut ImageLoaderSettings| {
|
||||||
},
|
settings.sampler = ImageSampler::nearest();
|
||||||
),
|
},
|
||||||
sprite: Sprite {
|
),
|
||||||
custom_size: Some(Vec2 { x: 160.0, y: 120.0 }),
|
custom_size: Some(Vec2 { x: 160.0, y: 120.0 }),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
transform: Transform::from_xyz(0.0, 150.0, 0.0),
|
Transform::from_xyz(0.0, 150.0, 0.0),
|
||||||
..Default::default()
|
));
|
||||||
});
|
|
||||||
|
|
||||||
commands.spawn(Camera2d);
|
commands.spawn(Camera2d);
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,8 +61,5 @@ fn main() {
|
||||||
|
|
||||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
commands.spawn(Camera2d);
|
commands.spawn(Camera2d);
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn(Sprite::from_image(asset_server.load("branding/icon.png")));
|
||||||
texture: asset_server.load("branding/icon.png"),
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,8 +48,5 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
"embedded://embedded_asset/files/bevy_pixel_light.png".into()
|
"embedded://embedded_asset/files/bevy_pixel_light.png".into()
|
||||||
);
|
);
|
||||||
|
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn(Sprite::from_image(asset_server.load(asset_path)));
|
||||||
texture: asset_server.load(asset_path),
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,8 +42,5 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
// path.
|
// path.
|
||||||
assert_eq!(asset_path, "example_files://bevy_pixel_light.png".into());
|
assert_eq!(asset_path, "example_files://bevy_pixel_light.png".into());
|
||||||
|
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn(Sprite::from_image(asset_server.load(asset_path)));
|
||||||
texture: asset_server.load(asset_path),
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,26 +46,16 @@ fn setup(
|
||||||
.spawn((SpatialBundle::default(), listener.clone()))
|
.spawn((SpatialBundle::default(), listener.clone()))
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
// left ear
|
// left ear
|
||||||
parent.spawn(SpriteBundle {
|
parent.spawn((
|
||||||
sprite: Sprite {
|
Sprite::from_color(RED, Vec2::splat(20.0)),
|
||||||
color: RED.into(),
|
Transform::from_xyz(-gap / 2.0, 0.0, 0.0),
|
||||||
custom_size: Some(Vec2::splat(20.0)),
|
));
|
||||||
..default()
|
|
||||||
},
|
|
||||||
transform: Transform::from_xyz(-gap / 2.0, 0.0, 0.0),
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
|
|
||||||
// right ear
|
// right ear
|
||||||
parent.spawn(SpriteBundle {
|
parent.spawn((
|
||||||
sprite: Sprite {
|
Sprite::from_color(LIME, Vec2::splat(20.0)),
|
||||||
color: LIME.into(),
|
Transform::from_xyz(gap / 2.0, 0.0, 0.0),
|
||||||
custom_size: Some(Vec2::splat(20.0)),
|
));
|
||||||
..default()
|
|
||||||
},
|
|
||||||
transform: Transform::from_xyz(gap / 2.0, 0.0, 0.0),
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// example instructions
|
// example instructions
|
||||||
|
|
|
@ -68,15 +68,12 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
rotation_speed: 2.0,
|
rotation_speed: 2.0,
|
||||||
min_follow_radius: 50.0,
|
min_follow_radius: 50.0,
|
||||||
},
|
},
|
||||||
SpriteBundle {
|
Sprite {
|
||||||
sprite: Sprite {
|
image: texture,
|
||||||
color: bevy::color::palettes::tailwind::BLUE_800.into(),
|
color: bevy::color::palettes::tailwind::BLUE_800.into(),
|
||||||
..default()
|
..Default::default()
|
||||||
},
|
|
||||||
transform: Transform::from_translation(Vec3::ZERO),
|
|
||||||
texture,
|
|
||||||
..default()
|
|
||||||
},
|
},
|
||||||
|
Transform::from_translation(Vec3::ZERO),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,15 +96,12 @@ fn user_input(
|
||||||
rotation: rng.gen_range(0.0..std::f32::consts::TAU),
|
rotation: rng.gen_range(0.0..std::f32::consts::TAU),
|
||||||
rotation_speed: rng.gen_range(0.5..1.5),
|
rotation_speed: rng.gen_range(0.5..1.5),
|
||||||
},
|
},
|
||||||
SpriteBundle {
|
Sprite {
|
||||||
sprite: Sprite {
|
image: texture,
|
||||||
color: bevy::color::palettes::tailwind::RED_800.into(),
|
color: bevy::color::palettes::tailwind::RED_800.into(),
|
||||||
..default()
|
|
||||||
},
|
|
||||||
transform: Transform::from_translation(Vec3::ZERO),
|
|
||||||
texture,
|
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
|
Transform::from_translation(Vec3::ZERO),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,23 +18,21 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
|
|
||||||
// Spawn a root entity with no parent
|
// Spawn a root entity with no parent
|
||||||
let parent = commands
|
let parent = commands
|
||||||
.spawn(SpriteBundle {
|
.spawn((
|
||||||
transform: Transform::from_scale(Vec3::splat(0.75)),
|
Sprite::from_image(texture.clone()),
|
||||||
texture: texture.clone(),
|
Transform::from_scale(Vec3::splat(0.75)),
|
||||||
..default()
|
))
|
||||||
})
|
|
||||||
// With that entity as a parent, run a lambda that spawns its children
|
// With that entity as a parent, run a lambda that spawns its children
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
// parent is a ChildBuilder, which has a similar API to Commands
|
// parent is a ChildBuilder, which has a similar API to Commands
|
||||||
parent.spawn(SpriteBundle {
|
parent.spawn((
|
||||||
transform: Transform::from_xyz(250.0, 0.0, 0.0).with_scale(Vec3::splat(0.75)),
|
Transform::from_xyz(250.0, 0.0, 0.0).with_scale(Vec3::splat(0.75)),
|
||||||
texture: texture.clone(),
|
Sprite {
|
||||||
sprite: Sprite {
|
image: texture.clone(),
|
||||||
color: BLUE.into(),
|
color: BLUE.into(),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
})
|
})
|
||||||
// Store parent entity for next sections
|
// Store parent entity for next sections
|
||||||
.id();
|
.id();
|
||||||
|
@ -42,15 +40,14 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
// Another way is to use the add_child function to add children after the parent
|
// Another way is to use the add_child function to add children after the parent
|
||||||
// entity has already been spawned.
|
// entity has already been spawned.
|
||||||
let child = commands
|
let child = commands
|
||||||
.spawn(SpriteBundle {
|
.spawn((
|
||||||
transform: Transform::from_xyz(0.0, 250.0, 0.0).with_scale(Vec3::splat(0.75)),
|
Sprite {
|
||||||
texture,
|
image: texture,
|
||||||
sprite: Sprite {
|
|
||||||
color: LIME.into(),
|
color: LIME.into(),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
..default()
|
Transform::from_xyz(0.0, 250.0, 0.0).with_scale(Vec3::splat(0.75)),
|
||||||
})
|
))
|
||||||
.id();
|
.id();
|
||||||
|
|
||||||
// Add child to the parent.
|
// Add child to the parent.
|
||||||
|
|
|
@ -16,11 +16,8 @@ fn spawn_system(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
let mut rng = ChaCha8Rng::seed_from_u64(19878367467713);
|
let mut rng = ChaCha8Rng::seed_from_u64(19878367467713);
|
||||||
for _ in 0..128 {
|
for _ in 0..128 {
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite::from_image(texture.clone()),
|
||||||
texture: texture.clone(),
|
Transform::from_scale(Vec3::splat(0.1)),
|
||||||
transform: Transform::from_scale(Vec3::splat(0.1)),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
Velocity(20.0 * Vec2::new(rng.gen::<f32>() - 0.5, rng.gen::<f32>() - 0.5)),
|
Velocity(20.0 * Vec2::new(rng.gen::<f32>() - 0.5, rng.gen::<f32>() - 0.5)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,7 @@ struct MyComponent;
|
||||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
commands.spawn(Camera2d);
|
commands.spawn(Camera2d);
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite::from_image(asset_server.load("branding/icon.png")),
|
||||||
texture: asset_server.load("branding/icon.png"),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
// Add the `Component`.
|
// Add the `Component`.
|
||||||
MyComponent,
|
MyComponent,
|
||||||
));
|
));
|
||||||
|
|
|
@ -106,7 +106,8 @@ struct CollisionSound(Handle<AudioSource>);
|
||||||
struct WallBundle {
|
struct WallBundle {
|
||||||
// You can nest bundles inside of other bundles like this
|
// You can nest bundles inside of other bundles like this
|
||||||
// Allowing you to compose their functionality
|
// Allowing you to compose their functionality
|
||||||
sprite_bundle: SpriteBundle,
|
sprite: Sprite,
|
||||||
|
transform: Transform,
|
||||||
collider: Collider,
|
collider: Collider,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,21 +154,15 @@ impl WallBundle {
|
||||||
// making our code easier to read and less prone to bugs when we change the logic
|
// making our code easier to read and less prone to bugs when we change the logic
|
||||||
fn new(location: WallLocation) -> WallBundle {
|
fn new(location: WallLocation) -> WallBundle {
|
||||||
WallBundle {
|
WallBundle {
|
||||||
sprite_bundle: SpriteBundle {
|
sprite: Sprite::from_color(WALL_COLOR, Vec2::ONE),
|
||||||
transform: Transform {
|
transform: Transform {
|
||||||
// We need to convert our Vec2 into a Vec3, by giving it a z-coordinate
|
// We need to convert our Vec2 into a Vec3, by giving it a z-coordinate
|
||||||
// This is used to determine the order of our sprites
|
// This is used to determine the order of our sprites
|
||||||
translation: location.position().extend(0.0),
|
translation: location.position().extend(0.0),
|
||||||
// The z-scale of 2D objects must always be 1.0,
|
// The z-scale of 2D objects must always be 1.0,
|
||||||
// or their ordering will be affected in surprising ways.
|
// or their ordering will be affected in surprising ways.
|
||||||
// See https://github.com/bevyengine/bevy/issues/4149
|
// See https://github.com/bevyengine/bevy/issues/4149
|
||||||
scale: location.size().extend(1.0),
|
scale: location.size().extend(1.0),
|
||||||
..default()
|
|
||||||
},
|
|
||||||
sprite: Sprite {
|
|
||||||
color: WALL_COLOR,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
collider: Collider,
|
collider: Collider,
|
||||||
|
@ -200,16 +195,10 @@ fn setup(
|
||||||
let paddle_y = BOTTOM_WALL + GAP_BETWEEN_PADDLE_AND_FLOOR;
|
let paddle_y = BOTTOM_WALL + GAP_BETWEEN_PADDLE_AND_FLOOR;
|
||||||
|
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite::from_color(PADDLE_COLOR, Vec2::ONE),
|
||||||
transform: Transform {
|
Transform {
|
||||||
translation: Vec3::new(0.0, paddle_y, 0.0),
|
translation: Vec3::new(0.0, paddle_y, 0.0),
|
||||||
scale: PADDLE_SIZE.extend(1.0),
|
scale: PADDLE_SIZE.extend(1.0),
|
||||||
..default()
|
|
||||||
},
|
|
||||||
sprite: Sprite {
|
|
||||||
color: PADDLE_COLOR,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
Paddle,
|
Paddle,
|
||||||
|
@ -294,16 +283,13 @@ fn setup(
|
||||||
|
|
||||||
// brick
|
// brick
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite {
|
||||||
sprite: Sprite {
|
color: BRICK_COLOR,
|
||||||
color: BRICK_COLOR,
|
..default()
|
||||||
..default()
|
},
|
||||||
},
|
Transform {
|
||||||
transform: Transform {
|
translation: brick_position.extend(0.0),
|
||||||
translation: brick_position.extend(0.0),
|
scale: Vec3::new(BRICK_SIZE.x, BRICK_SIZE.y, 1.0),
|
||||||
scale: Vec3::new(BRICK_SIZE.x, BRICK_SIZE.y, 1.0),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
Brick,
|
Brick,
|
||||||
|
|
|
@ -106,17 +106,14 @@ fn setup_contributor_selection(mut commands: Commands, asset_server: Res<AssetSe
|
||||||
translation: velocity,
|
translation: velocity,
|
||||||
rotation: -dir * 5.0,
|
rotation: -dir * 5.0,
|
||||||
},
|
},
|
||||||
SpriteBundle {
|
Sprite {
|
||||||
sprite: Sprite {
|
image: texture_handle.clone(),
|
||||||
custom_size: Some(Vec2::splat(SPRITE_SIZE)),
|
custom_size: Some(Vec2::splat(SPRITE_SIZE)),
|
||||||
color: DESELECTED.with_hue(hue).into(),
|
color: DESELECTED.with_hue(hue).into(),
|
||||||
flip_x: flipped,
|
flip_x: flipped,
|
||||||
..default()
|
|
||||||
},
|
|
||||||
texture: texture_handle.clone(),
|
|
||||||
transform,
|
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
|
transform,
|
||||||
))
|
))
|
||||||
.id();
|
.id();
|
||||||
|
|
||||||
|
|
|
@ -135,10 +135,7 @@ fn setup(
|
||||||
// Spawn the Bevy logo sprite
|
// Spawn the Bevy logo sprite
|
||||||
commands
|
commands
|
||||||
.spawn((
|
.spawn((
|
||||||
SpriteBundle {
|
Sprite::from_image(asset_server.load("branding/icon.png")),
|
||||||
texture: asset_server.load("branding/icon.png"),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
BevyLogo,
|
BevyLogo,
|
||||||
))
|
))
|
||||||
.with_children(|commands| {
|
.with_children(|commands| {
|
||||||
|
|
|
@ -133,11 +133,8 @@ fn spawn_player(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
commands.spawn(Camera2d);
|
commands.spawn(Camera2d);
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
Name::new("Player"),
|
Name::new("Player"),
|
||||||
SpriteBundle {
|
Sprite::from_image(asset_server.load("branding/icon.png")),
|
||||||
texture: asset_server.load("branding/icon.png"),
|
Transform::from_scale(Vec3::splat(0.3)),
|
||||||
transform: Transform::from_scale(Vec3::splat(0.3)),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
AccumulatedInput::default(),
|
AccumulatedInput::default(),
|
||||||
Velocity::default(),
|
Velocity::default(),
|
||||||
PhysicalTranslation::default(),
|
PhysicalTranslation::default(),
|
||||||
|
|
|
@ -32,7 +32,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
commands.spawn(Camera2d);
|
commands.spawn(Camera2d);
|
||||||
|
|
||||||
let len = 128.0;
|
let len = 128.0;
|
||||||
let sprite_size = Some(Vec2::splat(len / 2.0));
|
let sprite_size = Vec2::splat(len / 2.0);
|
||||||
|
|
||||||
commands
|
commands
|
||||||
.spawn(SpatialBundle::default())
|
.spawn(SpatialBundle::default())
|
||||||
|
@ -57,35 +57,29 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
|
|
||||||
// spawn black square behind sprite to show anchor point
|
// spawn black square behind sprite to show anchor point
|
||||||
commands
|
commands
|
||||||
.spawn(SpriteBundle {
|
.spawn((
|
||||||
sprite: Sprite {
|
Sprite::from_color(Color::BLACK, sprite_size),
|
||||||
custom_size: sprite_size,
|
Transform::from_xyz(i * len - len, j * len - len, -1.0),
|
||||||
color: Color::BLACK,
|
))
|
||||||
..default()
|
|
||||||
},
|
|
||||||
transform: Transform::from_xyz(i * len - len, j * len - len, -1.0),
|
|
||||||
..default()
|
|
||||||
})
|
|
||||||
.observe(recolor_on::<Pointer<Over>>(Color::srgb(0.0, 1.0, 1.0)))
|
.observe(recolor_on::<Pointer<Over>>(Color::srgb(0.0, 1.0, 1.0)))
|
||||||
.observe(recolor_on::<Pointer<Out>>(Color::BLACK))
|
.observe(recolor_on::<Pointer<Out>>(Color::BLACK))
|
||||||
.observe(recolor_on::<Pointer<Down>>(Color::srgb(1.0, 1.0, 0.0)))
|
.observe(recolor_on::<Pointer<Down>>(Color::srgb(1.0, 1.0, 0.0)))
|
||||||
.observe(recolor_on::<Pointer<Up>>(Color::srgb(0.0, 1.0, 1.0)));
|
.observe(recolor_on::<Pointer<Up>>(Color::srgb(0.0, 1.0, 1.0)));
|
||||||
|
|
||||||
commands
|
commands
|
||||||
.spawn(SpriteBundle {
|
.spawn((
|
||||||
sprite: Sprite {
|
Sprite {
|
||||||
custom_size: sprite_size,
|
image: asset_server.load("branding/bevy_bird_dark.png"),
|
||||||
|
custom_size: Some(sprite_size),
|
||||||
color: Color::srgb(1.0, 0.0, 0.0),
|
color: Color::srgb(1.0, 0.0, 0.0),
|
||||||
anchor: anchor.to_owned(),
|
anchor: anchor.to_owned(),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
texture: asset_server.load("branding/bevy_bird_dark.png"),
|
|
||||||
// 3x3 grid of anchor examples by changing transform
|
// 3x3 grid of anchor examples by changing transform
|
||||||
transform: Transform::from_xyz(i * len - len, j * len - len, 0.0)
|
Transform::from_xyz(i * len - len, j * len - len, 0.0)
|
||||||
.with_scale(Vec3::splat(1.0 + (i - 1.0) * 0.2))
|
.with_scale(Vec3::splat(1.0 + (i - 1.0) * 0.2))
|
||||||
.with_rotation(Quat::from_rotation_z((j - 1.0) * 0.2)),
|
.with_rotation(Quat::from_rotation_z((j - 1.0) * 0.2)),
|
||||||
..default()
|
))
|
||||||
})
|
|
||||||
.observe(recolor_on::<Pointer<Over>>(Color::srgb(0.0, 1.0, 0.0)))
|
.observe(recolor_on::<Pointer<Over>>(Color::srgb(0.0, 1.0, 0.0)))
|
||||||
.observe(recolor_on::<Pointer<Out>>(Color::srgb(1.0, 0.0, 0.0)))
|
.observe(recolor_on::<Pointer<Out>>(Color::srgb(1.0, 0.0, 0.0)))
|
||||||
.observe(recolor_on::<Pointer<Down>>(Color::srgb(0.0, 0.0, 1.0)))
|
.observe(recolor_on::<Pointer<Down>>(Color::srgb(0.0, 0.0, 1.0)))
|
||||||
|
@ -131,15 +125,14 @@ fn setup_atlas(
|
||||||
let animation_indices = AnimationIndices { first: 1, last: 6 };
|
let animation_indices = AnimationIndices { first: 1, last: 6 };
|
||||||
commands
|
commands
|
||||||
.spawn((
|
.spawn((
|
||||||
TextureAtlas {
|
Sprite::from_atlas_image(
|
||||||
layout: texture_atlas_layout_handle,
|
texture_handle,
|
||||||
index: animation_indices.first,
|
TextureAtlas {
|
||||||
},
|
layout: texture_atlas_layout_handle,
|
||||||
SpriteBundle {
|
index: animation_indices.first,
|
||||||
texture: texture_handle,
|
},
|
||||||
transform: Transform::from_xyz(300.0, 0.0, 0.0).with_scale(Vec3::splat(6.0)),
|
),
|
||||||
..default()
|
Transform::from_xyz(300.0, 0.0, 0.0).with_scale(Vec3::splat(6.0)),
|
||||||
},
|
|
||||||
animation_indices,
|
animation_indices,
|
||||||
AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
|
AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
|
||||||
))
|
))
|
||||||
|
|
|
@ -67,15 +67,14 @@ fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
|
||||||
let image0 = images.add(image.clone());
|
let image0 = images.add(image.clone());
|
||||||
let image1 = images.add(image);
|
let image1 = images.add(image);
|
||||||
|
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn((
|
||||||
sprite: Sprite {
|
Sprite {
|
||||||
|
image: image0.clone(),
|
||||||
custom_size: Some(Vec2::new(SIZE.0 as f32, SIZE.1 as f32)),
|
custom_size: Some(Vec2::new(SIZE.0 as f32, SIZE.1 as f32)),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
texture: image0.clone(),
|
Transform::from_scale(Vec3::splat(DISPLAY_FACTOR as f32)),
|
||||||
transform: Transform::from_scale(Vec3::splat(DISPLAY_FACTOR as f32)),
|
));
|
||||||
..default()
|
|
||||||
});
|
|
||||||
commands.spawn(Camera2d);
|
commands.spawn(Camera2d);
|
||||||
|
|
||||||
commands.insert_resource(GameOfLifeImages {
|
commands.insert_resource(GameOfLifeImages {
|
||||||
|
|
|
@ -423,10 +423,7 @@ mod ui {
|
||||||
pub fn setup_game(mut commands: Commands, asset_server: Res<AssetServer>) {
|
pub fn setup_game(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
StateScoped(InGame),
|
StateScoped(InGame),
|
||||||
SpriteBundle {
|
Sprite::from_image(asset_server.load("branding/icon.png")),
|
||||||
texture: asset_server.load("branding/icon.png"),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -223,10 +223,7 @@ fn setup(mut commands: Commands) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_game(mut commands: Commands, asset_server: Res<AssetServer>) {
|
fn setup_game(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn(Sprite::from_image(asset_server.load("branding/icon.png")));
|
||||||
texture: asset_server.load("branding/icon.png"),
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
info!("Setup game");
|
info!("Setup game");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,10 +120,7 @@ fn cleanup_menu(mut commands: Commands, menu_data: Res<MenuData>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_game(mut commands: Commands, asset_server: Res<AssetServer>) {
|
fn setup_game(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn(Sprite::from_image(asset_server.load("branding/icon.png")));
|
||||||
texture: asset_server.load("branding/icon.png"),
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const SPEED: f32 = 100.0;
|
const SPEED: f32 = 100.0;
|
||||||
|
|
|
@ -198,10 +198,7 @@ mod ui {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_game(mut commands: Commands, asset_server: Res<AssetServer>) {
|
pub fn setup_game(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn(Sprite::from_image(asset_server.load("branding/icon.png")));
|
||||||
texture: asset_server.load("branding/icon.png"),
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_paused_screen(mut commands: Commands) {
|
pub fn setup_paused_screen(mut commands: Commands) {
|
||||||
|
|
|
@ -433,16 +433,16 @@ fn spawn_birds(
|
||||||
color
|
color
|
||||||
};
|
};
|
||||||
(
|
(
|
||||||
SpriteBundle {
|
Sprite {
|
||||||
texture: bird_resources
|
image: bird_resources
|
||||||
.textures
|
.textures
|
||||||
.choose(&mut bird_resources.material_rng)
|
.choose(&mut bird_resources.material_rng)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.clone(),
|
.clone(),
|
||||||
transform,
|
color,
|
||||||
sprite: Sprite { color, ..default() },
|
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
|
transform,
|
||||||
Bird { velocity },
|
Bird { velocity },
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -82,19 +82,16 @@ fn setup(
|
||||||
timer.set_elapsed(Duration::from_secs_f32(rng.gen::<f32>()));
|
timer.set_elapsed(Duration::from_secs_f32(rng.gen::<f32>()));
|
||||||
|
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite {
|
||||||
texture: texture_handle.clone(),
|
image: texture_handle.clone(),
|
||||||
transform: Transform {
|
custom_size: Some(tile_size),
|
||||||
translation,
|
|
||||||
rotation,
|
|
||||||
scale,
|
|
||||||
},
|
|
||||||
sprite: Sprite {
|
|
||||||
custom_size: Some(tile_size),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
|
Transform {
|
||||||
|
translation,
|
||||||
|
rotation,
|
||||||
|
scale,
|
||||||
|
},
|
||||||
TextureAtlas::from(texture_atlas_handle.clone()),
|
TextureAtlas::from(texture_atlas_handle.clone()),
|
||||||
AnimationTimer(timer),
|
AnimationTimer(timer),
|
||||||
));
|
));
|
||||||
|
|
|
@ -81,14 +81,9 @@ fn setup(mut commands: Commands, assets: Res<AssetServer>, color_tint: Res<Color
|
||||||
let rotation = Quat::from_rotation_z(rng.gen::<f32>());
|
let rotation = Quat::from_rotation_z(rng.gen::<f32>());
|
||||||
let scale = Vec3::splat(rng.gen::<f32>() * 2.0);
|
let scale = Vec3::splat(rng.gen::<f32>() * 2.0);
|
||||||
|
|
||||||
sprites.push(SpriteBundle {
|
sprites.push((
|
||||||
texture: sprite_handle.clone(),
|
Sprite {
|
||||||
transform: Transform {
|
image: sprite_handle.clone(),
|
||||||
translation,
|
|
||||||
rotation,
|
|
||||||
scale,
|
|
||||||
},
|
|
||||||
sprite: Sprite {
|
|
||||||
custom_size: Some(tile_size),
|
custom_size: Some(tile_size),
|
||||||
color: if color_tint.0 {
|
color: if color_tint.0 {
|
||||||
COLORS[rng.gen_range(0..3)]
|
COLORS[rng.gen_range(0..3)]
|
||||||
|
@ -97,8 +92,12 @@ fn setup(mut commands: Commands, assets: Res<AssetServer>, color_tint: Res<Color
|
||||||
},
|
},
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
..default()
|
Transform {
|
||||||
});
|
translation,
|
||||||
|
rotation,
|
||||||
|
scale,
|
||||||
|
},
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
commands.spawn_batch(sprites);
|
commands.spawn_batch(sprites);
|
||||||
|
|
|
@ -53,27 +53,21 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut time: ResMu
|
||||||
|
|
||||||
// the sprite moving based on real time
|
// the sprite moving based on real time
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite::from_image(texture_handle.clone()),
|
||||||
texture: texture_handle.clone(),
|
Transform::from_scale(sprite_scale),
|
||||||
transform: Transform::from_scale(sprite_scale),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
RealTime,
|
RealTime,
|
||||||
));
|
));
|
||||||
|
|
||||||
// the sprite moving based on virtual time
|
// the sprite moving based on virtual time
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
SpriteBundle {
|
Sprite {
|
||||||
texture: texture_handle,
|
image: texture_handle,
|
||||||
sprite: Sprite {
|
color: virtual_color,
|
||||||
color: virtual_color,
|
..Default::default()
|
||||||
..default()
|
},
|
||||||
},
|
Transform {
|
||||||
transform: Transform {
|
scale: sprite_scale,
|
||||||
scale: sprite_scale,
|
translation: Vec3::new(0., -160., 0.),
|
||||||
translation: Vec3::new(0., -160., 0.),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
VirtualTime,
|
VirtualTime,
|
||||||
|
|
|
@ -282,34 +282,20 @@ fn setup_sticks(
|
||||||
})
|
})
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
// full extent
|
// full extent
|
||||||
parent.spawn(SpriteBundle {
|
parent.spawn(Sprite::from_color(
|
||||||
sprite: Sprite {
|
DEAD_COLOR,
|
||||||
custom_size: Some(Vec2::splat(STICK_BOUNDS_SIZE * 2.)),
|
Vec2::splat(STICK_BOUNDS_SIZE * 2.),
|
||||||
color: DEAD_COLOR,
|
));
|
||||||
..default()
|
|
||||||
},
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
// live zone
|
// live zone
|
||||||
parent.spawn(SpriteBundle {
|
parent.spawn((
|
||||||
transform: Transform::from_xyz(live_mid, live_mid, 2.),
|
Sprite::from_color(LIVE_COLOR, Vec2::splat(live_size)),
|
||||||
sprite: Sprite {
|
Transform::from_xyz(live_mid, live_mid, 2.),
|
||||||
custom_size: Some(Vec2::new(live_size, live_size)),
|
));
|
||||||
color: LIVE_COLOR,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
// dead zone
|
// dead zone
|
||||||
parent.spawn(SpriteBundle {
|
parent.spawn((
|
||||||
transform: Transform::from_xyz(dead_mid, dead_mid, 3.),
|
Sprite::from_color(DEAD_COLOR, Vec2::splat(dead_size)),
|
||||||
sprite: Sprite {
|
Transform::from_xyz(dead_mid, dead_mid, 3.),
|
||||||
custom_size: Some(Vec2::new(dead_size, dead_size)),
|
));
|
||||||
color: DEAD_COLOR,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
// text
|
// text
|
||||||
let style = TextStyle {
|
let style = TextStyle {
|
||||||
font_size: 13.,
|
font_size: 13.,
|
||||||
|
|
|
@ -32,8 +32,5 @@ fn main() {
|
||||||
|
|
||||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
commands.spawn(Camera2d);
|
commands.spawn(Camera2d);
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn(Sprite::from_image(asset_server.load("branding/icon.png")));
|
||||||
texture: asset_server.load("branding/icon.png"),
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,12 +71,8 @@ fn setup_2d(mut commands: Commands) {
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn(Sprite::from_color(
|
||||||
sprite: Sprite {
|
Color::srgb(0.25, 0.25, 0.75),
|
||||||
color: Color::srgb(0.25, 0.25, 0.75),
|
Vec2::new(50.0, 50.0),
|
||||||
custom_size: Some(Vec2::new(50.0, 50.0)),
|
));
|
||||||
..default()
|
|
||||||
},
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,12 +147,8 @@ fn setup_2d(mut commands: Commands) {
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn(Sprite::from_color(
|
||||||
sprite: Sprite {
|
Color::srgb(0.25, 0.25, 0.75),
|
||||||
color: Color::srgb(0.25, 0.25, 0.75),
|
Vec2::new(50.0, 50.0),
|
||||||
custom_size: Some(Vec2::new(50.0, 50.0)),
|
));
|
||||||
..default()
|
|
||||||
},
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue