//! Demonstrates rotating entities in 2D using quaternions. use bevy::{math::ops, 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, ), ) .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"); commands.spawn(Camera2d); // Create a minimal UI explaining how to interact with the example commands.spawn(( Text::new("Up Arrow: Move Forward\nLeft / Right Arrow: Turn"), Node { position_type: PositionType::Absolute, top: Val::Px(12.0), left: Val::Px(12.0), ..default() }, )); let horizontal_margin = BOUNDS.x / 4.0; let vertical_margin = BOUNDS.y / 4.0; // Player controlled ship commands.spawn(( Sprite::from_image(ship_handle), 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(( Sprite::from_image(enemy_a_handle.clone()), Transform::from_xyz(0.0 - horizontal_margin, 0.0, 0.0), SnapToPlayer, )); commands.spawn(( Sprite::from_image(enemy_a_handle), Transform::from_xyz(0.0, 0.0 - vertical_margin, 0.0), SnapToPlayer, )); // Enemy that rotates to face the player enemy spawns on the top and right commands.spawn(( Sprite::from_image(enemy_b_handle.clone()), Transform::from_xyz(0.0 + horizontal_margin, 0.0, 0.0), RotateToPlayer { rotation_speed: f32::to_radians(45.0), // Degrees per second }, )); commands.spawn(( Sprite::from_image(enemy_b_handle), Transform::from_xyz(0.0, 0.0 + vertical_margin, 0.0), 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