add super basic music engine
Signed-off-by: Jessie Williams <quorawings@gmail.com>
This commit is contained in:
parent
f36431f491
commit
fe7570a43a
23
src/lib.rs
23
src/lib.rs
|
@ -8,8 +8,7 @@ use sh0rk::{
|
||||||
palette,
|
palette,
|
||||||
sys::*,
|
sys::*,
|
||||||
Direction::{self, *},
|
Direction::{self, *},
|
||||||
Rect,
|
Song, Point, Rect,
|
||||||
Point,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static mut GAME: Game = Game::new();
|
static mut GAME: Game = Game::new();
|
||||||
|
@ -26,6 +25,8 @@ struct Game {
|
||||||
bonk_timer: Option<u8>,
|
bonk_timer: Option<u8>,
|
||||||
gate_count: u8,
|
gate_count: u8,
|
||||||
gate_pos: Point,
|
gate_pos: Point,
|
||||||
|
|
||||||
|
song: Song<48>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Game {
|
impl Game {
|
||||||
|
@ -42,6 +43,7 @@ impl Game {
|
||||||
bonk_timer: None,
|
bonk_timer: None,
|
||||||
gate_count: 4,
|
gate_count: 4,
|
||||||
gate_pos: Point { x: 40, y: 64 },
|
gate_pos: Point { x: 40, y: 64 },
|
||||||
|
song: Song::new(sh0rk::CHOPSTICKS),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +98,8 @@ impl Game {
|
||||||
|
|
||||||
fn update(&mut self) {
|
fn update(&mut self) {
|
||||||
self.frame_count += 1;
|
self.frame_count += 1;
|
||||||
|
self.song.update();
|
||||||
|
|
||||||
if let Some(rem) = self.bonk_timer {
|
if let Some(rem) = self.bonk_timer {
|
||||||
if rem == 0 {
|
if rem == 0 {
|
||||||
self.bonk_timer = None;
|
self.bonk_timer = None;
|
||||||
|
@ -110,6 +114,9 @@ impl Game {
|
||||||
let just_pressed = gamepad & (gamepad ^ self.prev_gamepad);
|
let just_pressed = gamepad & (gamepad ^ self.prev_gamepad);
|
||||||
|
|
||||||
let speed = if just_pressed & BUTTON_2 != 0 { 4 } else { 2 };
|
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 {
|
if gamepad & BUTTON_UP != 0 {
|
||||||
self.mara_dir = Up;
|
self.mara_dir = Up;
|
||||||
|
@ -134,8 +141,16 @@ impl Game {
|
||||||
|
|
||||||
self.mara_walk();
|
self.mara_walk();
|
||||||
|
|
||||||
let player = Rect { base: self.mara_position.clone(), width: 16, height: 16 };
|
let player = Rect {
|
||||||
let gate = Rect { base: self.gate_pos.clone(), width: 12, height: 4 * self.gate_count as i32 };
|
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) {
|
if player.collides(&gate) {
|
||||||
self.mara_speed = 0;
|
self.mara_speed = 0;
|
||||||
match self.mara_dir {
|
match self.mara_dir {
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
pub mod palette;
|
pub mod palette;
|
||||||
pub mod sys;
|
pub mod sys;
|
||||||
|
mod music;
|
||||||
|
|
||||||
|
pub use music::*;
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Default)]
|
#[derive(Clone, Copy, PartialEq, Eq, Default)]
|
||||||
pub struct Point {
|
pub struct Point {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue