From b7680019ee210934a2978ca92ad862a85331eb8f Mon Sep 17 00:00:00 2001 From: Alula <6276139+alula@users.noreply.github.com> Date: Wed, 5 Jan 2022 06:40:50 +0100 Subject: [PATCH] refactor: split background and fix outside scaling --- src/components/background.rs | 139 +++++++++++++++++++++++++++++++++++ src/components/mod.rs | 1 + src/scene/game_scene.rs | 101 ++----------------------- 3 files changed, 146 insertions(+), 95 deletions(-) create mode 100644 src/components/background.rs diff --git a/src/components/background.rs b/src/components/background.rs new file mode 100644 index 0000000..f6316c7 --- /dev/null +++ b/src/components/background.rs @@ -0,0 +1,139 @@ +use crate::{Context, GameResult, graphics, SharedGameState}; +use crate::common::{Color, Rect}; +use crate::frame::Frame; +use crate::stage::{BackgroundType, Stage, StageTexturePaths}; + +pub struct Background { + pub tick: usize, + pub prev_tick: usize, +} + +impl Background { + pub fn new() -> Self { + Background { + tick: 0, + prev_tick: 0, + } + } + + pub fn tick(&mut self) -> GameResult<()> { + self.tick = self.tick.wrapping_add(1); + + Ok(()) + } + + pub fn draw_tick(&mut self) -> GameResult<()> { + self.prev_tick = self.tick; + + Ok(()) + } + + pub fn draw( + &self, + state: &mut SharedGameState, + ctx: &mut Context, + frame: &Frame, + textures: &StageTexturePaths, + stage: &Stage, + ) -> GameResult { + let batch = state.texture_set.get_or_load_batch( + ctx, + &state.constants, + &textures.background, + )?; + let scale = state.scale; + let (frame_x, frame_y) = frame.xy_interpolated(state.frame_time); + + match stage.data.background_type { + BackgroundType::TiledStatic => { + graphics::clear(ctx, stage.data.background_color); + + let count_x = state.canvas_size.0 as usize / batch.width() + 1; + let count_y = state.canvas_size.1 as usize / batch.height() + 1; + + for y in 0..count_y { + for x in 0..count_x { + batch.add((x * batch.width()) as f32, (y * batch.height()) as f32); + } + } + } + BackgroundType::TiledParallax | BackgroundType::Tiled | BackgroundType::Waterway => { + graphics::clear(ctx, stage.data.background_color); + + let (off_x, off_y) = if stage.data.background_type == BackgroundType::Tiled { + (frame_x % (batch.width() as f32), frame_y % (batch.height() as f32)) + } else { + ( + ((frame_x / 2.0 * scale).floor() / scale) % (batch.width() as f32), + ((frame_y / 2.0 * scale).floor() / scale) % (batch.height() as f32), + ) + }; + + let count_x = state.canvas_size.0 as usize / batch.width() + 2; + let count_y = state.canvas_size.1 as usize / batch.height() + 2; + + for y in 0..count_y { + for x in 0..count_x { + batch.add((x * batch.width()) as f32 - off_x, (y * batch.height()) as f32 - off_y); + } + } + } + BackgroundType::Water => { + graphics::clear(ctx, stage.data.background_color); + } + BackgroundType::Black => { + graphics::clear(ctx, stage.data.background_color); + } + BackgroundType::Scrolling => { + graphics::clear(ctx, stage.data.background_color); + } + BackgroundType::OutsideWind | BackgroundType::Outside | BackgroundType::OutsideUnknown => { + graphics::clear(ctx, Color::from_rgb(0, 0, 0)); + + let offset_x = (self.tick % 640) as i32; + let offset_y = ((state.canvas_size.1 - 240.0) / 2.0).floor(); + + for x in (0..(state.canvas_size.0 as i32)).step_by(100) { + batch.add_rect(x as f32, offset_y, &Rect::new_size(128, 0, 100, 88)); + } + + // top / bottom edges + if offset_y > 0.0 { + let scale = offset_y; + + for x in (0..(state.canvas_size.0 as i32)).step_by(100) { + batch.add_rect_scaled(x as f32,0.0, 1.0, scale, &Rect::new_size(128, 0, 100, 1)); + } + + batch.add_rect_scaled((state.canvas_size.0 - 320.0) / 2.0, 0.0, 1.0, scale, &Rect::new_size(0, 0, 320, 1)); + + for x in ((-offset_x * 4)..(state.canvas_size.0 as i32)).step_by(320) { + batch.add_rect_scaled(x as f32, offset_y + 240.0, 1.0, scale + 4.0, &Rect::new_size(0, 239, 320, 1)); + } + } + + batch.add_rect((state.canvas_size.0 - 320.0) / 2.0, offset_y, &Rect::new_size(0, 0, 320, 88)); + + for x in ((-offset_x / 2)..(state.canvas_size.0 as i32)).step_by(320) { + batch.add_rect(x as f32, offset_y + 88.0, &Rect::new_size(0, 88, 320, 35)); + } + + for x in ((-offset_x % 320)..(state.canvas_size.0 as i32)).step_by(320) { + batch.add_rect(x as f32, offset_y + 123.0, &Rect::new_size(0, 123, 320, 23)); + } + + for x in ((-offset_x * 2)..(state.canvas_size.0 as i32)).step_by(320) { + batch.add_rect(x as f32, offset_y + 146.0, &Rect::new_size(0, 146, 320, 30)); + } + + for x in ((-offset_x * 4)..(state.canvas_size.0 as i32)).step_by(320) { + batch.add_rect(x as f32, offset_y + 176.0, &Rect::new_size(0, 176, 320, 64)); + } + } + } + + batch.draw(ctx)?; + + Ok(()) + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index c625dc4..72a97ed 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -1,3 +1,4 @@ +pub mod background; pub mod boss_life_bar; pub mod credits; pub mod draw_common; diff --git a/src/scene/game_scene.rs b/src/scene/game_scene.rs index 798aaa5..7c891f6 100644 --- a/src/scene/game_scene.rs +++ b/src/scene/game_scene.rs @@ -6,6 +6,7 @@ use log::info; use crate::caret::CaretType; use crate::common::{interpolate_fix9_scale, Color, Direction, FadeDirection, FadeState, Rect}; +use crate::components::background::Background; use crate::components::boss_life_bar::BossLifeBar; use crate::components::credits::Credits; use crate::components::draw_common::Alignment; @@ -57,6 +58,7 @@ pub struct GameScene { pub inventory_ui: InventoryUI, pub hud_player1: HUD, pub hud_player2: HUD, + pub background: Background, pub tilemap: Tilemap, pub text_boxes: TextBoxes, pub frame: Frame, @@ -141,6 +143,7 @@ impl GameScene { inventory_ui: InventoryUI::new(), hud_player1: HUD::new(Alignment::Left), hud_player2: HUD::new(Alignment::Right), + background: Background::new(), tilemap: Tilemap::new(), text_boxes: TextBoxes::new(), frame: Frame { @@ -183,92 +186,6 @@ impl GameScene { self.player2.cond.set_alive(false); } - fn draw_background(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { - let batch = state.texture_set.get_or_load_batch( - ctx, - &state.constants, - &self.stage_textures.deref().borrow().background, - )?; - let scale = state.scale; - let (frame_x, frame_y) = self.frame.xy_interpolated(state.frame_time); - - match self.stage.data.background_type { - BackgroundType::TiledStatic => { - graphics::clear(ctx, self.stage.data.background_color); - - let count_x = state.canvas_size.0 as usize / batch.width() + 1; - let count_y = state.canvas_size.1 as usize / batch.height() + 1; - - for y in 0..count_y { - for x in 0..count_x { - batch.add((x * batch.width()) as f32, (y * batch.height()) as f32); - } - } - } - BackgroundType::TiledParallax | BackgroundType::Tiled | BackgroundType::Waterway => { - graphics::clear(ctx, self.stage.data.background_color); - - let (off_x, off_y) = if self.stage.data.background_type == BackgroundType::Tiled { - (frame_x % (batch.width() as f32), frame_y % (batch.height() as f32)) - } else { - ( - ((frame_x / 2.0 * scale).floor() / scale) % (batch.width() as f32), - ((frame_y / 2.0 * scale).floor() / scale) % (batch.height() as f32), - ) - }; - - let count_x = state.canvas_size.0 as usize / batch.width() + 2; - let count_y = state.canvas_size.1 as usize / batch.height() + 2; - - for y in 0..count_y { - for x in 0..count_x { - batch.add((x * batch.width()) as f32 - off_x, (y * batch.height()) as f32 - off_y); - } - } - } - BackgroundType::Water => { - graphics::clear(ctx, self.stage.data.background_color); - } - BackgroundType::Black => { - graphics::clear(ctx, self.stage.data.background_color); - } - BackgroundType::Scrolling => { - graphics::clear(ctx, self.stage.data.background_color); - } - BackgroundType::OutsideWind | BackgroundType::Outside | BackgroundType::OutsideUnknown => { - graphics::clear(ctx, Color::from_rgb(0, 0, 0)); - - let offset = (self.tick % 640) as i32; - - for x in (0..(state.canvas_size.0 as i32)).step_by(200) { - batch.add_rect(x as f32, 0.0, &Rect::new_size(0, 0, 200, 88)); - } - - batch.add_rect(state.canvas_size.0 - 320.0, 0.0, &Rect::new_size(0, 0, 320, 88)); - - for x in ((-offset / 2)..(state.canvas_size.0 as i32)).step_by(320) { - batch.add_rect(x as f32, 88.0, &Rect::new_size(0, 88, 320, 35)); - } - - for x in ((-offset % 320)..(state.canvas_size.0 as i32)).step_by(320) { - batch.add_rect(x as f32, 123.0, &Rect::new_size(0, 123, 320, 23)); - } - - for x in ((-offset * 2)..(state.canvas_size.0 as i32)).step_by(320) { - batch.add_rect(x as f32, 146.0, &Rect::new_size(0, 146, 320, 30)); - } - - for x in ((-offset * 4)..(state.canvas_size.0 as i32)).step_by(320) { - batch.add_rect(x as f32, 176.0, &Rect::new_size(0, 176, 320, 64)); - } - } - } - - batch.draw(ctx)?; - - Ok(()) - } - fn draw_npc_layer(&self, state: &mut SharedGameState, ctx: &mut Context, layer: NPCLayer) -> GameResult { for npc in self.npc_list.iter_alive() { if npc.layer != layer @@ -1294,6 +1211,7 @@ impl GameScene { } fn tick_world(&mut self, state: &mut SharedGameState) -> GameResult { + self.background.tick()?; self.hud_player1.visible = self.player1.cond.alive(); self.hud_player2.visible = self.player2.cond.alive(); self.hud_player1.has_player2 = self.player2.cond.alive() && !self.player2.cond.hidden(); @@ -1596,14 +1514,6 @@ impl Scene for GameScene { state.npc_table.stage_textures = self.stage_textures.clone(); - /*if state.constants.is_cs_plus { - match state.season { - Season::Halloween => self.player1.appearance = PlayerAppearance::HalloweenQuote, - Season::Christmas => self.player1.appearance = PlayerAppearance::ReindeerQuote, - _ => {} - } - }*/ - self.boss.boss_type = self.stage.data.boss_no as u16; self.player1.target_x = self.player1.x; self.player1.target_y = self.player1.y; @@ -1803,6 +1713,7 @@ impl Scene for GameScene { }; self.inventory_dim = self.inventory_dim.clamp(0.0, 1.0); + self.background.draw_tick()?; self.credits.draw_tick(state); Ok(()) @@ -1810,8 +1721,8 @@ impl Scene for GameScene { fn draw(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { //graphics::set_canvas(ctx, Some(&state.game_canvas)); - self.draw_background(state, ctx)?; let stage_textures_ref = &*self.stage_textures.deref().borrow(); + self.background.draw(state, ctx, &self.frame, stage_textures_ref, &self.stage)?; self.tilemap.draw(state, ctx, &self.frame, TileLayer::Background, stage_textures_ref, &self.stage)?; self.draw_npc_layer(state, ctx, NPCLayer::Background)?; self.tilemap.draw(state, ctx, &self.frame, TileLayer::Middleground, stage_textures_ref, &self.stage)?;