diff --git a/src/builtin/lightmap/spot.png b/src/builtin/lightmap/spot.png index 593a525..640e30f 100644 Binary files a/src/builtin/lightmap/spot.png and b/src/builtin/lightmap/spot.png differ diff --git a/src/common.rs b/src/common.rs index c2963b6..28ce1d1 100644 --- a/src/common.rs +++ b/src/common.rs @@ -15,7 +15,7 @@ pub const CDEG_RAD: f64 = std::f64::consts::PI / 128.0; lazy_static! { pub static ref VERSION_BANNER: String = { let version = option_env!("DRS_BUILD_VERSION_OVERRIDE").unwrap_or(env!("CARGO_PKG_VERSION")); - format!("NXEngine-RS {}", version) + format!("doukutsu-rs {}", version) }; } diff --git a/src/engine_constants/mod.rs b/src/engine_constants/mod.rs index 78d4324..afe3ca8 100644 --- a/src/engine_constants/mod.rs +++ b/src/engine_constants/mod.rs @@ -277,7 +277,7 @@ impl EngineConstants { supports_og_textures: false, my_char: MyCharConsts { display_bounds: Rect { left: 8 * 0x200, top: 8 * 0x200, right: 8 * 0x200, bottom: 8 * 0x200 }, - hit_bounds: Rect { left: 8 * 0x200, top: 8 * 0x200, right: 8 * 0x200, bottom: 8 * 0x200 }, + hit_bounds: Rect { left: 5 * 0x200, top: 8 * 0x200, right: 5 * 0x200, bottom: 8 * 0x200 }, life: 3, max_life: 3, control_mode: ControlMode::Normal, diff --git a/src/framework/backend_sdl2.rs b/src/framework/backend_sdl2.rs index d3fae01..93f82ab 100644 --- a/src/framework/backend_sdl2.rs +++ b/src/framework/backend_sdl2.rs @@ -61,7 +61,7 @@ impl SDL2EventLoop { let event_pump = sdl.event_pump().map_err(|e| GameError::WindowError(e))?; let video = sdl.video().map_err(|e| GameError::WindowError(e))?; let window = - video.window("NXEngine-RS", 640, 480).position_centered().resizable().build().map_err(|e| GameError::WindowError(e.to_string()))?; + video.window("Cave Story (doukutsu-rs)", 640, 480).position_centered().resizable().build().map_err(|e| GameError::WindowError(e.to_string()))?; let canvas = window.into_canvas().accelerated().present_vsync().build().map_err(|e| GameError::RenderError(e.to_string()))?; @@ -365,7 +365,6 @@ impl BackendRenderer for SDL2Renderer { let (r, g, b, a) = color.to_rgba(); refs.canvas.set_draw_color(pixels::Color::RGBA(r, g, b, a)); - refs.canvas.set_blend_mode(sdl2::render::BlendMode::Blend); refs.canvas .fill_rect(sdl2::rect::Rect::new(rect.left as i32, rect.top as i32, rect.width() as u32, rect.height() as u32)) .map_err(|e| GameError::RenderError(e.to_string()))?; @@ -379,7 +378,6 @@ impl BackendRenderer for SDL2Renderer { let (r, g, b, a) = color.to_rgba(); refs.canvas.set_draw_color(pixels::Color::RGBA(r, g, b, a)); - refs.canvas.set_blend_mode(sdl2::render::BlendMode::Blend); match line_width { 0 => {} // no-op diff --git a/src/main.rs b/src/main.rs index 103d7fc..b548c45 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,7 @@ fn main() { if let Err(e) = result { let title: LPCWSTR = OsStr::new("Error!") .encode_wide().chain(Some(0)).collect::>().as_ptr(); - let message: LPCWSTR = OsStr::new(format!("Whoops, nxengine-rs crashed: {}", e).as_str()) + let message: LPCWSTR = OsStr::new(format!("Whoops, doukutsu-rs crashed: {}", e).as_str()) .encode_wide().chain(Some(0)).collect::>().as_ptr(); MessageBoxW(null_mut(), message, diff --git a/src/npc/ai/sand_zone.rs b/src/npc/ai/sand_zone.rs index cfe1fb0..2b68d21 100644 --- a/src/npc/ai/sand_zone.rs +++ b/src/npc/ai/sand_zone.rs @@ -1,7 +1,7 @@ use num_traits::{abs, clamp}; use crate::caret::CaretType; -use crate::common::{CDEG_RAD, Direction}; +use crate::common::{Direction, CDEG_RAD}; use crate::framework::error::GameResult; use crate::npc::list::NPCList; use crate::npc::NPC; @@ -667,14 +667,7 @@ impl NPC { if self.action_counter > 50 { state.sound_manager.play_sfx(25); self.vanish(state); - npc_list.create_death_smoke( - self.x, - self.y, - self.display_bounds.right as usize, - 8, - state, - &self.rng, - ); + npc_list.create_death_smoke(self.x, self.y, self.display_bounds.right as usize, 8, state, &self.rng); } } _ => {} @@ -904,68 +897,6 @@ impl NPC { Ok(()) } - pub(crate) fn tick_n122_colon_enraged( - &mut self, - state: &mut SharedGameState, - players: [&mut Player; 2], - ) -> GameResult { - match self.action_num { - 0 | 1 => { - if self.action_num == 0 { - self.action_num = 1; - self.anim_num = 0; - self.anim_counter = 0; - } - - if self.rng.range(0..120) == 10 { - self.action_num = 2; - self.action_counter = 0; - self.anim_num = 1; - } - - let player = self.get_closest_player_mut(players); - if (self.x - player.x).abs() < 0x4000 && self.y - 0x4000 < player.y && self.y + 0x2000 > player.y { - if self.x <= player.x { - Direction::Right - } else { - Direction::Left - }; - } - } - 2 => { - self.action_counter += 1; - if self.action_counter > 8 { - self.action_num = 1; - self.anim_num = 0; - } - } - 10 | 11 => { - if self.action_num == 10 { - self.action_num = 11; - self.action_counter = self.rng.range(0..50) as u16; - self.anim_num = 0; - self.life = 1000; - self.damage = 0; - } - - if self.action_counter > 0 { - self.action_counter -= 1; - } else { - self.action_num = 13; - } - } - 13 | 14 => { - if self.action_num == 13 { - self.action_num = 14; - self.action_counter = self.rng.range(0..50) as u16; - } - } - _ => {} - } - - Ok(()) - } - pub(crate) fn tick_n124_sunstone(&mut self, state: &mut SharedGameState) -> GameResult { match self.action_num { 0 | 1 => { @@ -1056,7 +987,7 @@ impl NPC { self.animate(2, 4, 5); } else { self.anim_num = 5; - self.anim_counter = 0; + self.anim_counter =0; } if self.vel_x < 0 && self.flags.hit_left_wall() { @@ -1099,6 +1030,7 @@ impl NPC { self.x += self.vel_x; self.y += self.vel_y; + let dir_offset = if self.direction == Direction::Left { 0 } else { 6 }; self.anim_rect = state.constants.npc.n126_puppy_running[self.anim_num as usize + dir_offset]; diff --git a/src/scene/game_scene.rs b/src/scene/game_scene.rs index 17aaae9..bd57f19 100644 --- a/src/scene/game_scene.rs +++ b/src/scene/game_scene.rs @@ -591,19 +591,17 @@ impl GameScene { } fn draw_light_map(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { - //let canvas = state.lightmap_canvas.as_mut(); - // if let None = canvas { - // return Ok(()); - // } + let canvas = state.lightmap_canvas.as_mut(); + if let None = canvas { + return Ok(()); + } - // let canvas = canvas.unwrap(); + let canvas = canvas.unwrap(); - //graphics::set_render_target(ctx, Some(canvas))?; - //graphics::set_blend_mode(ctx, BlendMode::Add)?; - - //graphics::clear(ctx, Color::from_rgb(100, 100, 110)); - graphics::draw_rect(ctx, Rect::new(0, 0, state.screen_size.0 as isize + 1, state.screen_size.1 as isize + 1), Color::from_rgba(0, 0, 0, 150))?; + graphics::set_render_target(ctx, Some(canvas))?; + graphics::set_blend_mode(ctx, BlendMode::Add)?; + graphics::clear(ctx, Color::from_rgb(100, 100, 110)); { let scale = state.scale; let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "builtin/lightmap/spot")?; @@ -804,15 +802,15 @@ impl GameScene { batch.draw_filtered(FilterMode::Linear, ctx)?; } - //graphics::set_blend_mode(ctx, BlendMode::Multiply)?; - //graphics::set_render_target(ctx, None)?; + graphics::set_blend_mode(ctx, BlendMode::Multiply)?; + graphics::set_render_target(ctx, None)?; - /*let rect = Rect { left: 0.0, top: 0.0, right: state.screen_size.0, bottom: state.screen_size.1 }; + let rect = Rect { left: 0.0, top: 0.0, right: state.screen_size.0, bottom: state.screen_size.1 }; canvas.clear(); canvas.add(SpriteBatchCommand::DrawRect(rect, rect)); canvas.draw()?; - graphics::set_blend_mode(ctx, BlendMode::Alpha)?;*/ + graphics::set_blend_mode(ctx, BlendMode::Alpha)?; Ok(()) } @@ -1441,7 +1439,12 @@ impl Scene for GameScene { //graphics::set_canvas(ctx, Some(&state.game_canvas)); self.draw_background(state, ctx)?; self.draw_tiles(state, ctx, TileLayer::Background)?; - if state.settings.shader_effects { + if state.settings.shader_effects + && self.stage.data.background_type != BackgroundType::Black + && self.stage.data.background_type != BackgroundType::Outside + && self.stage.data.background_type != BackgroundType::OutsideWind + && self.stage.data.background.name() != "bkBlack" + { self.draw_light_map(state, ctx)?; } @@ -1466,11 +1469,19 @@ impl Scene for GameScene { self.draw_bullets(state, ctx)?; self.player2.draw(state, ctx, &self.frame)?; self.player1.draw(state, ctx, &self.frame)?; + /*if state.settings.shader_effects && self.water_visible { + self.draw_water(state, ctx)?; + }*/ self.draw_tiles(state, ctx, TileLayer::Foreground)?; self.draw_tiles(state, ctx, TileLayer::Snack)?; self.draw_carets(state, ctx)?; - + if state.settings.shader_effects + && (self.stage.data.background_type == BackgroundType::Black + || self.stage.data.background.name() == "bkBlack") + { + self.draw_light_map(state, ctx)?; + } self.flash.draw(state, ctx, &self.frame)?; /*graphics::set_canvas(ctx, None); @@ -1575,7 +1586,7 @@ impl Scene for GameScene { ctx: &mut Context, ui: &mut imgui::Ui, ) -> GameResult { - //components.live_debugger.run_ingame(self, state, ctx, ui)?; + components.live_debugger.run_ingame(self, state, ctx, ui)?; Ok(()) } } diff --git a/src/sound/org_playback.rs b/src/sound/org_playback.rs index b7f1efe..918ce20 100644 --- a/src/sound/org_playback.rs +++ b/src/sound/org_playback.rs @@ -4,7 +4,6 @@ use crate::sound::organya::{Song as Organya, Version}; use crate::sound::stuff::*; use crate::sound::wav::*; use crate::sound::wave_bank::SoundBank; -use num_traits::Pow; pub(crate) struct OrgPlaybackEngine { song: Organya, @@ -118,9 +117,11 @@ impl OrgPlaybackEngine { .zip(self.track_buffers[128..].iter_mut()) .enumerate() { - static MAP: [usize; 12] = [0, 0, 1, 0, 4, 2, 3, 0, 5, 0, 0, 0]; - - *buf = RenderBuffer::new(samples.samples[MAP[track.inst.inst as usize]].clone()); + if self.song.version == Version::Extended { + *buf = RenderBuffer::new(samples.samples[track.inst.inst as usize].clone()); + } else { + *buf = RenderBuffer::new(samples.samples[idx].clone()); + } } self.song = song; @@ -170,14 +171,12 @@ impl OrgPlaybackEngine { let key = note.key % 12; let p_oct = k % 8; - //let freq = org_key_to_freq(key + p_oct * 12, self.song.tracks[track].inst.freq as i16); - let freq = 2.0f32.pow((note.key as f32 + self.song.tracks[track].inst.freq as f32 / 1000.0 + 155.0) / 12.0); + let freq = org_key_to_freq(key + p_oct * 12, self.song.tracks[track].inst.freq as i16); let l = p_oct as usize * 8 + track + swap; self.track_buffers[l].set_frequency(freq as u32); - self.track_buffers[l].organya_select_octave(0, false); - //self.track_buffers[l] - // .organya_select_octave(p_oct as usize, self.song.tracks[track].inst.pipi != 0); + self.track_buffers[l] + .organya_select_octave(p_oct as usize, self.song.tracks[track].inst.pipi != 0); } self.track_buffers[j].looping = true; self.track_buffers[j].playing = true; @@ -191,14 +190,11 @@ impl OrgPlaybackEngine { if self.song.tracks[track].inst.pipi == 0 { self.track_buffers[j].looping = false; } - //self.swaps[track] += 64; - //self.swaps[track] %= 128; + self.swaps[track] += 64; + self.swaps[track] %= 128; let j = octave as usize + track + self.swaps[track]; - let freq = 2.0f32.pow((note.key as f32 + self.song.tracks[track].inst.freq as f32 / 1000.0 + 155.0) / 12.0) / 3.0; - self.track_buffers[j].set_frequency(freq as u32); - self.track_buffers[j].organya_select_octave(2, false); - //self.track_buffers[j] - // .organya_select_octave(note.key as usize / 12, self.song.tracks[track].inst.pipi != 0); + self.track_buffers[j] + .organya_select_octave(note.key as usize / 12, self.song.tracks[track].inst.pipi != 0); self.track_buffers[j].looping = true; self.track_buffers[j].playing = true; } else { @@ -208,8 +204,8 @@ impl OrgPlaybackEngine { if self.song.tracks[track].inst.pipi == 0 { self.track_buffers[j].looping = false; } - //self.swaps[track] += 64; - //self.swaps[track] %= 128; + self.swaps[track] += 64; + self.swaps[track] %= 128; let octave = (note.key / 12) * 8; let j = octave as usize + track + self.swaps[track]; for k in 0..16 { @@ -217,13 +213,11 @@ impl OrgPlaybackEngine { let key = note.key % 12; let p_oct = k % 8; - //let freq = org_key_to_freq(key + p_oct * 12, self.song.tracks[track].inst.freq as i16); - let freq = 2.0f32.pow((note.key as f32 + self.song.tracks[track].inst.freq as f32 / 1000.0 + 155.0) / 12.0); + let freq = org_key_to_freq(key + p_oct * 12, self.song.tracks[track].inst.freq as i16); let l = p_oct as usize * 8 + track + swap; self.track_buffers[l].set_frequency(freq as u32); - self.track_buffers[l].organya_select_octave(0, false); - //self.track_buffers[l] - // .organya_select_octave(p_oct as usize, self.song.tracks[track].inst.pipi != 0); + self.track_buffers[l] + .organya_select_octave(p_oct as usize, self.song.tracks[track].inst.pipi != 0); } self.track_buffers[j].looping = true; self.track_buffers[j].playing = true; @@ -273,8 +267,7 @@ impl OrgPlaybackEngine { if let Some(note) = notes.iter().find(|x| x.pos == self.play_pos) { // FIXME: Add constants for dummy values if note.key != 255 { - //let freq = org_key_to_drum_freq(note.key); - let freq = note.key as f32 * (22050.0 / 32.5); + let freq = org_key_to_drum_freq(note.key); self.track_buffers[j].set_frequency(freq as u32); self.track_buffers[j].set_position(0); self.track_buffers[j].playing = true; @@ -350,15 +343,8 @@ pub fn mix(dst: &mut [u16], dst_fmt: WavFormat, srcs: &mut [RenderBuffer]) { } } - let mut last_frame: u16 = 0; - #[allow(unused_variables)] - for (idx, frame) in dst.iter_mut().enumerate() { - if idx % 2 == 1 { - *frame = last_frame; - continue; - } - + for frame in dst.iter_mut() { let pos = buf.position as usize + buf.base_pos; // -1..1 let s1 = (buf.sample.data[pos] as f32 - 128.0) / 128.0; @@ -371,10 +357,10 @@ pub fn mix(dst: &mut [u16], dst_fmt: WavFormat, srcs: &mut [RenderBuffer]) { let r1 = buf.position.fract() as f32; let r2 = (1.0 - f32::cos(r1 * PI)) / 2.0; - // let s = s1; // No interp - let s = s1 + (s2 - s1) * r1; // Linear interp + //let s = s1; // No interp + //let s = s1 + (s2 - s1) * r1; // Linear interp //let s = s1 * (1.0 - r2) + s2 * r2; // Cosine interp - //let s = cubic_interp(s1, s2, s4, s3, r1); // Cubic interp + let s = cubic_interp(s1, s2, s4, s3, r1); // Cubic interp // Ideally we want sinc/lanczos interpolation, since that's what DirectSound appears to use. // -128..128 @@ -405,8 +391,7 @@ pub fn mix(dst: &mut [u16], dst_fmt: WavFormat, srcs: &mut [RenderBuffer]) { l = xl.saturating_add(sl as i8) as u8 ^ 128; r = xr.saturating_add(sr as i8) as u8 ^ 128; - last_frame = u16::from_le_bytes([l, r]); - *frame = last_frame; + *frame = u16::from_le_bytes([l, r]); } } }