More correct parallax example!

main
Elijah Voigt 2 months ago
parent 1525cc75f9
commit 4a2bbf3242

BIN
assets/bevy.png (Stored with Git LFS)

Binary file not shown.

@ -9,7 +9,6 @@ fn main() {
},)) },))
.add_systems(Startup, spawn_background) .add_systems(Startup, spawn_background)
.add_systems(Update, move_camera) .add_systems(Update, move_camera)
.add_systems(Update, parallax_gizmos)
.run(); .run();
} }
@ -17,43 +16,55 @@ fn spawn_background(
mut commands: Commands, mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>, mut materials: ResMut<Assets<ColorMaterial>>,
server: Res<AssetServer>,
) { ) {
let mesh = Mesh2d(meshes.add(Circle::new(1.0)));
commands.spawn(( commands.spawn((
Name::new("Depth: 1.1"), Name::new("Depth: 1.0"),
Transform::default().with_translation(Vec3::new(0.0, 0.0, 0.0)).with_scale(Vec3::splat(50.0)), Transform::default().with_translation(Vec3::new(0.0, 0.0, 0.0)).with_scale(Vec3::splat(50.0)),
mesh.clone(), Mesh2d(meshes.add(Circle::new(1.0))),
MeshMaterial2d(materials.add(ColorMaterial::from_color(RED))), MeshMaterial2d(materials.add(ColorMaterial {
ParallaxDepth(1.1), texture: Some(server.load("bevy.png")),
color: RED.into(),
..default()
})),
ParallaxDepth(1.0),
Visibility::Inherited, Visibility::Inherited,
children![(Text2d("1.1".into()), Transform::from_xyz(0.0, 35.0, 0.0))],
)); ));
commands.spawn(( commands.spawn((
Name::new("Depth: 2.1"), Name::new("Depth: 2.0"),
Transform::default().with_translation(Vec3::new(0.0, 0.0, -1.0)).with_scale(Vec3::splat(50.0)), Transform::default().with_translation(Vec3::new(0.0, 0.0, -1.0)).with_scale(Vec3::splat(25.0)),
mesh.clone(), Mesh2d(meshes.add(Circle::new(2.0))),
MeshMaterial2d(materials.add(ColorMaterial::from_color(GREEN))), MeshMaterial2d(materials.add(ColorMaterial {
ParallaxDepth(2.1), texture: Some(server.load("bevy.png")),
color: GREEN.into(),
..default()
})),
ParallaxDepth(2.0),
Visibility::Inherited, Visibility::Inherited,
children![(Text2d("2.0".into()), Transform::from_xyz(0.0, 35.0, 0.0))],
)); ));
commands.spawn(( commands.spawn((
Name::new("Depth: 4.1"), Name::new("Depth: 4.0"),
Transform::default().with_translation(Vec3::new(0.0, 0.0, -2.0)).with_scale(Vec3::splat(50.0)), Transform::default().with_translation(Vec3::new(0.0, 0.0, -2.0)).with_scale(Vec3::splat(12.5)),
mesh.clone(), Mesh2d(meshes.add(Circle::new(4.0))),
MeshMaterial2d(materials.add(ColorMaterial::from_color(BLUE))), MeshMaterial2d(materials.add(ColorMaterial {
ParallaxDepth(4.1), texture: Some(server.load("bevy.png")),
color: BLUE.into(),
..default()
})),
ParallaxDepth(4.0),
Visibility::Inherited, Visibility::Inherited,
children![(Text2d("4.1".into()), Transform::from_xyz(0.0, 35.0, 0.0))],
)); ));
commands.spawn(( commands.spawn((
Name::new("Depth: 8.1"), Name::new("Depth: 8.0"),
Transform::default().with_translation(Vec3::new(0.0, 0.0, -3.0)).with_scale(Vec3::splat(50.0)), Transform::default().with_translation(Vec3::new(0.0, 0.0, -3.0)).with_scale(Vec3::splat(6.25)),
mesh.clone(), Mesh2d(meshes.add(Circle::new(8.0))),
MeshMaterial2d(materials.add(ColorMaterial::from_color(YELLOW))), MeshMaterial2d(materials.add(ColorMaterial {
ParallaxDepth(8.1), texture: Some(server.load("bevy.png")),
color: YELLOW.into(),
..default()
})),
ParallaxDepth(8.0),
Visibility::Inherited, Visibility::Inherited,
children![(Text2d("8.1".into()), Transform::from_xyz(0.0, 35.0, 0.0))],
)); ));
} }
@ -70,18 +81,3 @@ fn move_camera(mut t: Single<&mut Transform, With<Camera2d>>, keys: Res<ButtonIn
t.translation.y += 5.0; t.translation.y += 5.0;
} }
} }
fn parallax_gizmos(mut gizmos: Gizmos, q: Query<&Transform, With<ParallaxDepth>>) {
// Closest to camera
// Parallax(1)
q.iter().for_each(|t| {
gizmos
.grid_2d(
t.translation.truncate(),
UVec2::new(5, 5),
Vec2::splat(10.),
MAGENTA,
)
.outer_edges();
});
}

