diff --git a/src/bullet.rs b/src/bullet.rs index 960d411..0b047f3 100644 --- a/src/bullet.rs +++ b/src/bullet.rs @@ -12,6 +12,7 @@ pub struct BulletManager { } impl BulletManager { + #[allow(clippy::new_without_default)] pub fn new() -> BulletManager { BulletManager { bullets: Vec::with_capacity(32), @@ -22,9 +23,9 @@ impl BulletManager { self.bullets.push(Bullet::new(x, y, btype, direction, constants)); } - pub fn tick_bullets(&mut self, state: &mut SharedGameState, stage: &mut Stage) { + pub fn tick_bullets(&mut self, state: &mut SharedGameState, player: &dyn PhysicalEntity, stage: &mut Stage) { for bullet in self.bullets.iter_mut() { - bullet.tick(state); + bullet.tick(state, player); bullet.hit_flags.0 = 0; bullet.tick_map_collisions(state, stage); } @@ -206,7 +207,101 @@ impl Bullet { } } - pub fn tick(&mut self, state: &mut SharedGameState) { + fn tick_fireball(&mut self, state: &mut SharedGameState, player: &dyn PhysicalEntity) { + self.action_counter += 1; + if self.action_counter > self.lifetime { + self.cond.set_alive(false); + state.create_caret(self.x, self.y, CaretType::Shoot, Direction::Left); + return; + } + + if (self.flags.hit_left_wall() && self.flags.hit_right_wall()) + || (self.flags.hit_top_wall() && self.flags.hit_bottom_wall()) { + self.cond.set_alive(false); + state.create_caret(self.x, self.y, CaretType::ProjectileDissipation, Direction::Left); + // todo play sound 28 + return; + } + + // bounce off walls + match self.direction { + Direction::Left if self.flags.hit_left_wall() => { + self.direction = Direction::Right; + } + Direction::Right if self.flags.hit_right_wall() => { + self.direction = Direction::Left; + } + _ => {} + } + + if self.action_num == 0 { + self.action_num = 1; + + match self.direction { + Direction::Left => { + self.vel_x = -0x400; + } + Direction::Right => { + self.vel_x = 0x400; + } + Direction::Up => { + self.vel_x = player.vel_x(); + + self.direction = if self.vel_x < 0 { + Direction::Left + } else { + Direction::Right + }; + + self.vel_x += if player.direction() == Direction::Left { + -0x80 + } else { + 0x80 + }; + + self.vel_y = -0x5ff; + } + Direction::Bottom => { + self.vel_x = player.vel_x(); + + self.direction = if self.vel_x < 0 { + Direction::Left + } else { + Direction::Right + }; + + self.vel_y = 0x5ff; + } + } + } else { + if self.flags.hit_bottom_wall() { + self.vel_y = -0x400; + } else if self.flags.hit_left_wall() { + self.vel_x = 0x400; + } else if self.flags.hit_right_wall() { + self.vel_x = -0x400; + } + + self.vel_y += 0x55; + if self.vel_y > 0x3ff { + self.vel_y = 0x3ff; + } + + self.x += self.vel_x; + self.y += self.vel_y; + + if self.flags.hit_left_wall() || self.flags.hit_right_wall() || self.flags.hit_bottom_wall() { + // todo play sound 34 + } + } + + self.anim_num += 1; + + if self.btype == 7 { // level 1 + } + } + + pub fn tick(&mut self, state: &mut SharedGameState, player: &PhysicalEntity) { if self.lifetime == 0 { self.cond.set_alive(false); return; @@ -216,6 +311,9 @@ impl Bullet { 4 | 5 | 6 => { self.tick_polar_star(state); } + 7 | 8 | 9 => { + self.tick_fireball(state, player); + } _ => { self.cond.set_alive(false); } } } @@ -320,61 +418,78 @@ impl Bullet { } } else if self.hit_flags.hit_left_wall() || self.hit_flags.hit_top_wall() || self.hit_flags.hit_right_wall() || self.hit_flags.hit_bottom_wall() { - self.vanish(state); } } } impl PhysicalEntity for Bullet { + #[inline(always)] fn x(&self) -> isize { self.x } + #[inline(always)] fn y(&self) -> isize { self.y } + #[inline(always)] fn vel_x(&self) -> isize { self.vel_x } + #[inline(always)] fn vel_y(&self) -> isize { self.vel_y } + #[inline(always)] fn size(&self) -> u8 { 1 } + #[inline(always)] fn hit_bounds(&self) -> &Rect { &self.hit_bounds } + #[inline(always)] fn set_x(&mut self, x: isize) { self.x = x; } + #[inline(always)] fn set_y(&mut self, y: isize) { self.y = y; } + #[inline(always)] fn set_vel_x(&mut self, vel_x: isize) { self.vel_x = vel_x; } + #[inline(always)] fn set_vel_y(&mut self, vel_y: isize) { self.vel_y = vel_y; } + #[inline(always)] fn cond(&mut self) -> &mut Condition { &mut self.cond } + #[inline(always)] fn flags(&mut self) -> &mut Flag { &mut self.hit_flags } + #[inline(always)] + fn direction(&self) -> Direction { + self.direction + } + + #[inline(always)] fn is_player(&self) -> bool { false } @@ -389,7 +504,6 @@ impl PhysicalEntity for Bullet { } } - fn tick_map_collisions(&mut self, state: &mut SharedGameState, stage: &mut Stage) { let x = clamp(self.x() / 16 / 0x200, 0, stage.map.width as isize); let y = clamp(self.y() / 16 / 0x200, 0, stage.map.height as isize); diff --git a/src/engine_constants.rs b/src/engine_constants.rs index 70b7147..2d27a11 100644 --- a/src/engine_constants.rs +++ b/src/engine_constants.rs @@ -3,7 +3,7 @@ use log::info; use case_insensitive_hashmap::CaseInsensitiveHashMap; use crate::case_insensitive_hashmap; -use crate::common::{Rect, Flag}; +use crate::common::{Flag, Rect}; use crate::player::ControlMode; use crate::str; use crate::text_script::TextScriptEncoding; @@ -107,6 +107,12 @@ pub struct BulletRects { pub b004_polar_star_l1: [Rect; 2], pub b005_polar_star_l2: [Rect; 2], pub b006_polar_star_l3: [Rect; 2], + pub b037_spur_l1: [Rect; 2], + pub b038_spur_l2: [Rect; 2], + pub b039_spur_l3: [Rect; 2], + pub b040_spur_trail_l1: [Rect; 6], + pub b041_spur_trail_l2: [Rect; 6], + pub b042_spur_trail_l3: [Rect; 6], } #[derive(Debug)] @@ -131,6 +137,7 @@ pub struct WorldConsts { #[derive(Debug, Copy, Clone)] pub struct NPCConsts { + pub n001_experience: [Rect; 6], pub n002_behemoth: [Rect; 14], pub n004_smoke: [Rect; 16], pub n005_green_critter: [Rect; 6], @@ -401,6 +408,14 @@ impl EngineConstants { snack_rect: Rect { left: 256, top: 48, right: 272, bottom: 64 }, }, npc: NPCConsts { + n001_experience: [ + Rect { left: 0, top: 16, right: 16, bottom: 32 }, + Rect { left: 16, top: 16, right: 32, bottom: 32 }, + Rect { left: 32, top: 16, right: 48, bottom: 32 }, + Rect { left: 48, top: 16, right: 64, bottom: 32 }, + Rect { left: 64, top: 16, right: 80, bottom: 32 }, + Rect { left: 80, top: 16, right: 96, bottom: 32 }, + ], n002_behemoth: [ Rect { left: 32, top: 0, right: 64, bottom: 24 }, // left Rect { left: 0, top: 0, right: 32, bottom: 24 }, @@ -872,16 +887,52 @@ impl EngineConstants { ], bullet_rects: BulletRects { b004_polar_star_l1: [ - Rect { left: 128, top: 32, right: 144, bottom: 48 }, - Rect { left: 144, top: 32, right: 160, bottom: 48 }, + Rect { left: 128, top: 32, right: 144, bottom: 48 }, // horizontal + Rect { left: 144, top: 32, right: 160, bottom: 48 }, // vertical ], b005_polar_star_l2: [ - Rect { left: 160, top: 32, right: 176, bottom: 48 }, - Rect { left: 176, top: 32, right: 192, bottom: 48 }, + Rect { left: 160, top: 32, right: 176, bottom: 48 }, // horizontal + Rect { left: 176, top: 32, right: 192, bottom: 48 }, // vertical ], b006_polar_star_l3: [ - Rect { left: 128, top: 48, right: 144, bottom: 64 }, - Rect { left: 144, top: 48, right: 160, bottom: 64 }, + Rect { left: 128, top: 48, right: 144, bottom: 64 }, // horizontal + Rect { left: 144, top: 48, right: 160, bottom: 64 }, // vertical + ], + b037_spur_l1: [ + Rect { left: 128, top: 32, right: 144, bottom: 48 }, // horizontal + Rect { left: 144, top: 32, right: 160, bottom: 48 }, // vertical + ], + b038_spur_l2: [ + Rect { left: 160, top: 32, right: 176, bottom: 48 }, // horizontal + Rect { left: 176, top: 32, right: 192, bottom: 48 }, // vertical + ], + b039_spur_l3: [ + Rect { left: 128, top: 48, right: 144, bottom: 64 }, // horizontal + Rect { left: 144, top: 48, right: 160, bottom: 64 }, // vertical + ], + b040_spur_trail_l1: [ + Rect { left: 192, top: 32, right: 200, bottom: 40 }, // horizontal + Rect { left: 200, top: 32, right: 208, bottom: 40 }, + Rect { left: 208, top: 32, right: 216, bottom: 40 }, + Rect { left: 192, top: 40, right: 200, bottom: 48 }, // vertical + Rect { left: 200, top: 40, right: 208, bottom: 48 }, + Rect { left: 208, top: 40, right: 216, bottom: 48 }, + ], + b041_spur_trail_l2: [ + Rect { left: 216, top: 32, right: 224, bottom: 40 }, // horizontal + Rect { left: 224, top: 32, right: 232, bottom: 40 }, + Rect { left: 232, top: 32, right: 240, bottom: 40 }, + Rect { left: 216, top: 40, right: 224, bottom: 48 }, // vertical + Rect { left: 224, top: 40, right: 232, bottom: 48 }, + Rect { left: 232, top: 40, right: 240, bottom: 48 }, + ], + b042_spur_trail_l3: [ + Rect { left: 240, top: 32, right: 248, bottom: 40 }, // horizontal + Rect { left: 248, top: 32, right: 256, bottom: 40 }, + Rect { left: 256, top: 32, right: 264, bottom: 40 }, + Rect { left: 240, top: 32, right: 248, bottom: 40 }, // vertical + Rect { left: 248, top: 32, right: 256, bottom: 40 }, + Rect { left: 256, top: 32, right: 264, bottom: 40 }, ], }, },