Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorporate AtlasSprite rework for upcoming Bevy 1.13 #15

Merged
merged 11 commits into from
Feb 26, 2024
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ repository = "https://github.com/FraserLee/bevy_sprite3d"
keywords = ["gamedev", "bevy", "sprite", "3d"]

[dependencies.bevy]
version = "0.12"
version = "0.13"
default-features = false
features = ["bevy_asset", "bevy_pbr", "bevy_sprite"]

[dev-dependencies]
bevy.version = "0.12" # (include default features when running examples)
bevy.version = "0.13" # (include default features when running examples)
rand = "0.8"
114 changes: 68 additions & 46 deletions examples/dungeon.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use bevy::{prelude::*, window::WindowResolution};
use bevy::asset::LoadState;
use bevy::core_pipeline::bloom::BloomSettings;
use bevy::core_pipeline::clear_color::ClearColorConfig;
use bevy::core_pipeline::tonemapping::Tonemapping;
use bevy::render::camera::PerspectiveProjection;
use bevy::utils::Duration;
use bevy::pbr::ScreenSpaceAmbientOcclusionBundle;
use bevy::core_pipeline::experimental::taa::TemporalAntiAliasBundle;
Expand All @@ -26,7 +24,7 @@ enum GameState { #[default] Loading, Ready }
#[derive(Resource, Default)]
struct ImageAssets {
image: Handle<Image>,
tileset: Handle<TextureAtlas>,
layout: Handle<TextureAtlasLayout>,
}


Expand All @@ -43,17 +41,17 @@ fn main() {
}))
.insert_resource(Msaa::Off)
.add_plugins(Sprite3dPlugin)
.add_state::<GameState>()
.init_state::<GameState>()

