chore(deps): upgrade Bevy 0.13 → 0.18
Three major versions of breaking changes: - Bundles → Required Components (SpriteBundle, NodeBundle, ButtonBundle, TextBundle, Camera2dBundle removed; spawn tuples of components instead) - Style merged into Node; TextStyle split into TextFont + TextColor - Color API: rgb/rgba → srgb/srgba; Color::Rgba pattern matching replaced with .alpha()/.set_alpha(); .r()/.g()/.b() → .to_srgba().red/green/blue - Time: delta_seconds() → delta_secs(); elapsed_seconds() → elapsed_secs() - Query: get_single()/get_single_mut() → single()/single_mut() (now Result) - Timer::finished() → Timer::is_finished() - despawn_recursive() removed (despawn() is now recursive); despawn_descendants() removed — replaced with Children query iteration - BorderColor(c) → BorderColor::all(c) - WindowResolution: From<(f32,f32)> removed → cast to (u32,u32) - flake.nix: added wayland to runtime libs (default-on in 0.18) Tests pass (8/8), clippy clean, headless render verified showing start menu, button, starfield, and player ship. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7a4305677b
commit
b2b564f690
11 changed files with 2746 additions and 1028 deletions
|
|
@ -14,19 +14,16 @@ use crate::systems::spawn_explosion;
|
|||
// Helper to spawn player (used in setup and respawn)
|
||||
pub fn spawn_player_ship(commands: &mut Commands) {
|
||||
commands.spawn((
|
||||
SpriteBundle {
|
||||
sprite: Sprite {
|
||||
color: Color::rgb(0.0, 0.5, 1.0),
|
||||
custom_size: Some(PLAYER_SIZE),
|
||||
..default()
|
||||
},
|
||||
transform: Transform::from_translation(Vec3::new(
|
||||
0.0,
|
||||
-WINDOW_HEIGHT / 2.0 + PLAYER_SIZE.y / 2.0 + 20.0,
|
||||
0.0,
|
||||
)),
|
||||
Sprite {
|
||||
color: Color::srgb(0.0, 0.5, 1.0),
|
||||
custom_size: Some(PLAYER_SIZE),
|
||||
..default()
|
||||
},
|
||||
Transform::from_translation(Vec3::new(
|
||||
0.0,
|
||||
-WINDOW_HEIGHT / 2.0 + PLAYER_SIZE.y / 2.0 + 20.0,
|
||||
0.0,
|
||||
)),
|
||||
Player {
|
||||
speed: PLAYER_SPEED,
|
||||
shoot_cooldown: Timer::new(Duration::from_secs_f32(0.3), TimerMode::Once),
|
||||
|
|
@ -48,7 +45,7 @@ pub fn move_player(
|
|||
time: Res<Time>,
|
||||
) {
|
||||
// Using get_single_mut handles the case where player might not exist yet (or was just destroyed)
|
||||
if let Ok((mut transform, player)) = query.get_single_mut() {
|
||||
if let Ok((mut transform, player)) = query.single_mut() {
|
||||
let mut direction = 0.0;
|
||||
|
||||
if keyboard_input.pressed(KeyCode::KeyA) || keyboard_input.pressed(KeyCode::ArrowLeft) {
|
||||
|
|
@ -59,7 +56,7 @@ pub fn move_player(
|
|||
direction += 1.0;
|
||||
}
|
||||
|
||||
transform.translation.x += direction * player.speed * time.delta_seconds();
|
||||
transform.translation.x += direction * player.speed * time.delta_secs();
|
||||
let half_player_width = PLAYER_SIZE.x / 2.0;
|
||||
transform.translation.x = transform.translation.x.clamp(
|
||||
-WINDOW_WIDTH / 2.0 + half_player_width,
|
||||
|
|
@ -124,7 +121,7 @@ pub fn handle_captured_player(
|
|||
}
|
||||
|
||||
// If capture duration expires, player escapes but loses a life
|
||||
if captured.timer.finished() {
|
||||
if captured.timer.is_finished() {
|
||||
println!("Player escaped from capture after timer expired!");
|
||||
commands.entity(entity).remove::<Captured>();
|
||||
lose_life_and_respawn(
|
||||
|
|
@ -175,12 +172,12 @@ pub fn player_shoot(
|
|||
mut commands: Commands,
|
||||
time: Res<Time>,
|
||||
) {
|
||||
if let Ok((player_transform, mut player)) = query.get_single_mut() {
|
||||
if let Ok((player_transform, mut player)) = query.single_mut() {
|
||||
player.shoot_cooldown.tick(time.delta());
|
||||
|
||||
if (keyboard_input.just_pressed(KeyCode::Space)
|
||||
|| keyboard_input.just_pressed(KeyCode::ArrowUp))
|
||||
&& player.shoot_cooldown.finished()
|
||||
&& player.shoot_cooldown.is_finished()
|
||||
{
|
||||
player.shoot_cooldown.reset();
|
||||
|
||||
|
|
@ -188,15 +185,12 @@ pub fn player_shoot(
|
|||
+ Vec3::Y * (PLAYER_SIZE.y / 2.0 + BULLET_SIZE.y / 2.0);
|
||||
|
||||
commands.spawn((
|
||||
SpriteBundle {
|
||||
sprite: Sprite {
|
||||
color: Color::rgb(1.0, 1.0, 1.0),
|
||||
custom_size: Some(BULLET_SIZE),
|
||||
..default()
|
||||
},
|
||||
transform: Transform::from_translation(bullet_start_pos),
|
||||
Sprite {
|
||||
color: Color::srgb(1.0, 1.0, 1.0),
|
||||
custom_size: Some(BULLET_SIZE),
|
||||
..default()
|
||||
},
|
||||
Transform::from_translation(bullet_start_pos),
|
||||
Bullet,
|
||||
));
|
||||
}
|
||||
|
|
@ -217,7 +211,7 @@ pub fn check_player_enemy_collisions(
|
|||
enemy_query: Query<(Entity, &Transform), With<Enemy>>,
|
||||
) {
|
||||
// This system only runs if player exists and is not invincible, due to run_if
|
||||
if let Ok((player_entity, player_transform)) = player_query.get_single() {
|
||||
if let Ok((player_entity, player_transform)) = player_query.single() {
|
||||
for (enemy_entity, enemy_transform) in enemy_query.iter() {
|
||||
let distance = player_transform
|
||||
.translation
|
||||
|
|
@ -285,7 +279,7 @@ pub fn manage_invincibility(
|
|||
};
|
||||
}
|
||||
|
||||
if invincible.timer.finished() {
|
||||
if invincible.timer.is_finished() {
|
||||
println!("Invincibility finished.");
|
||||
commands.entity(entity).remove::<Invincible>();
|
||||
// Ensure player is visible when invincibility ends
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue