add super basic music engine

Signed-off-by: Jessie Williams <quorawings@gmail.com>
This commit is contained in:
Jessie Williams 2022-03-07 07:37:13 -05:00
parent f36431f491
commit fe7570a43a
3 changed files with 151 additions and 4 deletions

View File

@ -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<u8>,
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 {

View File

@ -1,5 +1,8 @@
pub mod palette;
pub mod sys;
mod music;
pub use music::*;
#[derive(Clone, Copy, PartialEq, Eq, Default)]
pub struct Point {

129
src/sh0rk/music.rs Normal file
View File

@ -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<const N: usize> {
position: usize,
sleep_timer: u8,
song: [Quantum; N],
paused: bool,
}
impl<const N: usize> Song<N> {
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;
}
}