mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-12-01 08:37:23 +00:00
various lighting improvements
This commit is contained in:
parent
8a94f7f9d1
commit
55afe1292f
|
|
@ -8,6 +8,8 @@ use crate::framework::graphics;
|
|||
use crate::map::WaterRegionType;
|
||||
use crate::player::Player;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::physics::PhysicalEntity;
|
||||
use crate::npc::list::NPCList;
|
||||
|
||||
const TENSION: f32 = 0.03;
|
||||
const DAMPENING: f32 = 0.01;
|
||||
|
|
@ -115,30 +117,50 @@ impl WaterRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
impl GameEntity<&Player> for WaterRenderer {
|
||||
fn tick(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult<()> {
|
||||
let player_x = player.x as f32 / 512.0 + 8.0;
|
||||
let player_y = player.y as f32 / 512.0 + 8.0;
|
||||
impl GameEntity<(&[&Player], &NPCList)> for WaterRenderer {
|
||||
fn tick(&mut self, state: &mut SharedGameState, (players, npc_list): (&[&Player], &NPCList)) -> GameResult<()> {
|
||||
if !state.settings.shader_effects {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
for surf in self.water_surfaces.iter_mut() {
|
||||
let line_x = surf.x as f32 * 16.0;
|
||||
let line_y = surf.y as f32 * 16.0;
|
||||
if (player.vel_y > 0x80 || player.vel_y < -0x80)
|
||||
&& player_x > line_x
|
||||
&& player_x < surf.end_x as f32 * 16.0
|
||||
&& player_y > line_y - 5.0
|
||||
&& player_y < line_y + 4.0
|
||||
|
||||
let mut tick_object = |obj: &dyn PhysicalEntity| {
|
||||
let obj_x = obj.x() as f32 / 512.0 + 8.0;
|
||||
let obj_y = obj.y() as f32 / 512.0 + 8.0;
|
||||
|
||||
if (obj.vel_y() > 0x80 || obj.vel_y() < -0x80)
|
||||
&& obj_x > line_x
|
||||
&& obj_x < surf.end_x as f32 * 16.0
|
||||
&& obj_y > line_y - 5.0
|
||||
&& obj_y < line_y + 4.0
|
||||
{
|
||||
let col_idx_center = (((player_x - line_x) / 2.0) as i32).clamp(0, surf.columns.len() as i32);
|
||||
let col_idx_left = (col_idx_center - (player.hit_bounds.left as i32 / (8 * 0x200)))
|
||||
let col_idx_center = (((obj_x - line_x) / 2.0) as i32).clamp(0, surf.columns.len() as i32);
|
||||
let col_idx_left = (col_idx_center - (obj.hit_bounds().left as i32 / (8 * 0x200)))
|
||||
.clamp(0, surf.columns.len() as i32) as usize;
|
||||
let col_idx_right = (col_idx_center + (player.hit_bounds.left as i32 / (8 * 0x200)))
|
||||
let col_idx_right = (col_idx_center + (obj.hit_bounds().left as i32 / (8 * 0x200)))
|
||||
.clamp(0, surf.columns.len() as i32) as usize;
|
||||
|
||||
for col in surf.columns[col_idx_left..=col_idx_right].iter_mut() {
|
||||
col.speed = player.vel_y as f32 / 512.0;
|
||||
col.speed = (obj.vel_y() as f32 / 512.0) * (obj.hit_rect_size() as f32 * 0.25).clamp(0.1, 1.0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for player in players {
|
||||
tick_object(*player);
|
||||
}
|
||||
|
||||
for npc in npc_list.iter_alive() {
|
||||
static NO_COLL_NPCS: [u16; 3] = [0, 3, 4];
|
||||
if NO_COLL_NPCS.contains(&npc.npc_type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tick_object(npc);
|
||||
}
|
||||
|
||||
surf.tick();
|
||||
}
|
||||
|
|
@ -160,7 +182,7 @@ impl GameEntity<&Player> for WaterRenderer {
|
|||
graphics::draw_rect(ctx, out_rect, water_color)?;
|
||||
}
|
||||
|
||||
if !graphics::supports_vertex_draw(ctx)? {
|
||||
if !state.settings.shader_effects || !graphics::supports_vertex_draw(ctx)? {
|
||||
for region in self.surf_regions.iter() {
|
||||
out_rect.left = ((region.left as f32 * 16.0 - o_x - 8.0) * state.scale) as isize;
|
||||
out_rect.top = ((region.top as f32 * 16.0 - o_y - 5.0) * state.scale) as isize;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use case_insensitive_hashmap::CaseInsensitiveHashMap;
|
||||
use log::info;
|
||||
|
||||
use crate::case_insensitive_hashmap;
|
||||
use crate::common::{BulletFlag, Color, Rect};
|
||||
|
|
@ -80,6 +79,12 @@ pub struct CaretConsts {
|
|||
pub question_right_rect: Rect<u16>,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct TextureSizeTable {
|
||||
r#override: bool,
|
||||
sizes: HashMap<String, (u16, u16)>,
|
||||
}
|
||||
|
||||
impl Clone for CaretConsts {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
|
|
@ -1487,7 +1492,7 @@ impl EngineConstants {
|
|||
}
|
||||
|
||||
pub fn apply_csplus_patches(&mut self, sound_manager: &SoundManager) {
|
||||
info!("Applying Cave Story+ constants patches...");
|
||||
log::info!("Applying Cave Story+ constants patches...");
|
||||
|
||||
self.is_cs_plus = true;
|
||||
self.supports_og_textures = true;
|
||||
|
|
@ -1530,7 +1535,7 @@ impl EngineConstants {
|
|||
}
|
||||
|
||||
pub fn apply_csplus_nx_patches(&mut self) {
|
||||
info!("Applying Switch-specific Cave Story+ constants patches...");
|
||||
log::info!("Applying Switch-specific Cave Story+ constants patches...");
|
||||
|
||||
self.is_switch = true;
|
||||
self.supports_og_textures = true;
|
||||
|
|
@ -1547,4 +1552,8 @@ impl EngineConstants {
|
|||
self.soundtracks.insert("Famitracks".to_string(), "/base/ogg17/".to_string());
|
||||
self.soundtracks.insert("Ridiculon".to_string(), "/base/ogg_ridic/".to_string());
|
||||
}
|
||||
|
||||
pub fn apply_constant_json_files(&mut self) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use num_traits::{abs, clamp};
|
||||
|
||||
use crate::caret::CaretType;
|
||||
use crate::common::{CDEG_RAD, Direction};
|
||||
use crate::common::{Direction, CDEG_RAD};
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::npc::list::NPCList;
|
||||
use crate::npc::NPC;
|
||||
|
|
@ -1038,7 +1038,6 @@ impl NPC {
|
|||
self.y += self.vel_y;
|
||||
self.x += self.vel_x;
|
||||
|
||||
|
||||
let dir_offset = if self.direction == Direction::Left { 0 } else { 10 };
|
||||
|
||||
self.anim_rect = state.constants.npc.n122_colon_enraged[self.anim_num as usize + dir_offset];
|
||||
|
|
@ -1483,13 +1482,13 @@ impl NPC {
|
|||
self.anim_counter = 0;
|
||||
self.anim_num += 1;
|
||||
}
|
||||
if (self.anim_num > 1) {
|
||||
if self.anim_num > 1 {
|
||||
self.anim_num = 0;
|
||||
}
|
||||
if (self.direction == Direction::Left && self.flags.hit_left_wall()) {
|
||||
if self.direction == Direction::Left && self.flags.hit_left_wall() {
|
||||
self.direction = Direction::Right;
|
||||
}
|
||||
if (self.direction == Direction::Right && self.flags.hit_right_wall()) {
|
||||
if self.direction == Direction::Right && self.flags.hit_right_wall() {
|
||||
self.direction = Direction::Left;
|
||||
}
|
||||
self.x += self.direction.vector_x() * 0x100;
|
||||
|
|
|
|||
|
|
@ -690,12 +690,12 @@ impl GameScene {
|
|||
let d = deg as f32 * (std::f32::consts::PI / 180.0);
|
||||
let dx = d.cos() * -5.0;
|
||||
let dy = d.sin() * -5.0;
|
||||
let m = 1.0 - ((ahalf - i as f32).abs() / ahalf) * 0.3;
|
||||
let m = 1.0 - ((ahalf - i as f32).abs() / ahalf);
|
||||
let mut x = px;
|
||||
let mut y = py;
|
||||
let mut r = br * m;
|
||||
let mut g = bg * m;
|
||||
let mut b = bb * m;
|
||||
let mut r = br;
|
||||
let mut g = bg;
|
||||
let mut b = bb;
|
||||
|
||||
for i in 0..40 {
|
||||
x += dx;
|
||||
|
|
@ -762,15 +762,21 @@ impl GameScene {
|
|||
}
|
||||
}
|
||||
|
||||
r -= att;
|
||||
g -= att;
|
||||
b -= att;
|
||||
r *= att;
|
||||
g *= att;
|
||||
b *= att;
|
||||
|
||||
if r <= 0.0 && g <= 0.0 && b <= 0.0 {
|
||||
if r <= 1.0 && g <= 1.0 && b <= 1.0 {
|
||||
continue 'ray;
|
||||
}
|
||||
|
||||
self.draw_light(x - fx2, y - fy2, 0.12 + i as f32 / 75.0, (r as u8, g as u8, b as u8), batch);
|
||||
self.draw_light(
|
||||
x - fx2,
|
||||
y - fy2,
|
||||
0.15 + i as f32 / 75.0,
|
||||
((r * m) as u8, (g * m) as u8, (b * m) as u8),
|
||||
batch,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -803,10 +809,11 @@ impl GameScene {
|
|||
};
|
||||
|
||||
let (color, att) = match inv.get_current_weapon() {
|
||||
Some(Weapon { wtype: WeaponType::Fireball, .. }) => ((200u8, 90u8, 10u8), 4.0),
|
||||
Some(Weapon { wtype: WeaponType::Spur, .. }) => ((170u8, 170u8, 200u8), 6.0),
|
||||
Some(Weapon { wtype: WeaponType::Fireball, .. }) => ((170u8, 80u8, 0u8), 0.92),
|
||||
Some(Weapon { wtype: WeaponType::PolarStar, .. }) => ((150u8, 150u8, 160u8), 0.92),
|
||||
Some(Weapon { wtype: WeaponType::Spur, .. }) => ((170u8, 170u8, 200u8), 0.92),
|
||||
Some(Weapon { wtype: WeaponType::Blade, .. }) => continue 'cc,
|
||||
_ => ((100u8, 100u8, 100u8), 4.0),
|
||||
_ => ((150u8, 150u8, 150u8), 0.92),
|
||||
};
|
||||
|
||||
let (_, gun_off_y) = player.skin.get_gun_offset();
|
||||
|
|
@ -1004,7 +1011,7 @@ impl GameScene {
|
|||
);
|
||||
}
|
||||
38 => {
|
||||
let flicker = ((npc.anim_num.wrapping_add(npc.id) ^ 5) & 3) as u8 * 15;
|
||||
let flicker = ((npc.anim_num.wrapping_add(npc.id) ^ 5) & 3) as u8 * 24;
|
||||
self.draw_light(
|
||||
interpolate_fix9_scale(
|
||||
npc.prev_x - self.frame.prev_x,
|
||||
|
|
@ -1021,6 +1028,23 @@ impl GameScene {
|
|||
batch,
|
||||
);
|
||||
}
|
||||
69 | 81 => {
|
||||
self.draw_light(
|
||||
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,
|
||||
),
|
||||
if npc.npc_type == 69 { 0.5 } else { 1.0 },
|
||||
(200, 200, 200),
|
||||
batch,
|
||||
);
|
||||
}
|
||||
70 => {
|
||||
let flicker = 50 + npc.anim_num as u8 * 15;
|
||||
self.draw_light(
|
||||
|
|
@ -1039,13 +1063,6 @@ impl GameScene {
|
|||
batch,
|
||||
);
|
||||
}
|
||||
75 | 77 => self.draw_light(
|
||||
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,
|
||||
),
|
||||
85 if npc.action_num == 1 => {
|
||||
let (color, color2) = if npc.direction == Direction::Left {
|
||||
if state.constants.is_cs_plus {
|
||||
|
|
@ -1091,6 +1108,23 @@ impl GameScene {
|
|||
);
|
||||
}
|
||||
}
|
||||
175 if npc.action_num < 10 => {
|
||||
self.draw_light(
|
||||
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,
|
||||
(128, 175, 200),
|
||||
batch,
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -1115,7 +1149,7 @@ impl GameScene {
|
|||
right: (state.screen_size.0 + 1.0) as isize,
|
||||
bottom: (state.screen_size.1 + 1.0) as isize,
|
||||
},
|
||||
Color { r: 0.15, g: 0.15, b: 0.15, a: 1.0 },
|
||||
Color { r: 0.15, g: 0.12, b: 0.12, a: 1.0 },
|
||||
)?;
|
||||
graphics::set_render_target(ctx, None)?;
|
||||
graphics::set_blend_mode(ctx, BlendMode::Add)?;
|
||||
|
|
@ -1584,7 +1618,7 @@ impl GameScene {
|
|||
}
|
||||
}
|
||||
|
||||
self.water_renderer.tick(state, &self.player1)?;
|
||||
self.water_renderer.tick(state, (&[&self.player1, &self.player2], &self.npc_list))?;
|
||||
|
||||
if self.map_name_counter > 0 {
|
||||
self.map_name_counter -= 1;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use itertools::Itertools;
|
|||
use log::info;
|
||||
|
||||
use crate::common;
|
||||
use crate::common::{FILE_TYPES, Rect};
|
||||
use crate::common::{Rect, FILE_TYPES};
|
||||
use crate::engine_constants::EngineConstants;
|
||||
use crate::framework::backend::{BackendTexture, SpriteBatchCommand};
|
||||
use crate::framework::context::Context;
|
||||
|
|
@ -28,6 +28,8 @@ pub struct SizedBatch {
|
|||
real_height: usize,
|
||||
scale_x: f32,
|
||||
scale_y: f32,
|
||||
has_glow_layer: bool,
|
||||
has_normal_layer: bool,
|
||||
}
|
||||
|
||||
impl SizedBatch {
|
||||
|
|
@ -56,6 +58,16 @@ impl SizedBatch {
|
|||
(self.scale_x, self.scale_y)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn has_glow_layer(&self) -> bool {
|
||||
self.has_glow_layer
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn has_normal_layer(&self) -> bool {
|
||||
self.has_normal_layer
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn to_rect(&self) -> common::Rect<usize> {
|
||||
common::Rect::<usize>::new(0, 0, self.width, self.height)
|
||||
|
|
@ -74,12 +86,7 @@ impl SizedBatch {
|
|||
let mag = unsafe { I_MAG };
|
||||
|
||||
self.batch.add(SpriteBatchCommand::DrawRect(
|
||||
Rect {
|
||||
left: 0 as f32,
|
||||
top: 0 as f32,
|
||||
right: self.real_width as f32,
|
||||
bottom: self.real_height as f32,
|
||||
},
|
||||
Rect { left: 0 as f32, top: 0 as f32, right: self.real_width as f32, bottom: self.real_height as f32 },
|
||||
Rect {
|
||||
left: x * mag,
|
||||
top: y * mag,
|
||||
|
|
@ -99,10 +106,6 @@ impl SizedBatch {
|
|||
return;
|
||||
}
|
||||
|
||||
/*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(
|
||||
|
|
@ -118,7 +121,8 @@ impl SizedBatch {
|
|||
right: (x + rect.width() as f32) * mag,
|
||||
bottom: (y + rect.height() as f32) * mag,
|
||||
},
|
||||
flip_x, flip_y
|
||||
flip_x,
|
||||
flip_y,
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -154,7 +158,15 @@ impl SizedBatch {
|
|||
));
|
||||
}
|
||||
|
||||
pub fn add_rect_scaled_tinted(&mut self, mut x: f32, mut y: f32, color: (u8, u8, u8, u8), scale_x: f32, scale_y: f32, rect: &common::Rect<u16>) {
|
||||
pub fn add_rect_scaled_tinted(
|
||||
&mut self,
|
||||
mut x: f32,
|
||||
mut y: f32,
|
||||
color: (u8, u8, u8, u8),
|
||||
scale_x: f32,
|
||||
scale_y: f32,
|
||||
rect: &common::Rect<u16>,
|
||||
) {
|
||||
if (rect.right - rect.left) == 0 || (rect.bottom - rect.top) == 0 {
|
||||
return;
|
||||
}
|
||||
|
|
@ -166,12 +178,7 @@ impl SizedBatch {
|
|||
let mag = unsafe { I_MAG };
|
||||
|
||||
self.batch.add(SpriteBatchCommand::DrawRectTinted(
|
||||
Rect {
|
||||
left: rect.left as f32,
|
||||
top: rect.top as f32,
|
||||
right: rect.right as f32,
|
||||
bottom: rect.bottom as f32,
|
||||
},
|
||||
Rect { left: rect.left as f32, top: rect.top as f32, right: rect.right as f32, bottom: rect.bottom as f32 },
|
||||
Rect {
|
||||
left: x * mag,
|
||||
top: y * mag,
|
||||
|
|
@ -202,10 +209,7 @@ pub struct TextureSet {
|
|||
|
||||
impl TextureSet {
|
||||
pub fn new(base_path: &str) -> TextureSet {
|
||||
TextureSet {
|
||||
tex_map: HashMap::new(),
|
||||
paths: vec![base_path.to_string(), "".to_string()],
|
||||
}
|
||||
TextureSet { tex_map: HashMap::new(), paths: vec![base_path.to_string(), "".to_string()] }
|
||||
}
|
||||
|
||||
pub fn apply_seasonal_content(&mut self, season: Season, settings: &Settings) {
|
||||
|
|
@ -248,14 +252,26 @@ impl TextureSet {
|
|||
}
|
||||
|
||||
pub fn load_texture(&self, ctx: &mut Context, constants: &EngineConstants, name: &str) -> GameResult<SizedBatch> {
|
||||
let path = self.paths.iter().find_map(|s| FILE_TYPES
|
||||
let path = self
|
||||
.paths
|
||||
.iter()
|
||||
.map(|ext| [s, name, ext].join(""))
|
||||
.find(|path| {
|
||||
.find_map(|s| {
|
||||
FILE_TYPES.iter().map(|ext| [s, name, ext].join("")).find(|path| {
|
||||
println!("{}", path);
|
||||
filesystem::exists(ctx, path)
|
||||
})
|
||||
).ok_or_else(|| GameError::ResourceLoadError(format!("Texture {} does not exist.", name)))?;
|
||||
})
|
||||
.ok_or_else(|| GameError::ResourceLoadError(format!("Texture {} does not exist.", name)))?;
|
||||
|
||||
let has_glow_layer = self
|
||||
.paths
|
||||
.iter()
|
||||
.find_map(|s| {
|
||||
FILE_TYPES.iter().map(|ext| [s, name, ".glow", ext].join("")).find(|path| {
|
||||
println!("{}", path);
|
||||
filesystem::exists(ctx, path)
|
||||
})
|
||||
}).is_some();
|
||||
|
||||
info!("Loading texture: {}", path);
|
||||
|
||||
|
|
@ -278,10 +294,17 @@ impl TextureSet {
|
|||
scale_y: scale,
|
||||
real_width: size.0 as usize,
|
||||
real_height: size.1 as usize,
|
||||
has_glow_layer,
|
||||
has_normal_layer: false,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_or_load_batch(&mut self, ctx: &mut Context, constants: &EngineConstants, name: &str) -> GameResult<&mut SizedBatch> {
|
||||
pub fn get_or_load_batch(
|
||||
&mut self,
|
||||
ctx: &mut Context,
|
||||
constants: &EngineConstants,
|
||||
name: &str,
|
||||
) -> GameResult<&mut SizedBatch> {
|
||||
if !self.tex_map.contains_key(name) {
|
||||
let batch = self.load_texture(ctx, constants, name)?;
|
||||
self.tex_map.insert(str!(name), batch);
|
||||
|
|
|
|||
Loading…
Reference in a new issue