bevyjam/src/filters.rs

104 lines
2.3 KiB
Rust

use crate::game::Level;
use bevy::prelude::{shape::Quad, *};
use bevy_rapier2d::prelude::*;
#[derive(Component)]
pub enum PassThroughFilter {
/// Absorbs this color (ignoring alpha)
Absorbing(Color),
/// Rotates hue by this angle (in degrees)
Rotating(f32),
}
impl PassThroughFilter {
pub fn apply(&self, color: Color) -> Color {
match self {
PassThroughFilter::Absorbing(filter_color) => Vec4::from(color)
.mul_add(
-Vec4::from(*filter_color) * Vec4::from([1., 1., 1., 0.]),
Vec4::from(color),
)
.into(),
PassThroughFilter::Rotating(filter_angle) => {
let mut hsla = color.as_hsla_f32();
hsla[0] = (hsla[0] + filter_angle) % 360.;
// floating rem is not modulo!
if hsla[0] < 0. {
hsla[0] += 360.;
}
Color::hsla(hsla[0], hsla[1], hsla[2], hsla[3])
}
}
}
}
#[derive(Bundle)]
pub struct AbsorbingFilter {
#[bundle]
pub mesh: ColorMesh2dBundle,
pub collider: Collider,
pub sensor: Sensor,
pub filter: PassThroughFilter,
}
pub fn spawn_absorbing_filter(
commands: &mut Commands,
meshes: &mut ResMut<Assets<Mesh>>,
materials: &mut ResMut<Assets<ColorMaterial>>,
transform: Transform,
size: Vec2,
color: Color,
) {
let mut material_color = color;
material_color.set_a(0.5);
commands
.spawn_bundle(AbsorbingFilter {
mesh: ColorMesh2dBundle {
mesh: meshes.add(Mesh::from(Quad { size, flip: false })).into(),
material: materials.add(material_color.into()),
transform,
..Default::default()
},
collider: Collider::cuboid(size.x / 2., size.y / 2.),
sensor: Sensor,
filter: PassThroughFilter::Absorbing(color),
})
.insert(Level);
}
#[derive(Bundle)]
pub struct RotatingFilter {
#[bundle]
pub sprite: SpriteBundle,
pub collider: Collider,
pub sensor: Sensor,
pub filter: PassThroughFilter,
pub velocity: Velocity,
pub rigid_body: RigidBody,
}
pub fn spawn_rotating_filter(
commands: &mut Commands,
asset_server: &Res<AssetServer>,
transform: Transform,
angle: f32,
) {
commands
.spawn_bundle(RotatingFilter {
sprite: SpriteBundle {
texture: asset_server.get_handle("bevy.png"),
transform,
..Default::default()
},
collider: Collider::ball(32.),
sensor: Sensor,
filter: PassThroughFilter::Rotating(angle),
velocity: Velocity::angular(1.),
rigid_body: RigidBody::KinematicVelocityBased,
})
.insert(Level);
}