2020-12-25 22:39:41 +00:00
|
|
|
use crate::common::{fix9_scale, interpolate_fix9_scale};
|
|
|
|
use crate::rng::RNG;
|
2020-09-20 15:27:31 +00:00
|
|
|
use crate::shared_game_state::SharedGameState;
|
2020-09-04 23:08:33 +00:00
|
|
|
use crate::stage::Stage;
|
2020-08-18 16:46:07 +00:00
|
|
|
|
2020-11-01 19:39:57 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
#[repr(u8)]
|
|
|
|
pub enum UpdateTarget {
|
|
|
|
Player,
|
|
|
|
NPC(u16),
|
|
|
|
Boss(u16),
|
|
|
|
}
|
|
|
|
|
2020-08-18 16:46:07 +00:00
|
|
|
pub struct Frame {
|
2021-01-01 01:46:01 +00:00
|
|
|
pub x: i32,
|
|
|
|
pub y: i32,
|
|
|
|
pub prev_x: i32,
|
|
|
|
pub prev_y: i32,
|
2020-11-01 19:39:57 +00:00
|
|
|
pub update_target: UpdateTarget,
|
2021-01-01 01:46:01 +00:00
|
|
|
pub target_x: i32,
|
|
|
|
pub target_y: i32,
|
|
|
|
pub wait: i32,
|
2020-08-18 16:46:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Frame {
|
2022-01-06 01:11:17 +00:00
|
|
|
pub fn new() -> Frame {
|
|
|
|
Frame {
|
|
|
|
x: 0,
|
|
|
|
y: 0,
|
|
|
|
prev_x: 0,
|
|
|
|
prev_y: 0,
|
|
|
|
update_target: UpdateTarget::Player,
|
|
|
|
target_x: 0,
|
|
|
|
target_y: 0,
|
|
|
|
wait: 16,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-05 18:36:21 +00:00
|
|
|
pub fn xy_interpolated(&self, frame_time: f64) -> (f32, f32) {
|
2020-11-07 17:17:01 +00:00
|
|
|
if self.prev_x == self.x && self.prev_y == self.y {
|
2021-05-05 18:36:21 +00:00
|
|
|
return (fix9_scale(self.x), fix9_scale(self.y));
|
2020-11-07 17:17:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let x = interpolate_fix9_scale(self.prev_x, self.x, frame_time);
|
|
|
|
let y = interpolate_fix9_scale(self.prev_y, self.y, frame_time);
|
2020-10-30 22:47:29 +00:00
|
|
|
|
|
|
|
(x, y)
|
|
|
|
}
|
|
|
|
|
2020-11-01 19:39:57 +00:00
|
|
|
pub fn immediate_update(&mut self, state: &mut SharedGameState, stage: &Stage) {
|
2021-10-16 12:59:27 +00:00
|
|
|
let mut screen_width = state.canvas_size.0;
|
2021-10-16 13:26:10 +00:00
|
|
|
if state.constants.is_switch && stage.map.width <= 54 {
|
2021-10-16 12:59:27 +00:00
|
|
|
screen_width += 10.0; // hack for scrolling
|
|
|
|
}
|
|
|
|
|
2021-06-27 01:06:56 +00:00
|
|
|
let tile_size = state.tile_size.as_int();
|
|
|
|
|
2021-10-16 12:59:27 +00:00
|
|
|
if (stage.map.width as usize).saturating_sub(1) * (tile_size as usize) < screen_width as usize {
|
|
|
|
self.x = -(((screen_width as i32 - (stage.map.width as i32 - 1) * tile_size) * 0x200) / 2);
|
2020-09-04 23:08:33 +00:00
|
|
|
} else {
|
2021-10-16 12:59:27 +00:00
|
|
|
self.x = self.target_x - (screen_width as i32 * 0x200 / 2);
|
2020-09-04 23:47:09 +00:00
|
|
|
|
|
|
|
if self.x < 0 {
|
|
|
|
self.x = 0;
|
|
|
|
}
|
|
|
|
|
2021-10-16 12:59:27 +00:00
|
|
|
let max_x = (((stage.map.width as i32 - 1) * tile_size) - screen_width as i32) * 0x200;
|
2020-09-04 23:47:09 +00:00
|
|
|
if self.x > max_x {
|
|
|
|
self.x = max_x;
|
|
|
|
}
|
2020-09-04 23:08:33 +00:00
|
|
|
}
|
|
|
|
|
2021-06-27 01:06:56 +00:00
|
|
|
if (stage.map.height as usize).saturating_sub(1) * (tile_size as usize) < state.canvas_size.1 as usize {
|
|
|
|
self.y = -(((state.canvas_size.1 as i32 - (stage.map.height as i32 - 1) * tile_size) * 0x200) / 2);
|
2020-09-04 23:08:33 +00:00
|
|
|
} else {
|
2021-01-01 01:46:01 +00:00
|
|
|
self.y = self.target_y - (state.canvas_size.1 as i32 * 0x200 / 2);
|
2020-09-04 23:47:09 +00:00
|
|
|
|
|
|
|
if self.y < 0 {
|
|
|
|
self.y = 0;
|
|
|
|
}
|
|
|
|
|
2021-06-27 01:06:56 +00:00
|
|
|
let max_y = (((stage.map.height as i32 - 1) * tile_size) - state.canvas_size.1 as i32) * 0x200;
|
2020-09-04 23:47:09 +00:00
|
|
|
if self.y > max_y {
|
|
|
|
self.y = max_y;
|
|
|
|
}
|
2020-09-04 23:08:33 +00:00
|
|
|
}
|
2020-10-30 22:47:29 +00:00
|
|
|
|
|
|
|
self.prev_x = self.x;
|
|
|
|
self.prev_y = self.y;
|
2020-09-04 23:08:33 +00:00
|
|
|
}
|
|
|
|
|
2020-11-01 19:39:57 +00:00
|
|
|
pub fn update(&mut self, state: &mut SharedGameState, stage: &Stage) {
|
2021-10-16 12:59:27 +00:00
|
|
|
let mut screen_width = state.canvas_size.0;
|
2021-10-16 13:26:10 +00:00
|
|
|
if state.constants.is_switch && stage.map.width <= 54 {
|
2021-10-16 12:59:27 +00:00
|
|
|
screen_width += 10.0;
|
|
|
|
}
|
2021-10-16 13:26:10 +00:00
|
|
|
|
2021-06-27 01:06:56 +00:00
|
|
|
let tile_size = state.tile_size.as_int();
|
|
|
|
|
2021-10-16 12:59:27 +00:00
|
|
|
if (stage.map.width as usize).saturating_sub(1) * (tile_size as usize) < screen_width as usize {
|
|
|
|
self.x = -(((screen_width as i32 - (stage.map.width as i32 - 1) * tile_size) * 0x200) / 2);
|
2020-08-18 16:46:07 +00:00
|
|
|
} else {
|
2021-10-16 12:59:27 +00:00
|
|
|
self.x += (self.target_x - (screen_width as i32 * 0x200 / 2) - self.x) / self.wait;
|
2020-08-18 16:46:07 +00:00
|
|
|
|
|
|
|
if self.x < 0 {
|
|
|
|
self.x = 0;
|
|
|
|
}
|
|
|
|
|
2021-10-16 12:59:27 +00:00
|
|
|
let max_x = (((stage.map.width as i32 - 1) * tile_size) - screen_width as i32) * 0x200;
|
2020-08-18 16:46:07 +00:00
|
|
|
if self.x > max_x {
|
|
|
|
self.x = max_x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-27 01:06:56 +00:00
|
|
|
if (stage.map.height as usize).saturating_sub(1) * (tile_size as usize) < state.canvas_size.1 as usize {
|
|
|
|
self.y = -(((state.canvas_size.1 as i32 - (stage.map.height as i32 - 1) * tile_size) * 0x200) / 2);
|
2020-08-18 16:46:07 +00:00
|
|
|
} else {
|
2021-01-01 01:46:01 +00:00
|
|
|
self.y += (self.target_y - (state.canvas_size.1 as i32 * 0x200 / 2) - self.y) / self.wait;
|
2020-08-18 16:46:07 +00:00
|
|
|
|
|
|
|
if self.y < 0 {
|
|
|
|
self.y = 0;
|
|
|
|
}
|
|
|
|
|
2021-06-27 01:06:56 +00:00
|
|
|
let max_y = (((stage.map.height as i32 - 1) * tile_size) - state.canvas_size.1 as i32) * 0x200;
|
2020-08-18 16:46:07 +00:00
|
|
|
if self.y > max_y {
|
|
|
|
self.y = max_y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-03 12:06:12 +00:00
|
|
|
if state.quake_counter > 0 {
|
|
|
|
state.quake_counter -= 1;
|
|
|
|
|
2021-01-01 01:46:01 +00:00
|
|
|
self.x += state.effect_rng.range(-0x300..0x300) as i32;
|
|
|
|
self.y += state.effect_rng.range(-0x300..0x300) as i32;
|
2020-09-03 12:06:12 +00:00
|
|
|
}
|
2020-08-18 16:46:07 +00:00
|
|
|
}
|
|
|
|
}
|