prototypes/life: Adding colors and sound, broken but saving my place

main
Elijah Voigt 1 month ago
parent 839dd3d5a6
commit 314e604067

@ -1,11 +1,12 @@
// TODO: Rearchitected so it's Cell and Coordiantes not Cell { position { coordiantes } }
use bevy::picking::hover::Hovered;
use std::time::Duration;
use bevy::{picking::hover::Hovered, platform::collections::HashMap};
use engine::*;
const GREY_TILE: &str = "tileGrey_01.png";
const BLACK_TILE: &str = "tileBlack_01.png";
const BACKGROUND: &str = "texture_08.png";
const TILE: &str = "tileGrey_01.png";
const FRAME_DURATION: f32 = 0.5;
fn main() {
let file_path = {
@ -24,10 +25,14 @@ fn main() {
..default()
}))
.init_resource::<Coordinates>()
.init_resource::<CellAssets>()
.init_state::<SimulationState>()
.add_message::<Lifecycle>()
.add_message::<SimulationState>()
.add_systems(Startup, setup)
.add_systems(Startup, load_audio_tones)
.add_systems(Startup, load_materials)
.add_systems(Startup, load_meshes)
.add_systems(
Update,
update_grid_position.run_if(on_message::<CursorMoved>),
@ -51,7 +56,7 @@ fn main() {
Update,
simulation_step
.run_if(in_state(SimulationState::Run))
.run_if(cooldown_secs(0.5)),
.run_if(cooldown_secs(FRAME_DURATION)),
)
.add_systems(
Update,
@ -118,7 +123,7 @@ fn on_add_ui_button(
},
BackgroundColor(GRAY.into()),
ImageNode {
image: server.load(GREY_TILE),
image: server.load(TILE),
color: WHITE.with_alpha(0.5).into(),
..default()
},
@ -202,17 +207,6 @@ fn setup(mut commands: Commands) {
_ => todo!(),
});
}
// Spawn Coordiantes
commands
.spawn((Transform::default(), Visibility::Visible))
.with_children(|parent| {
for x in -10..10 {
for y in -10..10 {
parent.spawn(Coordinates { x, y });
}
}
});
}
#[derive(Debug, Default, Clone, PartialEq, Hash, Eq, Component, Resource)]
@ -264,6 +258,37 @@ impl Coordinates {
fn as_translation(&self) -> Vec3 {
(Vec2::new(self.x as f32, self.y as f32) * SCALE).extend(0.0)
}
fn as_color(&self) -> Color {
// hue (0..360.0) evenly spaced x in -2..4
// chroma (0..1) evenly spaced y in -2..5
let hue = (360.0 / 5.0) * ((self.x + 2) % 5) as f32;
let chroma = (1.0 / 5.0) * ((self.y + 2) % 5) as f32;
let lightness = (1.0 / 5.0) * ((self.y + 2) % 5) as f32;
Color::Oklcha(Oklcha {
hue,
chroma,
lightness,
..default()
})
}
fn as_cell_pitch(&self) -> CellPitch {
let note = match (self.x % 5) - 2 {
-2 => Note::A,
-1 => Note::B,
0 => Note::CSharp,
1 => Note::E,
2 => Note::FSharp,
_ => panic!("This shouldn't happen!"),
};
let octave = (self.y % 5) - 2;
CellPitch {
note, octave
}
}
}
fn on_add_coordinates(
@ -271,37 +296,30 @@ fn on_add_coordinates(
coordinates: Query<&Coordinates>,
cells: Query<&Cell>,
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
server: ResMut<AssetServer>,
cell_assets: Res<CellAssets>,
) {
// TODO: Reuse the same mesh
let mesh = {
let mesh_h = meshes.add(Rectangle::new(SCALE, SCALE));
Mesh2d(mesh_h)
};
let c = coordinates.get(trigger.entity).unwrap();
// TODO: Resuse the same material
let mat = {
let image: Handle<Image> = if cells.contains(trigger.entity) {
server.load(BLACK_TILE)
} else {
server.load(BACKGROUND)
};
let mat_h = materials.add(image);
MeshMaterial2d(mat_h)
// based on coordinates, get material, mesh, and tone from cell_assets
if cells.contains(trigger.entity) {
let mat_h = cell_assets.materials.get(c).unwrap();
let mesh_mat_2d = MeshMaterial2d(mat_h.clone());
commands.entity(trigger.entity).insert(mesh_mat_2d);
let mesh_2d = Mesh2d(cell_assets.mesh.clone());
commands.entity(trigger.entity).insert(mesh_2d);
};
let t = {
let c = coordinates.get(trigger.entity).unwrap();
if cells.contains(trigger.entity) {
Transform::from_translation(c.as_translation() + Vec3::new(0.0, 0.0, 1.0))
} else {
Transform::from_translation(c.as_translation())
}
let t = if cells.contains(trigger.entity) {
Transform::from_translation(c.as_translation() + Vec3::new(0.0, 0.0, 1.0))
} else {
Transform::from_translation(c.as_translation())
};
commands.entity(trigger.entity).insert(t);
commands.entity(trigger.entity).insert((mesh, mat, t));
// FIXME!!!
let p = cell_assets.pitches.get(&c.as_cell_pitch()).unwrap();
commands.entity(trigger.entity).insert((AudioPlayer(p.clone()), PlaybackSettings::LOOP));
}
/// When the cursor moves, update the Coordiantes
@ -510,3 +528,117 @@ fn visualize_ui_state(
// Scale grid with background?
// Pan camera: click and drag
#[derive(Resource, Default)]
struct CellAssets {
pitches: HashMap<CellPitch, Handle<Pitch>>,
materials: HashMap<Coordinates, Handle<ColorMaterial>>,
mesh: Handle<Mesh>,
}
#[derive(Hash, PartialEq, Eq, Debug, Clone)]
enum Note {
A,
B,
CSharp,
E,
FSharp,
}
impl Note {
fn as_frequency(&self) -> f32 {
match self {
Note::A => 440.0,
Note::B => 493.88,
Note::CSharp => 553.37,
Note::E => 659.25,
Note::FSharp => 698.46,
}
}
}
#[derive(Hash, PartialEq, Eq, Debug)]
struct CellPitch {
note: Note,
octave: isize,
}
impl CellPitch {
/// Pitches:
/// A -440 Hz
/// B - 493.88 Hz
/// C# - 554.37 Hz
/// E - 659.25 Hz
/// F# - 698.46 Hz
fn to_frequency(&self) -> f32 {
let base_note = self.note.as_frequency();
match self.octave {
// Negative octave values -> lower notes
..=-1 => base_note / (self.octave as f32),
0 => base_note,
// Positive octave values -> higher notes
1.. => base_note * (self.octave as f32),
}
}
}
fn load_audio_tones(mut pitches: ResMut<Assets<Pitch>>, mut cell_assets: ResMut<CellAssets>) {
let duration = Duration::from_secs_f32(FRAME_DURATION);
let notes = [Note::A, Note::B, Note::CSharp, Note::E, Note::FSharp];
let octaves = [-2, -1, 0, 1, 2];
notes.iter().for_each(|note| {
octaves.iter().for_each(|octave| {
let cell_pitch = CellPitch {
note: note.clone(),
octave: *octave,
};
let frequency = cell_pitch.to_frequency();
let handle = pitches.add(Pitch {
frequency,
duration,
});
cell_assets.pitches.insert(cell_pitch, handle);
});
});
}
fn load_materials(
server: ResMut<AssetServer>,
mut cell_assets: ResMut<CellAssets>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
let vertical = [-2, -1, 0, 1, 2];
let horizontal = [-2, -1, 0, 1, 2];
let texture = server.load(TILE);
vertical.iter().for_each(|&x| {
horizontal.iter().for_each(|&y| {
let c = Coordinates { x, y };
let color = c.as_color();
cell_assets.materials.insert(
c,
materials.add(ColorMaterial {
texture: Some(texture.clone()),
color,
..default()
}),
);
});
});
}
fn load_meshes(mut cell_assets: ResMut<CellAssets>, mut meshes: ResMut<Assets<Mesh>>) {
cell_assets.mesh = meshes.add(Rectangle::new(SCALE, SCALE));
}
fn play_audio_tone(cell_assets: Res<CellAssets>, mut commands: Commands) {
let handle = cell_assets
.pitches
.get(&CellPitch {
note: Note::A,
octave: 0,
})
.unwrap();
commands.spawn((AudioPlayer(handle.clone()), PlaybackSettings::LOOP));
}

Loading…
Cancel
Save