mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-03-22 18:09:32 +00:00
physics fixes
This commit is contained in:
parent
048816bfe7
commit
01dfb7997a
|
@ -32,7 +32,6 @@ impl BulletManager {
|
|||
}
|
||||
|
||||
bullet.tick(state, player);
|
||||
bullet.hit_flags.0 = 0;
|
||||
bullet.tick_map_collisions(state, stage);
|
||||
}
|
||||
|
||||
|
@ -450,9 +449,8 @@ impl PhysicalEntity for Bullet {
|
|||
self.vel_y
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn size(&self) -> u8 {
|
||||
1
|
||||
fn hit_rect_size(&self) -> usize {
|
||||
2
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -515,6 +513,7 @@ impl PhysicalEntity for Bullet {
|
|||
let y = clamp(self.y() / 16 / 0x200, 0, stage.map.height as isize);
|
||||
let mut hit_attribs = [0u8; 4];
|
||||
|
||||
self.flags().0 = 0;
|
||||
if self.flags.hit_right_wall() { // ???
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ pub struct NPCConsts {
|
|||
pub n008_blue_beetle: [Rect<usize>; 4],
|
||||
pub n009_balrog_falling_in: [Rect<usize>; 6],
|
||||
pub n010_balrog_shooting: [Rect<usize>; 8],
|
||||
pub n011_balrogs_projectile: [Rect<usize>; 3],
|
||||
pub n011_balrog_energy_shot: [Rect<usize>; 3],
|
||||
pub n012_balrog_cutscene: [Rect<usize>; 28],
|
||||
pub n013_forcefield: [Rect<usize>; 4],
|
||||
pub n014_key: [Rect<usize>; 3],
|
||||
|
@ -156,7 +156,7 @@ pub struct NPCConsts {
|
|||
pub n016_save_point: [Rect<usize>; 8],
|
||||
pub n017_health_refill: [Rect<usize>; 2],
|
||||
pub n018_door: [Rect<usize>; 2],
|
||||
pub n019_balrog_burst: [Rect<usize>; 8],
|
||||
pub n019_balrog_bust_in: [Rect<usize>; 8],
|
||||
pub n020_computer: [Rect<usize>; 4],
|
||||
pub n021_chest_open: Rect<usize>,
|
||||
pub n022_teleporter: [Rect<usize>; 2],
|
||||
|
@ -540,7 +540,7 @@ impl EngineConstants {
|
|||
Rect { left: 80, top: 24, right: 120, bottom: 48 },
|
||||
Rect { left: 120, top: 24, right: 160, bottom: 48 },
|
||||
],
|
||||
n011_balrogs_projectile: [
|
||||
n011_balrog_energy_shot: [
|
||||
Rect { left: 208, top: 104, right: 224, bottom: 120 },
|
||||
Rect { left: 224, top: 104, right: 240, bottom: 120 },
|
||||
Rect { left: 240, top: 104, right: 256, bottom: 120 },
|
||||
|
@ -609,7 +609,7 @@ impl EngineConstants {
|
|||
Rect { left: 224, top: 16, right: 240, bottom: 40 },
|
||||
Rect { left: 192, top: 112, right: 208, bottom: 136 },
|
||||
],
|
||||
n019_balrog_burst: [
|
||||
n019_balrog_bust_in: [
|
||||
Rect { left: 0, top: 0, right: 40, bottom: 24 }, // left
|
||||
Rect { left: 160, top: 0, right: 200, bottom: 24 },
|
||||
Rect { left: 80, top: 0, right: 120, bottom: 24 },
|
||||
|
|
|
@ -55,6 +55,10 @@ impl Map {
|
|||
}
|
||||
|
||||
pub fn get_attribute(&self, x: usize, y: usize) -> u8 {
|
||||
if x >= self.width || y >= self.height {
|
||||
return 0;
|
||||
}
|
||||
|
||||
self.attrib[*self.tiles.get(self.width * y + x).unwrap_or_else(|| &0u8) as usize]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -189,7 +189,7 @@ impl NPC {
|
|||
}
|
||||
}
|
||||
|
||||
self.anim_rect = state.constants.npc.n011_balrogs_projectile[self.anim_num as usize];
|
||||
self.anim_rect = state.constants.npc.n011_balrog_energy_shot[self.anim_num as usize];
|
||||
|
||||
self.action_counter2 += 1;
|
||||
if self.action_counter2 > 150 {
|
||||
|
@ -591,7 +591,7 @@ impl NPC {
|
|||
} else {
|
||||
self.action_counter += 1;
|
||||
|
||||
if self.flags.hit_left_wall() || self.flags.hit_right_wall() || self.action_counter > 75 {
|
||||
if (self.flags.hit_left_wall() || self.flags.hit_right_wall()) || self.action_counter > 75 {
|
||||
self.action_num = 9;
|
||||
self.anim_num = 0;
|
||||
} else if self.action_counter2 % 3 == 0 && self.action_counter > 25 {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use num_traits::real::Real;
|
||||
|
||||
use crate::caret::CaretType;
|
||||
use crate::common::Direction;
|
||||
use crate::ggez::GameResult;
|
||||
|
@ -5,17 +7,22 @@ use crate::npc::{NPC, NPCMap};
|
|||
use crate::player::Player;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::stage::Stage;
|
||||
use num_traits::real::Real;
|
||||
|
||||
impl NPC {
|
||||
pub(crate) fn tick_n000_null(&mut self) -> GameResult {
|
||||
if self.action_num != 0xffff {
|
||||
self.action_num = 0xffff;
|
||||
self.anim_rect.left = 0;
|
||||
self.anim_rect.top = 0;
|
||||
self.anim_rect.right = 0;
|
||||
self.anim_rect.bottom = 0;
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
|
||||
if self.direction == Direction::Right {
|
||||
self.y += 16 * 0x200;
|
||||
}
|
||||
}
|
||||
|
||||
self.anim_rect.left = 0;
|
||||
self.anim_rect.top = 0;
|
||||
self.anim_rect.right = 16;
|
||||
self.anim_rect.bottom = 16;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -191,29 +191,25 @@ impl GameEntity<(&mut Player, &HashMap<u16, RefCell<NPC>>, &mut Stage)> for NPC
|
|||
|
||||
impl PhysicalEntity for NPC {
|
||||
#[inline(always)]
|
||||
fn x(&self) -> isize {
|
||||
self.x
|
||||
}
|
||||
fn x(&self) -> isize { self.x }
|
||||
|
||||
#[inline(always)]
|
||||
fn y(&self) -> isize {
|
||||
self.y
|
||||
}
|
||||
fn y(&self) -> isize { self.y }
|
||||
|
||||
#[inline(always)]
|
||||
fn vel_x(&self) -> isize {
|
||||
self.vel_x
|
||||
}
|
||||
fn vel_x(&self) -> isize { self.vel_x }
|
||||
|
||||
#[inline(always)]
|
||||
fn vel_y(&self) -> isize {
|
||||
self.vel_y
|
||||
}
|
||||
fn vel_y(&self) -> isize { self.vel_y }
|
||||
|
||||
#[inline(always)]
|
||||
fn size(&self) -> u8 {
|
||||
self.size
|
||||
}
|
||||
fn hit_rect_size(&self) -> usize { if self.size >= 3 { 3 } else { 2 } }
|
||||
|
||||
#[inline(always)]
|
||||
fn offset_x(&self) -> isize { if self.size >= 3 { -0x1000 } else { 0 } }
|
||||
|
||||
#[inline(always)]
|
||||
fn offset_y(&self) -> isize { if self.size >= 3 { -0x1000 } else { 0 } }
|
||||
|
||||
#[inline(always)]
|
||||
fn hit_bounds(&self) -> &Rect<usize> {
|
||||
|
|
|
@ -5,8 +5,14 @@ use crate::common::{Condition, Direction, Flag, Rect};
|
|||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::stage::Stage;
|
||||
|
||||
pub const OFF_X: [isize; 9] = [0, 1, 0, 1, 2, 2, 2, 0, 1];
|
||||
pub const OFF_Y: [isize; 9] = [0, 0, 1, 1, 0, 1, 2, 2, 2];
|
||||
// -1 0 1 2
|
||||
// +------------
|
||||
// -1 | 10 14 15 16
|
||||
// 0 | 11 1 2 5
|
||||
// 1 | 12 3 4 6
|
||||
// 2 | 13 8 9 7
|
||||
pub const OFF_X: [isize; 16] = [0, 1, 0, 1, 2, 2, 2, 0, 1, -1, -1, -1, -1, 0, 1, 2];
|
||||
pub const OFF_Y: [isize; 16] = [0, 0, 1, 1, 0, 1, 2, 2, 2, -1, 0, 1, 2, -1, -1, -1];
|
||||
|
||||
pub trait PhysicalEntity {
|
||||
fn x(&self) -> isize;
|
||||
|
@ -14,7 +20,9 @@ pub trait PhysicalEntity {
|
|||
fn vel_x(&self) -> isize;
|
||||
fn vel_y(&self) -> isize;
|
||||
|
||||
fn size(&self) -> u8;
|
||||
fn hit_rect_size(&self) -> usize;
|
||||
fn offset_x(&self) -> isize { 0 }
|
||||
fn offset_y(&self) -> isize { 0 }
|
||||
|
||||
fn hit_bounds(&self) -> &Rect<usize>;
|
||||
|
||||
|
@ -31,11 +39,11 @@ pub trait PhysicalEntity {
|
|||
fn ignore_tile_44(&self) -> bool { true }
|
||||
|
||||
fn judge_hit_block(&mut self, state: &mut SharedGameState, x: isize, y: isize) {
|
||||
let bounds_x = 5;
|
||||
let bounds_x = if self.is_player() { 5 } else { 8 };
|
||||
let bounds_y = if self.is_player() { 4 } else { 5 };
|
||||
// left wall
|
||||
if (self.y() - self.hit_bounds().top as isize) < (y * 16 + bounds_y) * 0x200
|
||||
&& self.y() + self.hit_bounds().bottom as isize > (y * 16 - bounds_y) * 0x200
|
||||
&& (self.y() + self.hit_bounds().bottom as isize) > (y * 16 - bounds_y) * 0x200
|
||||
&& (self.x() - self.hit_bounds().right as isize) < (x * 16 + 8) * 0x200
|
||||
&& (self.x() - self.hit_bounds().right as isize) > x * 16 * 0x200 {
|
||||
self.set_x(((x * 16 + 8) * 0x200) + self.hit_bounds().right as isize);
|
||||
|
@ -100,8 +108,8 @@ pub trait PhysicalEntity {
|
|||
// floor
|
||||
if ((self.x() - self.hit_bounds().right as isize) < (x * 16 + bounds_x) * 0x200)
|
||||
&& ((self.x() + self.hit_bounds().right as isize) > (x * 16 - bounds_x) * 0x200)
|
||||
&& ((self.y() + self.hit_bounds().bottom as isize) > (y * 16 - 8) * 0x200)
|
||||
&& ((self.y() + self.hit_bounds().bottom as isize) < y * 16 * 0x200) {
|
||||
&& ((self.y() + self.hit_bounds().bottom as isize) > ((y * 16 - 8) * 0x200))
|
||||
&& ((self.y() + self.hit_bounds().bottom as isize) < (y * 16 * 0x200)) {
|
||||
self.set_y(((y * 16 - 8) * 0x200) - self.hit_bounds().bottom as isize);
|
||||
|
||||
if self.is_player() {
|
||||
|
@ -344,12 +352,15 @@ pub trait PhysicalEntity {
|
|||
}
|
||||
|
||||
fn tick_map_collisions(&mut self, state: &mut SharedGameState, stage: &mut Stage) {
|
||||
let big = self.size() >= 3;
|
||||
let x = clamp((self.x() - if big { 0x1000 } else { 0 }) / 16 / 0x200, 0, stage.map.width as isize);
|
||||
let y = clamp((self.y() - if big { 0x1000 } else { 0 }) / 16 / 0x200, 0, stage.map.height as isize);
|
||||
let hit_rect_size = clamp(self.hit_rect_size(), 1, 4);
|
||||
let hit_rect_size = hit_rect_size * hit_rect_size;
|
||||
|
||||
let x = clamp((self.x() + self.offset_x()) / 16 / 0x200, 0, stage.map.width as isize);
|
||||
let y = clamp((self.y() + self.offset_y()) / 16 / 0x200, 0, stage.map.height as isize);
|
||||
|
||||
self.flags().0 = 0;
|
||||
for (idx, (&ox, &oy)) in OFF_X.iter().zip(OFF_Y.iter()).enumerate() {
|
||||
if idx == 4 && !big {
|
||||
if idx == hit_rect_size {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -368,12 +379,12 @@ pub trait PhysicalEntity {
|
|||
self.judge_hit_water(x + ox, y + oy);
|
||||
}
|
||||
0x61 => {
|
||||
self.judge_hit_water(x + ox, y + oy);
|
||||
self.judge_hit_block(state, x + ox, y + oy);
|
||||
self.judge_hit_water(x + ox, y + oy);
|
||||
}
|
||||
0x04 | 0x64 if !self.is_player() => {
|
||||
self.judge_hit_water(x + ox, y + oy);
|
||||
self.judge_hit_block(state, x + ox, y + oy);
|
||||
self.judge_hit_water(x + ox, y + oy);
|
||||
}
|
||||
0x05 | 0x41 | 0x43 | 0x46 if self.is_player() => {
|
||||
self.judge_hit_block(state, x + ox, y + oy);
|
||||
|
@ -423,16 +434,16 @@ pub trait PhysicalEntity {
|
|||
|
||||
// Forces
|
||||
0x80 | 0xa0 if self.is_player() => {
|
||||
self.judge_hit_force(x + ox, y + ox, Direction::Left, attrib & 0x20 != 0);
|
||||
self.judge_hit_force(x + ox, y + oy, Direction::Left, attrib & 0x20 != 0);
|
||||
}
|
||||
0x81 | 0xa1 if self.is_player() => {
|
||||
self.judge_hit_force(x + ox, y + ox, Direction::Up, attrib & 0x20 != 0);
|
||||
self.judge_hit_force(x + ox, y + oy, Direction::Up, attrib & 0x20 != 0);
|
||||
}
|
||||
0x82 | 0xa2 if self.is_player() => {
|
||||
self.judge_hit_force(x + ox, y + ox, Direction::Right, attrib & 0x20 != 0);
|
||||
self.judge_hit_force(x + ox, y + oy, Direction::Right, attrib & 0x20 != 0);
|
||||
}
|
||||
0x83 | 0xa3 if self.is_player() => {
|
||||
self.judge_hit_force(x + ox, y + ox, Direction::Bottom, attrib & 0x20 != 0);
|
||||
self.judge_hit_force(x + ox, y + oy, Direction::Bottom, attrib & 0x20 != 0);
|
||||
}
|
||||
0x80 | 0xa0 if !self.is_player() => {
|
||||
self.flags().set_force_left(true);
|
||||
|
|
|
@ -29,9 +29,8 @@ impl PhysicalEntity for Player {
|
|||
self.vel_y
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn size(&self) -> u8 {
|
||||
1
|
||||
fn hit_rect_size(&self) -> usize {
|
||||
2
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
|
|
@ -871,7 +871,6 @@ impl GameScene {
|
|||
self.npc_map.process_npc_changes(state);
|
||||
self.npc_map.garbage_collect();
|
||||
|
||||
self.player.flags.0 = 0;
|
||||
self.player.tick_map_collisions(state, &mut self.stage);
|
||||
self.player.tick_npc_collisions(state, &mut self.npc_map, &mut self.inventory);
|
||||
|
||||
|
@ -880,7 +879,6 @@ impl GameScene {
|
|||
let mut npc = npc_cell.borrow_mut();
|
||||
|
||||
if npc.cond.alive() && !npc.npc_flags.ignore_solidity() {
|
||||
npc.flags.0 = 0;
|
||||
npc.tick_map_collisions(state, &mut self.stage);
|
||||
}
|
||||
}
|
||||
|
@ -1022,25 +1020,25 @@ impl GameScene {
|
|||
}
|
||||
|
||||
// top
|
||||
state.texture_set.draw_rect(Rect::new_size((npc.x - npc.hit_bounds.left as isize - self.frame.x) / 0x200,
|
||||
state.texture_set.draw_rect(Rect::new_size((npc.x - npc.hit_bounds.right as isize - self.frame.x) / 0x200,
|
||||
(npc.y - npc.hit_bounds.top as isize - self.frame.y) / 0x200,
|
||||
(npc.hit_bounds.left + npc.hit_bounds.right) as isize / 0x200,
|
||||
(npc.hit_bounds.right + npc.hit_bounds.right) as isize / 0x200,
|
||||
1),
|
||||
[0.0, if npc.flags.hit_top_wall() { 1.0 } else { 0.0 }, 1.0, 1.0], ctx)?;
|
||||
// bottom
|
||||
state.texture_set.draw_rect(Rect::new_size((npc.x - npc.hit_bounds.left as isize - self.frame.x) / 0x200,
|
||||
(npc.y + npc.hit_bounds.bottom as isize - self.frame.y) / 0x200,
|
||||
(npc.hit_bounds.left + npc.hit_bounds.right) as isize / 0x200,
|
||||
state.texture_set.draw_rect(Rect::new_size((npc.x - npc.hit_bounds.right as isize - self.frame.x) / 0x200,
|
||||
(npc.y + npc.hit_bounds.bottom as isize - self.frame.y) / 0x200 - 1,
|
||||
(npc.hit_bounds.right + npc.hit_bounds.right) as isize / 0x200,
|
||||
1),
|
||||
[0.0, if npc.flags.hit_bottom_wall() { 1.0 } else { 0.0 }, 1.0, 1.0], ctx)?;
|
||||
// left
|
||||
state.texture_set.draw_rect(Rect::new_size((npc.x - npc.hit_bounds.left as isize - self.frame.x) / 0x200,
|
||||
state.texture_set.draw_rect(Rect::new_size((npc.x - npc.hit_bounds.right as isize - self.frame.x) / 0x200,
|
||||
(npc.y - npc.hit_bounds.top as isize - self.frame.y) / 0x200,
|
||||
1,
|
||||
(npc.hit_bounds.top + npc.hit_bounds.bottom) as isize / 0x200),
|
||||
[0.0, if npc.flags.hit_left_wall() { 1.0 } else { 0.0 }, 1.0, 1.0], ctx)?;
|
||||
// right
|
||||
state.texture_set.draw_rect(Rect::new_size((npc.x + npc.hit_bounds.right as isize - self.frame.x) / 0x200,
|
||||
state.texture_set.draw_rect(Rect::new_size((npc.x + npc.hit_bounds.right as isize - self.frame.x) / 0x200 - 1,
|
||||
(npc.y - npc.hit_bounds.top as isize - self.frame.y) / 0x200,
|
||||
1,
|
||||
(npc.hit_bounds.top + npc.hit_bounds.bottom) as isize / 0x200),
|
||||
|
|
Loading…
Reference in a new issue