diff --git a/src/lib.rs b/src/lib.rs index 02810ff..c5e0c5d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,8 +8,7 @@ use sh0rk::{ palette, sys::*, Direction::{self, *}, - Rect, - Point, + Song, Point, Rect, }; static mut GAME: Game = Game::new(); @@ -26,6 +25,8 @@ struct Game { bonk_timer: Option, gate_count: u8, gate_pos: Point, + + song: Song<48>, } impl Game { @@ -42,6 +43,7 @@ impl Game { bonk_timer: None, gate_count: 4, gate_pos: Point { x: 40, y: 64 }, + song: Song::new(sh0rk::CHOPSTICKS), } } @@ -96,6 +98,8 @@ impl Game { fn update(&mut self) { self.frame_count += 1; + self.song.update(); + if let Some(rem) = self.bonk_timer { if rem == 0 { self.bonk_timer = None; @@ -110,6 +114,9 @@ impl Game { let just_pressed = gamepad & (gamepad ^ self.prev_gamepad); let speed = if just_pressed & BUTTON_2 != 0 { 4 } else { 2 }; + if just_pressed & BUTTON_1 != 0 { + self.song.pause(); + } if gamepad & BUTTON_UP != 0 { self.mara_dir = Up; @@ -134,8 +141,16 @@ impl Game { self.mara_walk(); - let player = Rect { base: self.mara_position.clone(), width: 16, height: 16 }; - let gate = Rect { base: self.gate_pos.clone(), width: 12, height: 4 * self.gate_count as i32 }; + let player = Rect { + base: self.mara_position.clone(), + width: 16, + height: 16, + }; + let gate = Rect { + base: self.gate_pos.clone(), + width: 12, + height: 4 * self.gate_count as i32, + }; if player.collides(&gate) { self.mara_speed = 0; match self.mara_dir { diff --git a/src/sh0rk/mod.rs b/src/sh0rk/mod.rs index d9e887a..03b7b48 100644 --- a/src/sh0rk/mod.rs +++ b/src/sh0rk/mod.rs @@ -1,5 +1,8 @@ pub mod palette; pub mod sys; +mod music; + +pub use music::*; #[derive(Clone, Copy, PartialEq, Eq, Default)] pub struct Point { diff --git a/src/sh0rk/music.rs b/src/sh0rk/music.rs new file mode 100644 index 0000000..b161cc7 --- /dev/null +++ b/src/sh0rk/music.rs @@ -0,0 +1,129 @@ +use super::sys::{tone, TONE_PULSE1, TONE_PULSE2}; + +pub struct Note { + pub freq: u32, + pub dur: u32, + pub volume: u32, + pub flags: u32, +} + +impl Note { + pub fn play(&self) { + tone(self.freq, self.dur, self.volume, self.flags); + } +} + +impl From<(u32, u32, u32, u32)> for Note { + fn from((freq, dur, volume, flags): (u32, u32, u32, u32)) -> Self { + Note {freq, dur, volume, flags} + } +} + +pub enum Quantum { + Rest(u8), + Notes([(u32, u32, u32, u32); 2]), +} +pub use Quantum::*; + +pub const CHOPSTICKS: [Quantum; 48] = [ + // G7 + Notes([(196, 14, 25, TONE_PULSE1), (175, 14, 25, TONE_PULSE2)]), + Rest(15), + Notes([(196, 14, 25, TONE_PULSE1), (175, 14, 25, TONE_PULSE2)]), + Rest(15), + Notes([(196, 14, 25, TONE_PULSE1), (175, 14, 25, TONE_PULSE2)]), + Rest(15), + // G7 + Notes([(196, 15, 25, TONE_PULSE1), (175, 15, 25, TONE_PULSE2)]), + Rest(15), + Notes([(196, 15, 25, TONE_PULSE1), (175, 15, 25, TONE_PULSE2)]), + Rest(15), + Notes([(196, 15, 25, TONE_PULSE1), (175, 15, 25, TONE_PULSE2)]), + Rest(15), + // C + Notes([(196, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]), + Rest(15), + Notes([(196, 15, 25, TONE_PULSE1), (175, 15, 25, TONE_PULSE2)]), + Rest(15), + Notes([(196, 15, 25, TONE_PULSE1), (175, 15, 25, TONE_PULSE2)]), + Rest(15), + // C + Notes([(196, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]), + Rest(15), + Notes([(246, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]), + Rest(15), + Notes([(246, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]), + Rest(15), + // G7 + Notes([(246, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]), + Rest(15), + Notes([(246, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]), + Rest(15), + Notes([(246, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]), + Rest(15), + // G7 + Notes([(246, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]), + Rest(15), + Notes([(261, 15, 25, TONE_PULSE1), (130, 15, 25, TONE_PULSE2)]), + Rest(15), + Notes([(261, 15, 25, TONE_PULSE1), (130, 15, 25, TONE_PULSE2)]), + Rest(15), + // C + Notes([(261, 15, 25, TONE_PULSE1), (130, 15, 25, TONE_PULSE2)]), + Rest(15), + Notes([(261, 15, 25, TONE_PULSE1), (130, 15, 25, TONE_PULSE2)]), + Rest(15), + Notes([(261, 15, 25, TONE_PULSE1), (130, 15, 25, TONE_PULSE2)]), + Rest(15), + // C + Notes([(261, 15, 25, TONE_PULSE1), (130, 15, 25, TONE_PULSE2)]), + Rest(15), + Notes([(246, 15, 25, TONE_PULSE1), (146, 15, 25, TONE_PULSE2)]), + Rest(15), + Notes([(220, 15, 25, TONE_PULSE1), (164, 15, 25, TONE_PULSE2)]), + Rest(15), +]; + +pub struct Song { + position: usize, + sleep_timer: u8, + song: [Quantum; N], + paused: bool, +} + +impl Song { + pub const fn new(song: [Quantum;N]) -> Self { + Self{ + position: 0, + sleep_timer: 0, + song, + paused: false, + } + } + + pub fn pause(&mut self) { + self.paused = !self.paused; + } + + pub fn update(&mut self) { + if self.paused { + return; + } + + if self.sleep_timer != 0 { + self.sleep_timer -= 1; + return; + } + + match self.song[self.position % self.song.len()] { + Rest(n) => self.sleep_timer = n, + Notes(notes) => { + for note in notes { + Note::from(note).play(); + } + }, + } + + self.position += 1; + } +}