//! Demonstrates rotating entities in 2D using quaternions. use bevy::prelude::*; const BOUNDS: Vec2 = Vec2::new(1200.0, 640.0); fn main() { App::new() .add_plugins(DefaultPlugins) .insert_resource(Time::::from_hz(60.0)) .add_systems(Startup, setup) .add_systems( FixedUpdate, ( player_movement_system, snap_to_player_system, rotate_to_player_system, ), ) .add_systems(Update, bevy::window::close_on_esc) .run(); } /// player component #[derive(Component)] struct Player { /// linear speed in meters per second movement_speed: f32, /// rotation speed in radians per second rotation_speed: f32, } /// snap to player ship behavior #[derive(Component)] struct SnapToPlayer; /// rotate to face player ship behavior #[derive(Component)] struct RotateToPlayer { /// rotation speed in radians per second rotation_speed: f32, } /// Add the game's entities to our world and creates an orthographic camera for 2D rendering. /// /// The Bevy coordinate system is the same for 2D and 3D, in terms of 2D this means that: /// /// * `X` axis goes from left to right (`+X` points right) /// * `Y` axis goes from bottom to top (`+Y` point up) /// * `Z` axis goes from far to near (`+Z` points towards you, out of the screen) /// /// The origin is at the center of the screen. fn setup(mut commands: Commands, asset_server: Res) { let ship_handle = asset_server.load("textures/simplespace/ship_C.png"); let enemy_a_handle = asset_server.load("textures/simplespace/enemy_A.png"); let enemy_b_handle = asset_server.load("textures/simplespace/enemy_B.png"); // 2D orthographic camera commands.spawn(Camera2dBundle::default()); let horizontal_margin = BOUNDS.x / 4.0; let vertical_margin = BOUNDS.y / 4.0; // player controlled ship commands.spawn(( SpriteBundle { texture: ship_handle, ..default() }, Player { movement_speed: 500.0, // meters per second rotation_speed: f32::to_radians(360.0), // degrees per second }, )); // enemy that snaps to face the player spawns on the bottom and left commands.spawn(( SpriteBundle { texture: enemy_a_handle.clone(), transform: Transform::from_xyz(0.0 - horizontal_margin, 0.0, 0.0), ..default() }, SnapToPlayer, )); commands.spawn(( SpriteBundle { texture: enemy_a_handle, transform: Transform::from_xyz(0.0, 0.0 - vertical_margin, 0.0), ..default() }, SnapToPlayer, )); // enemy that rotates to face the player enemy spawns on the top and right commands.spawn(( SpriteBundle { texture: enemy_b_handle.clone(), transform: Transform::from_xyz(0.0 + horizontal_margin, 0.0, 0.0), ..default() }, RotateToPlayer { rotation_speed: f32::to_radians(45.0), // degrees per second }, )); commands.spawn(( SpriteBundle { texture: enemy_b_handle, transform: Transform::from_xyz(0.0, 0.0 + vertical_margin, 0.0), ..default() }, RotateToPlayer { rotation_speed: f32::to_radians(90.0), // degrees per second }, )); } /// Demonstrates applying rotation and movement based on keyboard input. fn player_movement_system( time: Res