From 3dd21e4356e0e781f4a9f089114b01cd3a50afdc Mon Sep 17 00:00:00 2001 From: Alula Date: Fri, 2 Oct 2020 21:27:42 +0200 Subject: [PATCH] improve npc physics --- src/player_hit.rs | 83 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/src/player_hit.rs b/src/player_hit.rs index 1bdee26..a61ab52 100644 --- a/src/player_hit.rs +++ b/src/player_hit.rs @@ -1,11 +1,13 @@ use std::borrow::Borrow; +use num_traits::abs; + use crate::caret::CaretType; use crate::common::{Condition, Direction, Flag, Rect}; use crate::inventory::{AddExperienceResult, Inventory}; use crate::npc::{NPC, NPCMap}; use crate::physics::PhysicalEntity; -use crate::player::Player; +use crate::player::{Player, ControlMode}; use crate::shared_game_state::SharedGameState; impl PhysicalEntity for Player { @@ -135,6 +137,82 @@ impl Player { flags } + fn judge_hit_npc_solid_hard(&mut self, npc: &NPC, state: &mut SharedGameState) -> Flag { + let mut flags = Flag(0); + + let fx1 = abs(self.x - npc.x) as f32; + let fy1 = abs(self.y - npc.y) as f32; + + let fx2 = npc.hit_bounds.right as f32; + let fy2 = npc.hit_bounds.top as f32; + + let fx1 = if fx1 == 0.0 { 1.0 } else { fx1 }; + let fx2 = if fx2 == 0.0 { 1.0 } else { fx2 }; + + if fy1 / fx1 <= fy2 / fx2 { + if (self.y - self.hit_bounds.top as isize) < (npc.y + npc.hit_bounds.bottom as isize) + && (self.y + self.hit_bounds.bottom as isize) > (npc.y - npc.hit_bounds.top as isize) { + if (self.x - self.hit_bounds.right as isize) < (npc.x + npc.hit_bounds.right as isize) + && (self.x - self.hit_bounds.right as isize) > npc.x { + if self.vel_x < npc.vel_x { + self.vel_x = npc.vel_x; + } + + self.x = npc.x + npc.hit_bounds.right as isize + self.hit_bounds.right as isize; + flags.set_hit_left_wall(true); + } + + if (self.x + self.hit_bounds.right as isize) > (npc.x - npc.hit_bounds.right as isize) + && (self.x + self.hit_bounds.right as isize) < npc.x { + if self.vel_x > npc.vel_x { + self.vel_x = npc.vel_x; + } + + self.x = npc.x - npc.hit_bounds.right as isize - self.hit_bounds.right as isize; + flags.set_hit_right_wall(true); + } + } + } else if (self.x - self.hit_bounds.right as isize) < (npc.x + npc.hit_bounds.right as isize) + && (self.x + self.hit_bounds.right as isize) > (npc.x - npc.hit_bounds.right as isize) { + if (self.y - self.hit_bounds.top as isize) < (npc.y + npc.hit_bounds.bottom as isize) + && (self.y - self.hit_bounds.top as isize) > npc.y { + if self.vel_y >= npc.vel_y { + if self.vel_y < 0 { + self.vel_y = 0; + } + } else { + self.y = npc.y + npc.hit_bounds.bottom as isize + self.hit_bounds.top as isize + 0x200; + self.vel_y = npc.vel_y; + } + + flags.set_hit_top_wall(true); + } + + if (self.y + self.hit_bounds.bottom as isize) > (npc.y - npc.hit_bounds.top as isize) + && (self.y + self.hit_bounds.bottom as isize) < (npc.y + 3 * 0x200) { + if self.vel_y - npc.vel_y > 2 * 0x200 { + state.sound_manager.play_sfx(23); + } + + if self.control_mode == ControlMode::IronHead { + self.y = npc.y - npc.hit_bounds.top as isize - self.hit_bounds.bottom as isize + 0x200; + flags.set_hit_bottom_wall(true); + } else if npc.npc_flags.bouncy() { + self.vel_y = npc.vel_y - 0x200; + flags.set_hit_bottom_wall(true); + } else if !self.flags.hit_bottom_wall() && self.vel_y > npc.vel_y { + self.y = npc.y - npc.hit_bounds.top as isize - self.hit_bounds.bottom as isize + 0x200; + self.vel_y = npc.vel_y; + self.x += npc.vel_x; + + flags.set_hit_bottom_wall(true); + } + } + } + + flags + } + fn judge_hit_npc_non_solid(&mut self, npc: &NPC) -> Flag { let mut flags = Flag(0); let hit_left = if npc.direction == Direction::Left { npc.hit_bounds.left } else { npc.hit_bounds.right } as isize; @@ -162,7 +240,8 @@ impl Player { flags = self.judge_hit_npc_solid_soft(npc.borrow()); self.flags.0 |= flags.0; } else if npc.npc_flags.solid_hard() { - // + flags = self.judge_hit_npc_solid_hard(npc.borrow(), state); + self.flags.0 |= flags.0; } else { flags = self.judge_hit_npc_non_solid(npc.borrow()); }