@ -36,6 +36,7 @@ fn main() {
init_bird.after(init_assets), init_bird.after(init_assets),
init_first_batches.after(init_assets), init_first_batches.after(init_assets),
init_ui, init_ui,
init_background,
tweak_camera.after(create_camera_2d), tweak_camera.after(create_camera_2d),
), ),
) )
@ -699,6 +700,47 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
)); ));
} }
fn init_background(
mut commands: Commands,
server: Res<AssetServer>,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
{
let material = MeshMaterial2d(materials.add(ColorMaterial {
texture: Some(server.load("flappy/background-city.png")),
color: BLACK.into(),
alpha_mode: AlphaMode2d::Blend,
..default()
}));
let mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.0)));
let t = Transform::from_xyz(0.0, 0.0, -32.0).with_scale(Vec3::splat(650.0));
commands.spawn((ParallaxDepth(4.0), mesh, material, t));
}
{
let material = MeshMaterial2d(materials.add(ColorMaterial {
texture: Some(server.load("flappy/background-clouds.png")),
color: BLACK.into(),
alpha_mode: AlphaMode2d::Blend,
..default()
}));
let mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.0)));
let t = Transform::from_xyz(0.0, 0.0, -64.0).with_scale(Vec3::splat(650.0));
commands.spawn((ParallaxDepth(8.0), mesh, material, t));
}
{
let material = MeshMaterial2d(materials.add(ColorMaterial {
texture: Some(server.load("flappy/background-gradient.png")),
color: BLACK.into(),
alpha_mode: AlphaMode2d::Blend,
..default()
}));
let mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.0)));
let t = Transform::from_xyz(0.0, 0.0, -128.0).with_scale(Vec3::splat(650.0));
commands.spawn((ParallaxDepth(16.0), mesh, material, t));
}
}
fn start_rewind(_trigger: Trigger<Pointer<Pressed>>, mut next: ResMut<NextState<PlayerState>>) { fn start_rewind(_trigger: Trigger<Pointer<Pressed>>, mut next: ResMut<NextState<PlayerState>>) {
next.set(PlayerState::Rewind); next.set(PlayerState::Rewind);
} }

