From 753e7304a3c177b1c4ab80ba5c8eb8fae863b016 Mon Sep 17 00:00:00 2001 From: Alula <6276139+alula@users.noreply.github.com> Date: Wed, 28 Apr 2021 00:39:31 +0200 Subject: [PATCH] npc layers support --- src/npc/ai/misc.rs | 3 ++- src/npc/mod.rs | 18 +++++++++++++++++ src/npc/utils.rs | 3 ++- src/scene/game_scene.rs | 43 ++++++++++++++++++++++++----------------- 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/npc/ai/misc.rs b/src/npc/ai/misc.rs index 02d39ec..506fbe2 100644 --- a/src/npc/ai/misc.rs +++ b/src/npc/ai/misc.rs @@ -4,7 +4,7 @@ use crate::caret::CaretType; use crate::common::{Direction, Rect}; use crate::framework::error::GameResult; use crate::npc::list::NPCList; -use crate::npc::NPC; +use crate::npc::{NPC, NPCLayer}; use crate::player::Player; use crate::rng::RNG; use crate::shared_game_state::SharedGameState; @@ -495,6 +495,7 @@ impl NPC { pub(crate) fn tick_n041_busted_door(&mut self, state: &mut SharedGameState) -> GameResult { if self.action_num == 0 { self.action_num = 1; + self.layer = NPCLayer::Background; self.anim_rect = state.constants.npc.n041_busted_door; self.y -= 16 * 0x200; } diff --git a/src/npc/mod.rs b/src/npc/mod.rs index 255020f..48cc123 100644 --- a/src/npc/mod.rs +++ b/src/npc/mod.rs @@ -49,6 +49,14 @@ bitfield! { pub show_damage, set_show_damage: 15; // 0x8000 } +#[derive(Debug, Copy, Clone, Eq, PartialOrd, PartialEq)] +#[repr(u8)] +pub enum NPCLayer { + Background = 0, + Middleground = 1, + Foreground = 2, +} + /// Represents an NPC object. #[derive(Debug, Clone)] #[repr(C)] @@ -72,6 +80,7 @@ pub struct NPC { /// Previous Y position, used by frame interpolator pub prev_y: i32, pub exp: u16, + pub layer: NPCLayer, pub size: u8, pub shock: u16, pub life: u16, @@ -115,6 +124,7 @@ impl NPC { prev_x: 0, prev_y: 0, exp: 0, + layer: NPCLayer::Middleground, size: 0, shock: 0, life: 0, @@ -140,6 +150,14 @@ impl NPC { rng: Xoroshiro32PlusPlus::new(0), } } + + pub fn draw_if_layer(&self, state: &mut SharedGameState, ctx: &mut Context, frame: &Frame, layer: NPCLayer) -> GameResult { + if self.layer == layer { + self.draw(state, ctx, frame)? + } + + Ok(()) + } } impl GameEntity<([&mut Player; 2], &NPCList, &mut Stage, &BulletManager)> for NPC { diff --git a/src/npc/utils.rs b/src/npc/utils.rs index 68a6d7f..0d0236b 100644 --- a/src/npc/utils.rs +++ b/src/npc/utils.rs @@ -6,7 +6,7 @@ use crate::weapon::bullet::Bullet; use crate::caret::CaretType; use crate::common::{Condition, Direction, Flag, Rect}; use crate::map::NPCData; -use crate::npc::{NPC, NPCFlag, NPCTable}; +use crate::npc::{NPC, NPCFlag, NPCTable, NPCLayer}; use crate::npc::list::NPCList; use crate::player::Player; use crate::rng::{RNG, Xoroshiro32PlusPlus}; @@ -61,6 +61,7 @@ impl NPC { event_num: 0, shock: 0, exp, + layer: NPCLayer::Middleground, size, life, damage, diff --git a/src/scene/game_scene.rs b/src/scene/game_scene.rs index de7f07e..7f7750a 100644 --- a/src/scene/game_scene.rs +++ b/src/scene/game_scene.rs @@ -22,7 +22,7 @@ use crate::input::touch_controls::TouchControlType; use crate::inventory::{Inventory, TakeExperienceResult}; use crate::npc::boss::BossNPC; use crate::npc::list::NPCList; -use crate::npc::NPC; +use crate::npc::{NPC, NPCLayer}; use crate::physics::PhysicalEntity; use crate::player::{Player, TargetPlayer}; use crate::rng::XorShift; @@ -212,6 +212,28 @@ impl GameScene { 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 || npc.x < (self.frame.x - 128 * 0x200 - npc.display_bounds.width() as i32 * 0x200) + || npc.x + > (self.frame.x + + 128 * 0x200 + + (state.canvas_size.0 as i32 + npc.display_bounds.width() as i32) * 0x200) + && npc.y < (self.frame.y - 128 * 0x200 - npc.display_bounds.height() as i32 * 0x200) + || npc.y + > (self.frame.y + + 128 * 0x200 + + (state.canvas_size.1 as i32 + npc.display_bounds.height() as i32) * 0x200) + { + continue; + } + + npc.draw(state, ctx, &self.frame)?; + } + + Ok(()) + } + fn draw_bullets(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "Bullet")?; let mut x: i32; @@ -1552,6 +1574,7 @@ impl Scene for GameScene { //graphics::set_canvas(ctx, Some(&state.game_canvas)); self.draw_background(state, ctx)?; self.draw_tiles(state, ctx, TileLayer::Background)?; + self.draw_npc_layer(state, ctx, NPCLayer::Background)?; if state.settings.shader_effects && self.stage.data.background_type != BackgroundType::Black && self.stage.data.background_type != BackgroundType::Outside @@ -1562,23 +1585,7 @@ impl Scene for GameScene { } self.boss.draw(state, ctx, &self.frame)?; - for npc in self.npc_list.iter_alive() { - if npc.x < (self.frame.x - 128 * 0x200 - npc.display_bounds.width() as i32 * 0x200) - || npc.x - > (self.frame.x - + 128 * 0x200 - + (state.canvas_size.0 as i32 + npc.display_bounds.width() as i32) * 0x200) - && npc.y < (self.frame.y - 128 * 0x200 - npc.display_bounds.height() as i32 * 0x200) - || npc.y - > (self.frame.y - + 128 * 0x200 - + (state.canvas_size.1 as i32 + npc.display_bounds.height() as i32) * 0x200) - { - continue; - } - - npc.draw(state, ctx, &self.frame)?; - } + self.draw_npc_layer(state, ctx, NPCLayer::Middleground)?; self.draw_bullets(state, ctx)?; self.player2.draw(state, ctx, &self.frame)?; self.player1.draw(state, ctx, &self.frame)?;