#[cfg(feature = "buddy-alloc")] mod alloc; mod sh0rk; mod sprites; use fastrand::Rng; use sh0rk::{ palette, sys::*, Direction::{self, *}, Song, Point, Rect, }; static mut GAME: Game = Game::new(); struct Game { frame_count: u32, prev_gamepad: u8, rng: Option, mai_position: Point, mara_position: Point, mara_frame: u32, mara_dir: Direction, mara_speed: i32, bonk_timer: Option, gate_count: u8, gate_pos: Point, song: Song<48>, } impl Game { const fn new() -> Self { Self { frame_count: 0, prev_gamepad: 0, rng: None, mai_position: Point { x: 76, y: 32 }, mara_position: Point { x: 32, y: 90 }, mara_frame: 0, mara_dir: Right, mara_speed: 0, bonk_timer: None, gate_count: 4, gate_pos: Point { x: 40, y: 64 }, song: Song::new(sh0rk::CHOPSTICKS), } } fn bonk(&mut self) { if self.bonk_timer.is_some() { return; } tone(220 | (40 << 16), 6 | (6 << 8), 50, TONE_TRIANGLE); self.bonk_timer = Some(12); } fn mara_walk(&mut self) { if self.mara_speed == 0 { return; } if self.frame_count % 15 == 0 { self.mara_frame = if self.mara_frame == 1 { 0 } else { 1 }; } if self.frame_count % 4 == 0 { if self.mara_dir == Right && self.mara_position.x >= 144 { self.mara_speed = 0; self.mara_position.x = 144; self.bonk(); } if self.mara_dir == Down && self.mara_position.y >= 120 { self.mara_speed = 0; self.mara_position.y = 120; self.bonk(); } if self.mara_dir == Left && self.mara_position.x <= 0 { self.mara_speed = 0; self.mara_position.x = 0; self.bonk(); } if self.mara_dir == Up && self.mara_position.y <= 64 { self.mara_speed = 0; self.mara_position.y = 64; self.bonk(); } match self.mara_dir { Left => self.mara_position.x -= self.mara_speed, Right => self.mara_position.x += self.mara_speed, Up => self.mara_position.y -= self.mara_speed, Down => self.mara_position.y += self.mara_speed, }; } } 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; } else { self.bonk_timer = Some(rem - 1); } } self.mara_speed = 0; let gamepad = unsafe { *GAMEPAD1 }; 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; self.mara_speed = speed; } if gamepad & BUTTON_DOWN != 0 { self.mara_dir = Down; self.mara_speed = speed; } if gamepad & BUTTON_LEFT != 0 { self.mara_dir = Left; self.mara_speed = speed; } if gamepad & BUTTON_RIGHT != 0 { self.mara_dir = Right; self.mara_speed = speed; } self.prev_gamepad = gamepad; 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, }; if player.collides(&gate) { self.mara_speed = 0; match self.mara_dir { Right => self.mara_position = self.mara_position.add((-2, 0)), Left => self.mara_position = self.mara_position.add((2, 0)), Up => self.mara_position = self.mara_position.add((0, 2)), Down => self.mara_position = self.mara_position.add((0, -2)), }; self.bonk(); } // draw for i in 0..self.gate_count { let mut gate = self.gate_pos.clone(); gate.y = gate.y + (sprites::GATE.height * i as u32) as i32; sprites::GATE.draw(gate, 0); } palette::set_draw_color(4); line( self.gate_pos.x + 1, self.gate_pos.y - 1, self.gate_pos.x + 10, self.gate_pos.y - 1, ); palette::set_draw_color(2); text("Mara: Sh0rk of\nJustice 2", 10, 10); palette::set_draw_color(4); text("From Within, 2022", 10, 144); sprites::MAI.draw(self.mai_position, 0); sprites::MARA.draw(self.mara_dir, self.mara_frame, self.mara_position, 0); } } #[no_mangle] unsafe fn start() { palette::en4(); GAME.rng = Some(Rng::with_seed(420)); } #[no_mangle] unsafe fn update() { GAME.update(); }