use std::f32::consts;
use bevy::prelude::*;
#[derive(Debug, Component, Deref, DerefMut)]
struct CollisionShape(impacted::CollisionShape);
#[derive(Component)]
struct Controlled;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, startup)
.add_systems(PreUpdate, control_shape)
.add_systems(Update, (update_shape_transforms, update_color).chain())
.run();
}
fn startup(mut commands: Commands) {
commands.spawn(Camera2dBundle::default());
commands
.spawn(SpriteBundle {
sprite: Sprite {
custom_size: Some(Vec2::splat(100.0)),
color: Color::BLUE,
..Default::default()
},
transform: Transform::from_translation(Vec3::new(-200., 0.0, 0.0)),
..Default::default()
})
.insert((
CollisionShape(impacted::CollisionShape::new_rectangle(100.0, 100.0)),
Controlled,
));
commands
.spawn(SpriteBundle {
sprite: Sprite {
custom_size: Some(Vec2::splat(100.0)),
color: Color::BLUE,
..Default::default()
},
transform: Transform::from_translation(Vec3::new(200., 0.0, 0.0)),
..Default::default()
})
.insert(CollisionShape(impacted::CollisionShape::new_rectangle(
100.0, 100.0,
)));
}
fn update_shape_transforms(
mut shapes: Query<(&mut CollisionShape, &GlobalTransform), Changed<GlobalTransform>>,
) {
for (mut shape, transform) in shapes.iter_mut() {
let (scale, rotation, translation) = transform.to_scale_rotation_translation();
shape.set_transform(impacted::Transform::from_scale_angle_translation(
scale.truncate(),
angle_2d_from_quat(rotation),
translation.truncate(),
));
}
}
fn angle_2d_from_quat(quat: Quat) -> f32 {
if quat.is_near_identity() {
return 0.0;
}
let projected = quat.to_scaled_axis().project_onto(Vec3::Z);
let angle = projected.length();
if projected.z < 0.0 {
-angle
} else {
angle
}
}
fn update_color(
mut all_shapes: Query<(Entity, &mut Sprite, &CollisionShape)>,
moved_shapes: Query<(Entity, &CollisionShape), Changed<CollisionShape>>,
) {
for (moved_entity, moved_shape) in moved_shapes.iter() {
let mut is_collided = false;
for (other_entity, mut other_sprite, other_shape) in all_shapes.iter_mut() {
if other_entity == moved_entity {
continue; }
if moved_shape.is_collided_with(other_shape) {
other_sprite.color = Color::RED;
is_collided = true;
} else {
other_sprite.color = Color::BLUE;
}
}
let (_, mut sprite, _) = all_shapes.get_mut(moved_entity).unwrap();
sprite.color = if is_collided { Color::RED } else { Color::BLUE }
}
}
fn control_shape(
input: Res<Input<KeyCode>>,
time: Res<Time>,
mut transforms: Query<&mut Transform, With<Controlled>>,
) {
const LIN_SPEED: f32 = 200.0;
const ANG_SPEED: f32 = consts::FRAC_PI_2;
let lin_delta = Vec3::new(
get_input_axis(&input, KeyCode::Left, KeyCode::Right),
get_input_axis(&input, KeyCode::Down, KeyCode::Up),
0.0,
)
.normalize_or_zero()
* (LIN_SPEED * time.delta_seconds());
let ang_delta = Quat::from_axis_angle(
Vec3::Z,
get_input_axis(&input, KeyCode::D, KeyCode::A) * ANG_SPEED * time.delta_seconds(),
);
for mut transform in transforms.iter_mut() {
transform.translation += lin_delta;
transform.rotation *= ang_delta;
}
fn get_input_axis(input: &Input<KeyCode>, negative: KeyCode, positive: KeyCode) -> f32 {
let mut res = 0.0;
if input.pressed(positive) {
res += 1.0;
}
if input.pressed(negative) {
res -= 1.0;
}
res
}
}