@ -1,3 +1,6 @@
use bevy::render::primitives::Aabb;
use bevy::render::mesh::MeshAabb;
use super::*; use super::*;
pub struct ParallaxPlugin; pub struct ParallaxPlugin;
@ -54,9 +57,10 @@ fn move_parallax_items(
} }
fn wrap_parallax_items( fn wrap_parallax_items(
mut items: Query<(&mut Transform, &GlobalTransform, &ViewVisibility), (With<ParallaxDepth>, Without<Camera2d>, Changed<ViewVisibility>)>, mut items: Query<(&mut Transform, &GlobalTransform, &ViewVisibility, &Mesh2d), (With<ParallaxDepth>, Without<Camera2d>, Changed<ViewVisibility>)>,
camera: Single<(&Camera, &GlobalTransform), With<Camera2d>>, camera: Single<(&Camera, &GlobalTransform), With<Camera2d>>,
window: Single<&Window>, window: Single<&Window>,
meshes: Res<Assets<Mesh>>,
) { ) {
if !items.is_empty() { if !items.is_empty() {
let (cam, cam_gt) = *camera; let (cam, cam_gt) = *camera;
@ -68,26 +72,28 @@ fn wrap_parallax_items(
Vec2::abs(Vec2::new(bottom_right.x - top_left.x, bottom_right.y - top_left.y)) Vec2::abs(Vec2::new(bottom_right.x - top_left.x, bottom_right.y - top_left.y))
}; };
debug!("Window size: {:?}", window_size_in_world_space);
// for each item in the paralax items // for each item in the paralax items
items.iter_mut().for_each(|(mut t, gt, v)| { items.iter_mut().for_each(|(mut t, gt, v, Mesh2d(m))| {
if !v.get() { if !v.get() {
debug!("The item is not visible"); info!("Item is not visible");
// Get the total size (window + scale) // Get the total size (window + scale)
let total_size = window_size_in_world_space + (t.scale.truncate() * 2.0); let half_extents = {
debug!("Window size: {:?} | Object size: {:?}", window_size_in_world_space, t.scale.truncate()); let Aabb { half_extents, .. } = meshes.get(m).unwrap().compute_aabb().unwrap();
debug!("Total size: {:?}", total_size); half_extents.truncate()
};
let object_size = t.scale.truncate() * 2.0;
let total_size = window_size_in_world_space + (object_size * half_extents);
info!("Sizes:\n\twindow {window_size_in_world_space}\n\tobject size: {object_size}\n\tAabb Half extents: {half_extents}\n\tTotal size: {total_size}");
// Double check that item is out of bounds // Double check that item is out of bounds
let bounds_check = Vec2::abs(cam_gt.translation().truncate() - gt.translation().truncate()); let bounds_check = Vec2::abs(cam_gt.translation().truncate() - gt.translation().truncate());
let out_of_bounds = (total_size / 2.0) - bounds_check; let out_of_bounds = (total_size / 2.0) - bounds_check;
debug!("Bounds check {:?}", bounds_check); info!("Bounds check {bounds_check} | Out of bounds: {out_of_bounds:?}");
debug!("Out of bounds: {:?}", out_of_bounds);
debug!("Starting position: {:?}", t.translation); info!("Starting position: {:?}", t.translation);
if out_of_bounds.x < 0.0 { if out_of_bounds.x < 0.0 {
debug!("Object is actually out of bounds horizontally"); info!("Object is actually out of bounds horizontally");
// determine if should move to the left or right relative to camera // determine if should move to the left or right relative to camera
let move_right = cam_gt.translation().x > gt.translation().x; let move_right = cam_gt.translation().x > gt.translation().x;
@ -99,7 +105,7 @@ fn wrap_parallax_items(
} }
} }
if out_of_bounds.y < 0.0 { if out_of_bounds.y < 0.0 {
debug!("Object is actually out of bounds vertically"); info!("Object is actually out of bounds vertically");
let move_up = cam_gt.translation().y > gt.translation().y; let move_up = cam_gt.translation().y > gt.translation().y;
// move up or down // move up or down
@ -109,7 +115,7 @@ fn wrap_parallax_items(
t.translation.y -= total_size.y; t.translation.y -= total_size.y;
} }
} }
debug!("Moved to {:?}", t.translation); info!("Moved to {:?}", t.translation);
} }
}); });
} }

Loading…
Cancel
Save