1
0
Fork 0
mirror of https://github.com/doukutsu-rs/doukutsu-rs synced 2025-03-24 02:49:21 +00:00

rounding fixes

This commit is contained in:
Alula 2021-05-05 20:36:21 +02:00
parent 4904c165ed
commit 80a2fc024c
No known key found for this signature in database
GPG key ID: 3E00485503A1D8BA
8 changed files with 237 additions and 106 deletions

View file

@ -8,6 +8,7 @@ use serde::de::{SeqAccess, Visitor};
use serde::ser::SerializeTupleStruct;
use crate::bitfield;
use crate::texture_set::G_MAG;
/// Multiply cave story degrees (0-255, which corresponds to 0°-360°) with this to get
/// respective value in radians.
@ -367,8 +368,11 @@ rect_deserialze!(isize);
rect_deserialze!(usize);
#[inline(always)]
pub fn fix9_scale(val: i32, scale: f32) -> f32 {
(val as f64 * scale as f64 / 512.0).floor() as f32 / scale
pub fn fix9_scale(val: i32) -> f32 {
unsafe {
let mag = G_MAG as f32;
(val as f32 * mag / 512.0).floor() / mag
}
}
#[inline(always)]
@ -376,12 +380,21 @@ fn lerp_f64(v1: f64, v2: f64, t: f64) -> f64 {
v1 * (1.0 - t) + v2 * t
}
#[inline(always)]
fn lerp_f32(v1: f32, v2: f32, t: f32) -> f32 {
v1 * (1.0 - t) + v2 * t
}
pub fn interpolate_fix9_scale(old_val: i32, val: i32, frame_delta: f64) -> f32 {
if abs(old_val - val) > 0x1000 {
if abs(old_val - val) > 0x1800 {
return val as f32 / 512.0;
}
(lerp_f64(old_val as f64, val as f64, frame_delta) / 512.0) as f32
unsafe {
let interpolated = lerp_f64(old_val as f64, val as f64, frame_delta) as f32;
let mag = G_MAG as f32;
(interpolated * mag / 512.0).floor() / mag
}
}

View file

@ -65,7 +65,7 @@ impl GameEntity<()> for Flash {
FlashState::None => {}
FlashState::Cross(x, y, tick) => {
let tick = tick as f32 + state.frame_time as f32;
let frame_pos = frame.xy_interpolated(state.frame_time, state.scale);
let frame_pos = frame.xy_interpolated(state.frame_time);
let (cen_x, cen_y) = (
(x as f32 / 512.0) - frame_pos.0,

View file

@ -23,9 +23,9 @@ pub struct Frame {
}
impl Frame {
pub fn xy_interpolated(&self, frame_time: f64, scale: f32) -> (f32, f32) {
pub fn xy_interpolated(&self, frame_time: f64) -> (f32, f32) {
if self.prev_x == self.x && self.prev_y == self.y {
return (fix9_scale(self.x, scale), fix9_scale(self.y, scale));
return (fix9_scale(self.x), fix9_scale(self.y));
}
let x = interpolate_fix9_scale(self.prev_x, self.x, frame_time);

View file

@ -110,16 +110,16 @@ impl GameEntity<([&mut Player; 2], &NPCList, &mut Stage, &BulletManager, &mut Fl
let off_x =
if npc.direction == Direction::Left { npc.display_bounds.left } else { npc.display_bounds.right }
as i32;
let shock = if npc.shock > 0 { (2 * ((npc.shock as i32 / 2) % 2) - 1) as f32 } else { 0.0 };
let shock = if npc.shock > 0 { (2 * ((npc.shock as i32 / 2) & 1) - 1) as f32 } else { 0.0 };
let (frame_x, frame_y) = frame.xy_interpolated(state.frame_time);
batch.add_rect(
interpolate_fix9_scale(npc.prev_x - off_x - frame.prev_x, npc.x - off_x - frame.x, state.frame_time)
+ shock,
interpolate_fix9_scale(
npc.prev_y - npc.display_bounds.top as i32 - frame.prev_y,
npc.y - npc.display_bounds.top as i32 - frame.y,
state.frame_time,
),
interpolate_fix9_scale(npc.prev_x - off_x,
npc.x - off_x,
state.frame_time) + shock - frame_x,
interpolate_fix9_scale(npc.prev_y - npc.display_bounds.top as i32,
npc.y - npc.display_bounds.top as i32,
state.frame_time) - frame_y,
&npc.anim_rect,
);
}

View file

@ -406,13 +406,15 @@ impl GameEntity<([&mut Player; 2], &NPCList, &mut Stage, &BulletManager, &mut Fl
(2 * ((self.shock as i32 / 2) % 2) - 1) as f32
} else { 0.0 };
let (frame_x, frame_y) = frame.xy_interpolated(state.frame_time);
batch.add_rect(
interpolate_fix9_scale(self.prev_x - off_x - frame.prev_x,
self.x - off_x - frame.x,
state.frame_time) + shock,
interpolate_fix9_scale(self.prev_y - self.display_bounds.top as i32 - frame.prev_y,
self.y - self.display_bounds.top as i32 - frame.y,
state.frame_time),
interpolate_fix9_scale(self.prev_x - off_x,
self.x - off_x,
state.frame_time) + shock - frame_x,
interpolate_fix9_scale(self.prev_y - self.display_bounds.top as i32,
self.y - self.display_bounds.top as i32,
state.frame_time) - frame_y,
&self.anim_rect,
);
batch.draw(ctx)?;

View file

@ -740,6 +740,8 @@ impl GameEntity<&NPCList> for Player {
return Ok(());
}
let (frame_x, frame_y) = frame.xy_interpolated(state.frame_time);
// hack for stacked dogs
if state.constants.is_switch {
let dog_amount = (3000..=3005).filter(|id| state.get_flag(*id as usize)).count();
@ -762,15 +764,15 @@ impl GameEntity<&NPCList> for Player {
for i in 1..=(dog_amount as i32) {
batch.add_rect(
interpolate_fix9_scale(
self.prev_x - frame.prev_x - off_x - vec_x * i,
self.x - frame.x - off_x - vec_x * i,
self.prev_x - off_x - vec_x * i,
self.x - off_x - vec_x * i,
state.frame_time,
),
) - frame_x,
interpolate_fix9_scale(
self.prev_y - frame.prev_y - off_y - vec_y * i,
self.y - frame.y - off_y - vec_y * i,
self.prev_y - off_y - vec_y * i,
self.y - off_y - vec_y * i,
state.frame_time,
),
) - frame_y,
&state.constants.npc.n136_puppy_carried[frame_id],
);
}
@ -788,15 +790,17 @@ impl GameEntity<&NPCList> for Player {
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "Arms")?;
batch.add_rect(
interpolate_fix9_scale(
self.prev_x - self.display_bounds.left as i32 - frame.prev_x,
self.x - self.display_bounds.left as i32 - frame.x,
self.prev_x - self.display_bounds.left as i32,
self.x - self.display_bounds.left as i32,
state.frame_time,
) + if self.direction == Direction::Left { -8.0 } else { 0.0 },
) + if self.direction == Direction::Left { -8.0 } else { 0.0 }
- frame_x,
interpolate_fix9_scale(
self.prev_y - self.display_bounds.left as i32 - frame.prev_y,
self.y - self.display_bounds.left as i32 - frame.y,
self.prev_y - self.display_bounds.left as i32,
self.y - self.display_bounds.left as i32,
state.frame_time,
) + self.weapon_offset_y as f32,
) + self.weapon_offset_y as f32
- frame_y,
&self.weapon_rect,
);
@ -808,15 +812,15 @@ impl GameEntity<&NPCList> for Player {
state.texture_set.get_or_load_batch(ctx, &state.constants, self.skin.get_skin_texture_name())?;
batch.add_rect(
interpolate_fix9_scale(
self.prev_x - self.display_bounds.left as i32 - frame.prev_x,
self.x - self.display_bounds.left as i32 - frame.x,
self.prev_x - self.display_bounds.left as i32,
self.x - self.display_bounds.left as i32,
state.frame_time,
),
) - frame_x,
interpolate_fix9_scale(
self.prev_y - self.display_bounds.left as i32 - frame.prev_y,
self.y - self.display_bounds.left as i32 - frame.y,
self.prev_y - self.display_bounds.left as i32,
self.y - self.display_bounds.left as i32,
state.frame_time,
),
) - frame_y,
&self.anim_rect,
);
batch.draw(ctx)?;
@ -825,16 +829,8 @@ impl GameEntity<&NPCList> for Player {
if (self.equip.has_air_tank() && self.flags.in_water()) || self.control_mode == ControlMode::IronHead {
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "Caret")?;
batch.add_rect(
interpolate_fix9_scale(
self.prev_x - frame.prev_x - 12 * 0x200,
self.x - frame.x - 12 * 0x200,
state.frame_time,
),
interpolate_fix9_scale(
self.prev_y - frame.prev_y - 12 * 0x200,
self.y - frame.y - 12 * 0x200,
state.frame_time,
),
interpolate_fix9_scale(self.prev_x - 12 * 0x200, self.x - 12 * 0x200, state.frame_time) - frame_x,
interpolate_fix9_scale(self.prev_y - 12 * 0x200, self.y - 12 * 0x200, state.frame_time) - frame_y,
&state.constants.player.frames_bubble[(self.tick / 2 % 2) as usize],
);
batch.draw(ctx)?;

View file

@ -138,7 +138,7 @@ impl GameScene {
fn draw_background(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, &self.tex_background_name)?;
let scale = state.scale;
let (frame_x, frame_y) = self.frame.xy_interpolated(state.frame_time, state.scale);
let (frame_x, frame_y) = self.frame.xy_interpolated(state.frame_time);
match self.stage.data.background_type {
BackgroundType::Stationary => {
@ -761,8 +761,16 @@ impl GameScene {
for bullet in self.bullet_manager.bullets.iter() {
self.draw_light(
fix9_scale(bullet.x - self.frame.x, scale),
fix9_scale(bullet.y - self.frame.y, scale),
interpolate_fix9_scale(
bullet.prev_x - self.frame.prev_x,
bullet.x - self.frame.x,
state.frame_time,
),
interpolate_fix9_scale(
bullet.prev_y - self.frame.prev_y,
bullet.y - self.frame.y,
state.frame_time,
),
0.3,
(200, 200, 200),
batch,
@ -773,8 +781,16 @@ impl GameScene {
match caret.ctype {
CaretType::ProjectileDissipation | CaretType::Shoot => {
self.draw_light(
fix9_scale(caret.x - self.frame.x, scale),
fix9_scale(caret.y - self.frame.y, scale),
interpolate_fix9_scale(
caret.prev_x - self.frame.prev_x,
caret.x - self.frame.x,
state.frame_time,
),
interpolate_fix9_scale(
caret.prev_y - self.frame.prev_y,
caret.y - self.frame.y,
state.frame_time,
),
1.0,
(200, 200, 200),
batch,
@ -803,38 +819,62 @@ impl GameScene {
match npc.npc_type {
1 => {
self.draw_light(
fix9_scale(npc.x - self.frame.x, scale),
fix9_scale(npc.y - self.frame.y, scale),
interpolate_fix9_scale(
npc.prev_x - self.frame.prev_x,
npc.x - self.frame.x,
state.frame_time,
),
interpolate_fix9_scale(
npc.prev_y - self.frame.prev_y,
npc.y - self.frame.y,
state.frame_time,
),
0.4,
(255, 255, 0),
batch,
);
}
4 if npc.direction == Direction::Up => self.draw_light(
fix9_scale(npc.x - self.frame.x, scale),
fix9_scale(npc.y - self.frame.y, scale),
interpolate_fix9_scale(npc.prev_x - self.frame.prev_x, npc.x - self.frame.x, state.frame_time),
interpolate_fix9_scale(npc.prev_y - self.frame.prev_y, npc.y - self.frame.y, state.frame_time),
1.0,
(200, 100, 0),
batch,
),
7 => self.draw_light(
fix9_scale(npc.x - self.frame.x, scale),
fix9_scale(npc.y - self.frame.y, scale),
interpolate_fix9_scale(npc.prev_x - self.frame.prev_x, npc.x - self.frame.x, state.frame_time),
interpolate_fix9_scale(npc.prev_y - self.frame.prev_y, npc.y - self.frame.y, state.frame_time),
1.0,
(100, 100, 100),
batch,
),
17 if npc.anim_num == 0 => {
self.draw_light(
fix9_scale(npc.x - self.frame.x, scale),
fix9_scale(npc.y - self.frame.y, scale),
interpolate_fix9_scale(
npc.prev_x - self.frame.prev_x,
npc.x - self.frame.x,
state.frame_time,
),
interpolate_fix9_scale(
npc.prev_y - self.frame.prev_y,
npc.y - self.frame.y,
state.frame_time,
),
2.0,
(160, 0, 0),
batch,
);
self.draw_light(
fix9_scale(npc.x - self.frame.x, scale),
fix9_scale(npc.y - self.frame.y, scale),
interpolate_fix9_scale(
npc.prev_x - self.frame.prev_x,
npc.x - self.frame.x,
state.frame_time,
),
interpolate_fix9_scale(
npc.prev_y - self.frame.prev_y,
npc.y - self.frame.y,
state.frame_time,
),
0.5,
(255, 0, 0),
batch,
@ -842,8 +882,16 @@ impl GameScene {
}
20 if npc.direction == Direction::Right => {
self.draw_light(
fix9_scale(npc.x - self.frame.x, scale),
fix9_scale(npc.y - self.frame.y, scale),
interpolate_fix9_scale(
npc.prev_x - self.frame.prev_x,
npc.x - self.frame.x,
state.frame_time,
),
interpolate_fix9_scale(
npc.prev_y - self.frame.prev_y,
npc.y - self.frame.y,
state.frame_time,
),
2.0,
(0, 0, 150),
batch,
@ -851,8 +899,16 @@ impl GameScene {
if npc.anim_num < 2 {
self.draw_light(
fix9_scale(npc.x - self.frame.x, scale),
fix9_scale(npc.y - self.frame.y, scale),
interpolate_fix9_scale(
npc.prev_x - self.frame.prev_x,
npc.x - self.frame.x,
state.frame_time,
),
interpolate_fix9_scale(
npc.prev_y - self.frame.prev_y,
npc.y - self.frame.y,
state.frame_time,
),
2.1,
(0, 0, 30),
batch,
@ -860,16 +916,24 @@ impl GameScene {
}
}
22 if npc.action_num == 1 && npc.anim_num == 1 => self.draw_light(
fix9_scale(npc.x - self.frame.x, scale),
fix9_scale(npc.y - self.frame.y, scale),
interpolate_fix9_scale(npc.prev_x - self.frame.prev_x, npc.x - self.frame.x, state.frame_time),
interpolate_fix9_scale(npc.prev_y - self.frame.prev_y, npc.y - self.frame.y, state.frame_time),
3.0,
(0, 0, 255),
batch,
),
32 | 87 | 211 => {
self.draw_light(
fix9_scale(npc.x - self.frame.x, scale),
fix9_scale(npc.y - self.frame.y, scale),
interpolate_fix9_scale(
npc.prev_x - self.frame.prev_x,
npc.x - self.frame.x,
state.frame_time,
),
interpolate_fix9_scale(
npc.prev_y - self.frame.prev_y,
npc.y - self.frame.y,
state.frame_time,
),
2.0,
(255, 30, 30),
batch,
@ -878,8 +942,16 @@ impl GameScene {
38 => {
let flicker = (npc.anim_num ^ 5 & 3) as u8 * 15;
self.draw_light(
fix9_scale(npc.x - self.frame.x, scale),
fix9_scale(npc.y - self.frame.y, scale),
interpolate_fix9_scale(
npc.prev_x - self.frame.prev_x,
npc.x - self.frame.x,
state.frame_time,
),
interpolate_fix9_scale(
npc.prev_y - self.frame.prev_y,
npc.y - self.frame.y,
state.frame_time,
),
3.5,
(130 + flicker, 40 + flicker, 0),
batch,
@ -888,16 +960,24 @@ impl GameScene {
70 => {
let flicker = 50 + npc.anim_num as u8 * 15;
self.draw_light(
fix9_scale(npc.x - self.frame.x, scale),
fix9_scale(npc.y - self.frame.y, scale),
interpolate_fix9_scale(
npc.prev_x - self.frame.prev_x,
npc.x - self.frame.x,
state.frame_time,
),
interpolate_fix9_scale(
npc.prev_y - self.frame.prev_y,
npc.y - self.frame.y,
state.frame_time,
),
2.0,
(flicker, flicker, flicker),
batch,
);
}
75 | 77 => self.draw_light(
fix9_scale(npc.x - self.frame.x, scale),
fix9_scale(npc.y - self.frame.y, scale),
interpolate_fix9_scale(npc.prev_x - self.frame.prev_x, npc.x - self.frame.x, state.frame_time),
interpolate_fix9_scale(npc.prev_y - self.frame.prev_y, npc.y - self.frame.y, state.frame_time),
3.0,
(255, 100, 0),
batch,
@ -910,8 +990,16 @@ impl GameScene {
};
self.draw_light(
fix9_scale(npc.x - self.frame.x, scale),
fix9_scale(npc.y - self.frame.y, scale),
interpolate_fix9_scale(
npc.prev_x - self.frame.prev_x,
npc.x - self.frame.x,
state.frame_time,
),
interpolate_fix9_scale(
npc.prev_y - self.frame.prev_y,
npc.y - self.frame.y,
state.frame_time,
),
1.5,
color,
batch,
@ -919,8 +1007,16 @@ impl GameScene {
if npc.anim_num < 2 {
self.draw_light(
fix9_scale(npc.x - self.frame.x, scale),
fix9_scale(npc.y - self.frame.y, scale) - 8.0,
interpolate_fix9_scale(
npc.prev_x - self.frame.prev_x,
npc.x - self.frame.x,
state.frame_time,
),
interpolate_fix9_scale(
npc.prev_y - self.frame.prev_y,
npc.y - self.frame.y,
state.frame_time,
) - 8.0,
2.1,
color2,
batch,
@ -929,8 +1025,16 @@ impl GameScene {
}
299 => {
self.draw_light(
fix9_scale(npc.x - self.frame.x, scale),
fix9_scale(npc.y - self.frame.y, scale),
interpolate_fix9_scale(
npc.prev_x - self.frame.prev_x,
npc.x - self.frame.x,
state.frame_time,
),
interpolate_fix9_scale(
npc.prev_y - self.frame.prev_y,
npc.y - self.frame.y,
state.frame_time,
),
4.0,
(30, 30, 200),
batch,
@ -938,8 +1042,16 @@ impl GameScene {
}
300 => {
self.draw_light(
fix9_scale(npc.x - self.frame.x, scale),
fix9_scale(npc.y - self.frame.y, scale),
interpolate_fix9_scale(
npc.prev_x - self.frame.prev_x,
npc.x - self.frame.x,
state.frame_time,
),
interpolate_fix9_scale(
npc.prev_y - self.frame.prev_y,
npc.y - self.frame.y,
state.frame_time,
),
1.5,
(200, 10, 10),
batch,
@ -972,7 +1084,7 @@ impl GameScene {
};
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, tex)?;
let mut rect = Rect::new(0, 0, 16, 16);
let (frame_x, frame_y) = self.frame.xy_interpolated(state.frame_time, state.scale);
let (frame_x, frame_y) = self.frame.xy_interpolated(state.frame_time);
let tile_start_x = (frame_x as i32 / 16).clamp(0, self.stage.map.width as i32) as usize;
let tile_start_y = (frame_y as i32 / 16).clamp(0, self.stage.map.height as i32) as usize;
@ -1251,7 +1363,13 @@ impl GameScene {
for npc in self.npc_list.iter_alive() {
npc.tick(
state,
([&mut self.player1, &mut self.player2], &self.npc_list, &mut self.stage, &self.bullet_manager, &mut self.flash),
(
[&mut self.player1, &mut self.player2],
&self.npc_list,
&mut self.stage,
&self.bullet_manager,
&mut self.flash,
),
)?;
}
self.boss.tick(
@ -1745,10 +1863,12 @@ impl Scene for GameScene {
let pos_y = 0.0;
let line_height = state.font.line_height(&state.constants);
let w = (self.skip_counter as f32 / CUTSCENE_SKIP_WAIT as f32) * (width + 20.0) / 2.0;
let mut rect = Rect::new_size((pos_x * state.scale) as isize,
(pos_y * state.scale) as isize,
((20.0 + width) * state.scale) as isize,
((20.0 + line_height) * state.scale) as isize);
let mut rect = Rect::new_size(
(pos_x * state.scale) as isize,
(pos_y * state.scale) as isize,
((20.0 + width) * state.scale) as isize,
((20.0 + line_height) * state.scale) as isize,
);
draw_rect(ctx, rect, Color::from_rgb(0, 0, 32))?;

View file

@ -67,10 +67,10 @@ impl SizedBatch {
}
pub fn add(&mut self, mut x: f32, mut y: f32) {
unsafe {
x = (x * G_MAG).round() / G_MAG;
y = (y * G_MAG).round() / G_MAG;
}
/*unsafe {
x = (x * G_MAG).floor() / G_MAG;
y = (y * G_MAG).floor() / G_MAG;
}*/
let mag = unsafe { I_MAG };
self.batch.add(SpriteBatchCommand::DrawRect(
@ -99,10 +99,10 @@ impl SizedBatch {
return;
}
unsafe {
x = (x * G_MAG).round() / G_MAG;
y = (y * G_MAG).round() / G_MAG;
}
/*unsafe {
x = (x * G_MAG).floor() / G_MAG;
y = (y * G_MAG).floor() / G_MAG;
}*/
let mag = unsafe { I_MAG };
self.batch.add(SpriteBatchCommand::DrawRectFlip(
@ -132,10 +132,10 @@ impl SizedBatch {
return;
}
unsafe {
x = (x * G_MAG).round() / G_MAG;
y = (y * G_MAG).round() / G_MAG;
}
/*unsafe {
x = (x * G_MAG).floor() / G_MAG;
y = (y * G_MAG).floor() / G_MAG;
}*/
let mag = unsafe { I_MAG };
self.batch.add(SpriteBatchCommand::DrawRect(
@ -159,10 +159,10 @@ impl SizedBatch {
return;
}
unsafe {
/*unsafe {
x = (x * G_MAG).floor() / G_MAG;
y = (y * G_MAG).floor() / G_MAG;
}
}*/
let mag = unsafe { I_MAG };
self.batch.add(SpriteBatchCommand::DrawRectTinted(