diff --git a/src/bmfont_renderer.rs b/src/bmfont_renderer.rs index 4e685f7..066c7e2 100644 --- a/src/bmfont_renderer.rs +++ b/src/bmfont_renderer.rs @@ -49,6 +49,18 @@ impl BMFontRenderer { }) } + pub fn text_width>(&self, iter: I, constants: &EngineConstants) -> f32 { + let mut offset_x = 0.0; + + for chr in iter { + if let Some(glyph) = self.font.chars.get(&chr) { + offset_x += ((glyph.width as f32 + glyph.xoffset as f32) * constants.font_scale).floor() + if chr != ' ' { 1.0 } else { constants.font_space_offset }; + } + } + + offset_x + } + pub fn draw_text>(&self, iter: I, x: f32, y: f32, constants: &EngineConstants, texture_set: &mut TextureSet, ctx: &mut Context) -> GameResult { if self.pages.len() == 1 { let batch = texture_set.get_or_load_batch(ctx, constants, self.pages.get(0).unwrap())?; diff --git a/src/frame.rs b/src/frame.rs index 86c3e17..3669dfb 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -14,12 +14,30 @@ impl Frame { self.x = -(((state.canvas_size.0 as isize - ((stage.map.width - 1) * 16) as isize) * 0x200) / 2); } else { self.x = player.target_x - (state.canvas_size.0 as isize * 0x200 / 2); + + if self.x < 0 { + self.x = 0; + } + + let max_x = (((stage.map.width as isize - 1) * 16) - state.canvas_size.0 as isize) * 0x200; + if self.x > max_x { + self.x = max_x; + } } if (stage.map.height - 1) * 16 < state.canvas_size.1 as usize { self.y = -(((state.canvas_size.1 as isize - ((stage.map.height - 1) * 16) as isize) * 0x200) / 2); } else { self.y = player.target_y - (state.canvas_size.1 as isize * 0x200 / 2); + + if self.y < 0 { + self.y = 0; + } + + let max_y = (((stage.map.height as isize - 1) * 16) - state.canvas_size.1 as isize) * 0x200; + if self.y > max_y { + self.y = max_y; + } } } diff --git a/src/scene/game_scene.rs b/src/scene/game_scene.rs index 6ffabe9..49ddf8e 100644 --- a/src/scene/game_scene.rs +++ b/src/scene/game_scene.rs @@ -24,8 +24,9 @@ pub struct GameScene { pub npc_map: NPCMap, tex_background_name: String, tex_tileset_name: String, - life_bar: usize, - life_bar_count: usize, + life_bar: u16, + life_bar_counter: u16, + map_name_counter: u16, } #[derive(Debug, EnumIter, PartialEq, Eq, Hash, Copy, Clone)] @@ -65,10 +66,15 @@ impl GameScene { tex_background_name, tex_tileset_name, life_bar: 3, - life_bar_count: 0, + life_bar_counter: 0, + map_name_counter: 0, }) } + pub fn display_map_name(&mut self, ticks: u16) { + self.map_name_counter = ticks; + } + fn draw_number(&self, x: f32, y: f32, val: usize, align: Alignment, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "TextBox")?; let n = val.to_string(); @@ -409,7 +415,7 @@ impl Scene for GameScene { let npcs = self.stage.load_npcs(&state.base_path, ctx)?; for npc_data in npcs.iter() { - let mut npc = self.npc_map.create_npc_from_data(&state.npc_table, npc_data); + let npc = self.npc_map.create_npc_from_data(&state.npc_table, npc_data); if npc.npc_flags.appear_when_flag_set() { if let Some(true) = state.game_flags.get(npc_data.flag_id as usize) { npc.cond.set_alive(true); @@ -426,6 +432,8 @@ impl Scene for GameScene { state.npc_table.tex_npc1_name = ["Npc/", &self.stage.data.npc1.filename()].join(""); state.npc_table.tex_npc2_name = ["Npc/", &self.stage.data.npc2.filename()].join(""); + self.player.target_x = self.player.x; + self.player.target_y = self.player.y; self.frame.immediate_update(state, &self.player, &self.stage); //self.player.equip.set_booster_2_0(true); Ok(()) @@ -471,20 +479,24 @@ impl Scene for GameScene { if state.control_flags.control_enabled() { // update health bar - if self.life_bar < self.player.life as usize { - self.life_bar = self.player.life as usize; + if self.life_bar < self.player.life as u16 { + self.life_bar = self.player.life as u16; } - if self.life_bar > self.player.life as usize { - self.life_bar_count += 1; - if self.life_bar_count > 30 { + if self.life_bar > self.player.life as u16 { + self.life_bar_counter += 1; + if self.life_bar_counter > 30 { self.life_bar -= 1; } } else { - self.life_bar_count = 0; + self.life_bar_counter = 0; } } + if self.map_name_counter > 0 { + self.map_name_counter -= 1; + } + TextScriptVM::run(state, self, ctx)?; self.tick = self.tick.wrapping_add(1); Ok(()) @@ -506,6 +518,13 @@ impl Scene for GameScene { self.draw_hud(state, ctx)?; } + if self.map_name_counter > 0 { + let width = state.font.text_width(self.stage.data.name.chars(), &state.constants); + state.font.draw_text(self.stage.data.name.chars(), + ((state.canvas_size.0 - width) / 2.0).floor(), 80.0, + &state.constants, &mut state.texture_set, ctx)?; + } + self.draw_fade(state, ctx)?; self.draw_text_boxes(state, ctx)?; diff --git a/src/text_script.rs b/src/text_script.rs index d0f7678..1ac288d 100644 --- a/src/text_script.rs +++ b/src/text_script.rs @@ -643,6 +643,11 @@ impl TextScriptVM { exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32); } + OpCode::MNA => { + game_scene.display_map_name(160); + + exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32); + } OpCode::CMU => { let song_id = read_cur_varint(&mut cursor)? as usize; state.sound_manager.play_song(song_id, &state.constants, ctx)?; @@ -663,7 +668,7 @@ impl TextScriptVM { // Zero operands OpCode::AEp | OpCode::CAT | OpCode::CIL | OpCode::CPS | OpCode::CRE | OpCode::CSS | OpCode::ESC | OpCode::FLA | - OpCode::INI | OpCode::LDP | OpCode::MLP | OpCode::MNA | + OpCode::INI | OpCode::LDP | OpCode::MLP | OpCode::SAT | OpCode::SLP | OpCode::SPS | OpCode::STC | OpCode::SVP | OpCode::TUR | OpCode::WAS | OpCode::ZAM => { log::warn!("unimplemented opcode: {:?}", op); diff --git a/src/texture_set.rs b/src/texture_set.rs index 9bd357d..768f63e 100644 --- a/src/texture_set.rs +++ b/src/texture_set.rs @@ -185,8 +185,4 @@ impl TextureSet { Ok(self.tex_map.get_mut(name).unwrap()) } - - pub fn draw_text(&mut self, ctx: &mut Context, text: &str) -> GameResult { - Ok(()) - } }