// initially load assets
.add_systems(Startup, |asset_server: Res<AssetServer>,
mut assets: ResMut<ImageAssets>,
mut texture_atlases: ResMut<Assets<TextureAtlas>>| {
.add_systems(Startup, |asset_server: Res<AssetServer>,
mut assets: ResMut<ImageAssets>,
mut layouts: ResMut<Assets<TextureAtlasLayout>>| {

assets.image = asset_server.load("dungeon/tileset_padded.png");

assets.tileset = texture_atlases.add(
TextureAtlas::from_grid(assets.image.clone(),
assets.layout = layouts.add(
TextureAtlasLayout::from_grid(
Vec2::new(16.0, 16.0),
30,
35,
Expand All @@ -63,7 +61,7 @@ fn main() {
})

// every frame check if assets are loaded. Once they are, we can proceed with setup.
.add_systems( Update, (
.add_systems(Update, (
|asset_server : Res<AssetServer>,
assets : Res<ImageAssets>,
mut next_state : ResMut<NextState<GameState>>| {
Expand Down Expand Up @@ -99,23 +97,23 @@ fn setup(
) {
// cube
commands.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
material: materials.add(Color::WHITE.into()),
mesh: meshes.add(Mesh::from(Cuboid::from_size(Vec3::splat(1.0)))),
material: materials.add(Color::WHITE),
transform: Transform::from_xyz(-0.9, 0.5, -3.1),
..default()
});
// sphere
commands.spawn(PbrBundle {
mesh: meshes.add(shape::Icosphere { radius: 0.6, subdivisions: 20 }.try_into().unwrap()),
material: materials.add(Color::WHITE.into()),
mesh: meshes.add(Sphere::new(0.6)),
material: materials.add(Color::WHITE),
transform: Transform::from_xyz(-0.9, 0.5, -4.2),
..default()
});

// camera
commands.spawn((Camera3dBundle {
camera: Camera { hdr: true, ..default() },
camera_3d: Camera3d {
camera: Camera {
hdr: true,
clear_color: ClearColorConfig::Custom(Color::rgb(1.0, 1.0, 1.0) * 0.0),
..default()
},
Expand Down Expand Up @@ -211,14 +209,18 @@ fn spawn_sprites(
let (x, y) = (x as f32 - map[y].len() as f32 / 2.0, y as f32 - map.len() as f32 / 2.0);
if index == 0 { continue; }

commands.spawn(AtlasSprite3d {
atlas: images.tileset.clone(),
let atlas = TextureAtlas {
layout: images.layout.clone(),
index: index as usize,
};

commands.spawn(Sprite3d {
image: images.image.clone(),
pixels_per_metre: 16.,
index: index as usize,
double_sided: false,
transform: Transform::from_xyz(x, 0.0, y).with_rotation(Quat::from_rotation_x(-std::f32::consts::PI / 2.0)),
..default()
}.bundle(&mut sprite_params));
}.bundle_with_atlas(&mut sprite_params, atlas));
}
}

Expand Down Expand Up @@ -259,17 +261,21 @@ fn spawn_sprites(

let (x, y) = (x as f32 - map[y].len() as f32 / 2.0, y as f32 - map.len() as f32 / 2.0);

for i in [0,1]{ // add bottom and top piece
commands.spawn(AtlasSprite3d {
atlas: images.tileset.clone(),
for i in [0,1] { // add bottom and top piece
let atlas = TextureAtlas {
layout: images.layout.clone(),
index: (tile_x + (5 - i) * 30) as usize,
};

commands.spawn(Sprite3d {
image: images.image.clone(),
pixels_per_metre: 16.,
index: (tile_x + (5 - i) * 30) as usize,
double_sided: false,
transform: Transform::from_xyz(x+0.5, i as f32 + 0.499, y)
.with_rotation(Quat::from_rotation_y(
dir * std::f32::consts::PI / 2.0)),
..default()
}.bundle(&mut sprite_params));
}.bundle_with_atlas(&mut sprite_params, atlas));
}
}
}
Expand All @@ -293,16 +299,20 @@ fn spawn_sprites(
let (x, y) = (x as f32 - map[y].len() as f32 / 2.0, y as f32 - map.len() as f32 / 2.0);

for i in [0,1]{ // add bottom and top piece
commands.spawn(AtlasSprite3d {
atlas: images.tileset.clone(),
let atlas = TextureAtlas {
layout: images.layout.clone(),
index: (tile_x + (5 - i) * 30) as usize,
};

commands.spawn(Sprite3d {
image: images.image.clone(),
pixels_per_metre: 16.,
index: (tile_x + (5 - i) * 30) as usize,
double_sided: false,
transform: Transform::from_xyz(x, i as f32 + 0.499, y + 0.5)
.with_rotation(Quat::from_rotation_y(
(dir - 1.0) * std::f32::consts::PI / 2.0)),
..default()
}.bundle(&mut sprite_params));
}.bundle_with_atlas(&mut sprite_params, atlas));
}
}
}
Expand All @@ -314,13 +324,17 @@ fn spawn_sprites(
timer.set_elapsed(Duration::from_secs_f32(rng.gen_range(0.0..0.4)));

for i in 0usize..height {
let mut c = commands.spawn((AtlasSprite3d {
atlas: images.tileset.clone(),
let atlas = TextureAtlas {
layout: images.layout.clone(),
index: (tile_x + (tile_y - i) * 30) as usize,
};

let mut c = commands.spawn((Sprite3d {
image: images.image.clone(),
pixels_per_metre: 16.,
index: (tile_x + (tile_y - i) * 30) as usize,
transform: Transform::from_xyz(x as f32, i as f32 + 0.498, y),
..default()
}.bundle(&mut sprite_params),
}.bundle_with_atlas(&mut sprite_params, atlas),
FaceCamera {},
));

Expand Down Expand Up @@ -350,15 +364,19 @@ fn spawn_sprites(
entity((4.2, -8.), 13, 16, 2, 1);

// fire
commands.spawn((AtlasSprite3d {
atlas: images.tileset.clone(),
let atlas = TextureAtlas {
layout: images.layout.clone(),
index: 30*32 + 14,
};

commands.spawn((Sprite3d {
image: images.image.clone(),
pixels_per_metre: 16.,
index: 30*32 + 14,
transform: Transform::from_xyz(2.0, 0.5, -5.5),
emissive: Color::rgb(1.0, 0.5, 0.0) * 10.0,
unlit: true,
..default()
}.bundle(&mut sprite_params),
}.bundle_with_atlas(&mut sprite_params, atlas),

Animation {
frames: vec![30*32 + 14, 30*32 + 15, 30*32 + 16],
Expand All @@ -370,7 +388,7 @@ fn spawn_sprites(
));
commands.spawn(PointLightBundle {
point_light: PointLight {
intensity: 300.0,
intensity: 500_000.0,
color: Color::rgb(1.0, 231./255., 221./255.),
shadows_enabled: true,
..default()
Expand All @@ -380,21 +398,25 @@ fn spawn_sprites(
});

// glowy book
commands.spawn((AtlasSprite3d {
atlas: images.tileset.clone(),
let atlas = TextureAtlas {
layout: images.layout.clone(),
index: 22*30 + 22,
};

commands.spawn((Sprite3d {
image: images.image.clone(),
pixels_per_metre: 16.,
index: 22*30 + 22,
transform: Transform::from_xyz(-5., 0.7, 6.5),
emissive: Color::rgb(165./255., 1.0, 160./255.),
unlit: true,
..default()
}.bundle(&mut sprite_params),
}.bundle_with_atlas(&mut sprite_params, atlas),

FaceCamera {}
));
commands.spawn(PointLightBundle {
point_light: PointLight {
intensity: 100.0,
intensity: 70_000.0,
color: Color::rgb(91./255., 1.0, 92./255.),
shadows_enabled: true,
..default()
Expand Down Expand Up @@ -432,12 +454,12 @@ fn animate_camera(

fn animate_sprites(
time: Res<Time>,
mut query: Query<(&mut Animation, &mut AtlasSprite3dComponent)>,
mut query: Query<(&mut Animation, &mut TextureAtlas)>,
) {
for (mut animation, mut sprite) in query.iter_mut() {
for (mut animation, mut atlas) in query.iter_mut() {
animation.timer.tick(time.delta());
if animation.timer.just_finished() {
sprite.index = animation.frames[animation.current];
atlas.index = animation.frames[animation.current];
animation.current += 1;
animation.current %= animation.frames.len();
}
Expand Down
2 changes: 1 addition & 1 deletion examples/sprite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(Sprite3dPlugin)
.add_state::<GameState>()
.init_state::<GameState>()

// initially load assets
.add_systems( Startup, |asset_server: Res<AssetServer>, mut assets: ResMut<Assets>| {
Expand Down
32 changes: 16 additions & 16 deletions examples/sprite_sheet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ enum GameState { #[default] Loading, Ready }

#[derive(Resource, Default)]
struct ImageAssets {
image: Handle<Image>, // the `image` field here is only used to query the load state, lots of the
atlas: Handle<TextureAtlas>, // code in this file disappears if something like bevy_asset_loader is used.
image: Handle<Image>, // the `image` field here is only used to query the load state, lots of the
layout: Handle<TextureAtlasLayout>, // code in this file disappears if something like bevy_asset_loader is used.
}

#[derive(Component, Deref, DerefMut)]
Expand All @@ -19,17 +19,16 @@ fn main() {
App::new()
.add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
.add_plugins(Sprite3dPlugin)
.add_state::<GameState>()
.init_state::<GameState>()

// initially load assets
.add_systems(Startup, |asset_server: Res<AssetServer>,
mut assets: ResMut<ImageAssets>,
mut texture_atlases: ResMut<Assets<TextureAtlas>>| {
mut texture_atlases: ResMut<Assets<TextureAtlasLayout>>| {

assets.image = asset_server.load("gabe-idle-run.png");

assets.atlas = texture_atlases.add(
TextureAtlas::from_grid(assets.image.clone(), Vec2::new(24.0, 24.0), 7, 1, None, None)
assets.layout = texture_atlases.add(
TextureAtlasLayout::from_grid(Vec2::new(24.0, 24.0), 7, 1, None, None)
);
})

Expand Down Expand Up @@ -65,20 +64,21 @@ fn setup(

// -------------------- Spawn a 3D atlas sprite --------------------------

commands.spawn(AtlasSprite3d {
atlas: assets.atlas.clone(),
let texture_atlas = TextureAtlas {
layout: assets.layout.clone(),
index: 3,
};

commands.spawn(Sprite3d {
image: assets.image.clone(),
pixels_per_metre: 32.,
alpha_mode: AlphaMode::Blend,
unlit: true,

index: 3,

// transform: Transform::from_xyz(0., 0., 0.),
// pivot: Some(Vec2::new(0.5, 0.5)),

..default()
}.bundle(&mut sprite_params))
}.bundle_with_atlas(&mut sprite_params, texture_atlas))
.insert(AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)));

// -----------------------------------------------------------------------
Expand All @@ -87,12 +87,12 @@ fn setup(

fn animate_sprite(
time: Res<Time>,
mut query: Query<(&mut AnimationTimer, &mut AtlasSprite3dComponent)>,
mut query: Query<(&mut AnimationTimer, &mut TextureAtlas, &TextureAtlas3dData)>,
) {
for (mut timer, mut sprite) in query.iter_mut() {
for (mut timer, mut atlas, data) in query.iter_mut() {
timer.tick(time.delta());
if timer.just_finished() {
sprite.index = (sprite.index + 1) % sprite.atlas.len();
atlas.index = (atlas.index + 1) % data.keys.len();
}
}
}
Loading