first
This commit is contained in:
+90
@@ -0,0 +1,90 @@
|
||||
use std::time::Instant;
|
||||
use crate::grid::{Grid, NoteType};
|
||||
|
||||
pub const LOOP_LENGTH: u32 = 16;
|
||||
|
||||
pub struct Nome {
|
||||
/// Tempo in beats per minute
|
||||
pub tempo: u32,
|
||||
|
||||
// A count _in beats_ of where we are in the loop
|
||||
timer: f32,
|
||||
|
||||
/// Whether or not we're playing; false == paused
|
||||
pub playing: bool,
|
||||
|
||||
// The instant of the last time we called tick()
|
||||
last_tick: Option<Instant>,
|
||||
|
||||
/// The grids that we currently have going
|
||||
pub grids: Vec<Grid>,
|
||||
|
||||
// Running count of windows created (for ids)
|
||||
window_counter: usize
|
||||
}
|
||||
|
||||
impl Default for Nome {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
tempo: 90,
|
||||
timer: 0.0,
|
||||
playing: true,
|
||||
last_tick: None,
|
||||
grids: vec![],
|
||||
window_counter: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Nome {
|
||||
/// Call this every frame to update the timer / last tick based on the current instant
|
||||
/// and the tempo
|
||||
pub fn tick(&mut self) -> bool {
|
||||
let now = Instant::now();
|
||||
let old_beat = self.beat();
|
||||
if let Some(last) = self.last_tick && self.playing {
|
||||
let dt = (now - last).as_secs_f32();
|
||||
let bps = (self.tempo as f32) / 60.0;
|
||||
// Timer is an amount of time _in beats_ and some of those beats might have been for a
|
||||
// different tempo.
|
||||
// We know now a time delta in seconds and a conversion factor to turn that to beats, so:
|
||||
self.timer += dt * bps;
|
||||
// 16 beats in the loop, so timer should never be over 16:
|
||||
while self.timer > LOOP_LENGTH as f32 { self.timer -= LOOP_LENGTH as f32 }
|
||||
}
|
||||
|
||||
// Playing or not, update last_tick so that the next frame adds the correct duration to timer
|
||||
self.last_tick = Some(now);
|
||||
|
||||
// Did we enter a new beat?
|
||||
self.beat() != old_beat
|
||||
}
|
||||
|
||||
/// Which beat (0..loop_length) we're on
|
||||
pub fn beat(&self) -> u32 {
|
||||
self.timer.floor() as u32
|
||||
}
|
||||
|
||||
/// What fraction we are (0.0..1.0) through the loop
|
||||
/// (multiply by window width to find the x coord to draw the cursor line)
|
||||
pub fn ratio(&self) -> f32 {
|
||||
self.timer / LOOP_LENGTH as f32
|
||||
}
|
||||
|
||||
pub fn add_window(&mut self, note_type: NoteType) {
|
||||
self.window_counter += 1;
|
||||
self.grids.push(Grid::for_note_type(note_type, self.window_counter));
|
||||
}
|
||||
|
||||
pub fn notes_for_beat(&self) -> Vec<(String, u32)> {
|
||||
let mut notes = vec![];
|
||||
let beat = self.beat();
|
||||
|
||||
for grid in self.grids.iter() {
|
||||
for note in grid.notes(beat).into_iter() {
|
||||
notes.push((grid.id.clone(), note))
|
||||
}
|
||||
}
|
||||
notes
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user