1
0
Fork 0
mirror of https://github.com/doukutsu-rs/doukutsu-rs synced 2025-07-21 03:31:23 +00:00

death effect, minor tweaks

This commit is contained in:
Alula 2020-11-14 02:24:32 +01:00
parent 7db891f5a1
commit 15f961ad4f
No known key found for this signature in database
GPG key ID: 3E00485503A1D8BA
6 changed files with 39 additions and 27 deletions

View file

@ -6,7 +6,7 @@
A re-implementation of Cave Story (Doukutsu Monogatari) engine written in [Rust](https://www.rust-lang.org/). A re-implementation of Cave Story (Doukutsu Monogatari) engine written in [Rust](https://www.rust-lang.org/).
**The project is still incomplete and might not be playable. Expect lots of breaking changes and bugs** **The project is still incomplete and not fully playable yet.**
[Join the Discord server](https://discord.gg/fbRsNNB) [Join the Discord server](https://discord.gg/fbRsNNB)
@ -14,9 +14,9 @@ A re-implementation of Cave Story (Doukutsu Monogatari) engine written in [Rust]
This repository does not contain any copyrighted files. This repository does not contain any copyrighted files.
For better user experience, binaries are being distributed with slightly modified freeware game files. For better user experience, pre-built binaries are distributed with slightly modified freeware game files.
*doukutsu-rs* should work fine with [CSE2-Enhanced](https://github.com/Clownacy/CSE2) or [NXEngine(-evo)](https://github.com/nxengine/nxengine-evo) modified freeware data files and [Cave Story+](https://www.nicalis.com/games/cavestory+) data files. *doukutsu-rs* should work fine with [CSE2-Enhanced](https://github.com/Clownacy/CSE2) or [NXEngine(-evo)](https://github.com/nxengine/nxengine-evo) freeware data files and [Cave Story+](https://www.nicalis.com/games/cavestory+) data files.
Vanilla Cave Story does not work yet because some important data files have been embedded inside the executable. and we don't have a loader/extractor implemented yet. Vanilla Cave Story does not work yet because some important data files have been embedded inside the executable. and we don't have a loader/extractor implemented yet.
@ -30,12 +30,12 @@ Vanilla Cave Story does not work yet because some important data files have been
**Cave Story+** **Cave Story+**
- PC release - Copy `data` folder from installation directory ([guide for Steam](https://steamcommunity.com/sharedfiles/filedetails/?id=760447682)) to the runtime directory. - PC release - (Tested only with Steam version, both Windows and Linux builds) Copy `data` folder from installation directory ([guide for Steam](https://steamcommunity.com/sharedfiles/filedetails/?id=760447682)) to the runtime directory.
- Switch release - **Not supported or actively tested.** Some of release-specific opcodes have been implemented (no code - Switch release - **Not supported or actively tested.** Some of release-specific opcodes have been implemented (no code
decompilation was involved, just pure data file analysis), so you should be able to play it without any major issues. decompilation was involved, just pure data file analysis), so you should be able to play it without any major issues.
Because methods used to extract game data from cartridge vary, you have to find that out on your own. Because methods used to extract game data from cartridge vary, you have to find that out on your own.
#### Roadmap #### Gameplay support roadmap
- [x] Checkmarked things = fully implemented - [x] Checkmarked things = fully implemented
- [ ] Unmarked things = partially or not implemented yet. - [ ] Unmarked things = partially or not implemented yet.
@ -51,9 +51,9 @@ Because methods used to extract game data from cartridge vary, you have to find
- [x] HUD - [x] HUD
- [ ] Text scripts (TSC) - [ ] Text scripts (TSC)
- [x] Initial implementation - [x] Initial implementation
- [ ] Full implementation of opcodes (~90% done) - [x] Full implementation of gameplay opcodes
- [ ] Credits
- [x] Shift-JIS encoding support - [x] Shift-JIS encoding support
- [ ] Credits opcodes
- [ ] Audio - [ ] Audio
- [x] Organya BGM playback - [x] Organya BGM playback
- [x] Text script bindings - [x] Text script bindings
@ -62,11 +62,11 @@ Because methods used to extract game data from cartridge vary, you have to find
- [ ] NPCs/entities - [ ] NPCs/entities
- [x] Initial implementation - [x] Initial implementation
- [ ] Miscellaneous entities (~30% done) - [ ] Miscellaneous entities (~30% done)
- [ ] Bosses - [ ] Bosses (~20% done)
- [x] First Cave - [x] First Cave
- [x] Mimiga Village - [x] Mimiga Village
- [x] Egg Corridor - [x] Egg Corridor
- [ ] Grasstown (~30% done) - [ ] Grasstown (~90% done)
- [ ] Sand Zone (~10% done) - [ ] Sand Zone (~10% done)
- [ ] Labirynth (~10% done) - [ ] Labirynth (~10% done)
- [ ] Outer Wall - [ ] Outer Wall
@ -75,7 +75,7 @@ Because methods used to extract game data from cartridge vary, you have to find
- [ ] Balcony - [ ] Balcony
- [ ] Hell - [ ] Hell
- [ ] Cave Story+ specific NPCs - [ ] Cave Story+ specific NPCs
- [ ] Dashing Gaudis (361) - [x] Dashing Gaudis (361)
- [ ] ??? (362) - [ ] ??? (362)
- [ ] Weapons - [ ] Weapons
- [x] Leveling / XP system - [x] Leveling / XP system
@ -90,10 +90,6 @@ Because methods used to extract game data from cartridge vary, you have to find
- [ ] Super Missile Launcher - [ ] Super Missile Launcher
- [ ] Nemesis - [ ] Nemesis
- [ ] Spur - [ ] Spur
- [ ] Modding enhancements and built-in tools
- [x] Debugger
- [ ] Level editor
- [ ] Texture auto-reload mode for spriters
- [x] Saving and loading game state - [x] Saving and loading game state
- [ ] Support for different game editions - [ ] Support for different game editions
- [ ] Vanilla - [ ] Vanilla
@ -102,11 +98,10 @@ Because methods used to extract game data from cartridge vary, you have to find
- [x] Base mod - [x] Base mod
- [ ] Mod loading - [ ] Mod loading
- [ ] Curly Story - [ ] Curly Story
- [ ] Wind Fortress - [ ] Wind Fortress (~40%)
- [ ] Boss Run - [ ] Boss Run
- [ ] Seasonal graphics - [x] Seasonal graphics
- [ ] Remastered soundtrack - [ ] Remastered soundtrack
- [x] Optional enhanced graphics effects
*(tbd)* *(tbd)*
@ -120,9 +115,17 @@ Because methods used to extract game data from cartridge vary, you have to find
![CS+ with enhanced graphics](https://i.imgur.com/YaPAs70.png) ![CS+ with enhanced graphics](https://i.imgur.com/YaPAs70.png)
#### Legal note
This project includes reverse engineered implementations of NPC and game physics algorithms, derived from freeware Cave Story and PC Cave Story+ executables.
Since the game's (non-existent, even for CS+) EULA does not prohibit reverse engineering,
[according to Secion 103(f)](https://www.law.cornell.edu/uscode/text/17/1201) we could legally revese engineer those parts
to achieve interoperability.
#### Credits #### Credits
- Studio Pixel for Cave Story - Studio Pixel/Nicalis for Cave Story
- [Cave Story Tribute Site](https://cavestory.org) - for LOTS of useful resources related to the game. - [Cave Story Tribute Site](https://cavestory.org) - has lots of useful resources related to the game.
- [Clownacy/Cucky for CSE2](https://github.com/Clownacy/CSE2) - some game logic reference / mutual help in reverse engineering bitfields and other shit. - [CSE2](https://github.com/Clownacy/CSE2) - widescreen fixes, more readable reference for game logic, mutual help in various things.
- [LunarLambda for organism](https://gitdab.com/LunarLambda/organism) - which is being used by us as `.org` playback engine. - [LunarLambda for organism](https://gitdab.com/LunarLambda/organism) - which is being used by us as `.org` playback engine.

View file

@ -290,8 +290,11 @@ fn lerp_f64(v1: f64, v2: f64, t: f64) -> f64 {
v1 * (1.0 - t.fract()) + v2 * t.fract() v1 * (1.0 - t.fract()) + v2 * t.fract()
} }
#[inline(always)]
pub fn interpolate_fix9_scale(old_val: isize, val: isize, frame_delta: f64) -> f32 { pub fn interpolate_fix9_scale(old_val: isize, val: isize, frame_delta: f64) -> f32 {
if (frame_delta - 1.0).abs() < 0.001 {
return (val / 0x200) as f32;
}
(lerp_f64(old_val as f64, val as f64, frame_delta) / 512.0) as f32 (lerp_f64(old_val as f64, val as f64, frame_delta) / 512.0) as f32
//((lerp_f64(old_val as f64, val as f64, frame_delta) * scale as f64 / 512.0).floor() / (scale as f64)) as f32 //((lerp_f64(old_val as f64, val as f64, frame_delta) * scale as f64 / 512.0).floor() / (scale as f64)) as f32
} }

View file

@ -174,7 +174,7 @@ impl Game {
KeyCode::S => { state.key_state.set_weapon_next(true) } KeyCode::S => { state.key_state.set_weapon_next(true) }
KeyCode::F7 => { state.set_speed(1.0) } KeyCode::F7 => { state.set_speed(1.0) }
KeyCode::F8 => { KeyCode::F8 => {
if state.settings.speed > 0.5 { if state.settings.speed > 0.2 {
state.set_speed(state.settings.speed - 0.1); state.set_speed(state.settings.speed - 0.1);
} }
} }

View file

@ -113,7 +113,7 @@ impl NPC {
} }
10 | 11 => { 10 | 11 => {
if self.action_num == 10 { if self.action_num == 10 {
self.action_num = 1; self.action_num = 11;
self.action_counter = 0; self.action_counter = 0;
self.anim_num = 0; self.anim_num = 0;
self.vel_y = 0x200; self.vel_y = 0x200;

View file

@ -168,8 +168,6 @@ impl Player {
self.booster_switch = 0; self.booster_switch = 0;
} }
// todo: split those into separate procedures and refactor (try to not break the logic!)
// ground movement // ground movement
if self.flags.hit_bottom_wall() || self.flags.hit_right_slope() || self.flags.hit_left_slope() { if self.flags.hit_bottom_wall() || self.flags.hit_right_slope() || self.flags.hit_left_slope() {
self.booster_switch = 0; self.booster_switch = 0;
@ -608,6 +606,16 @@ impl Player {
state.control_flags.set_tick_world(true); state.control_flags.set_tick_world(true);
state.control_flags.set_interactions_disabled(true); state.control_flags.set_interactions_disabled(true);
state.textscript_vm.start_script(40); state.textscript_vm.start_script(40);
state.create_caret(self.x, self.y, CaretType::Explosion, Direction::Left);
let mut npc = NPCMap::create_npc(4, &state.npc_table);
npc.cond.set_alive(true);
for _ in 0..0x40 {
npc.x = self.x + state.game_rng.range(-10..10) as isize * 0x200;
npc.y = self.y + state.game_rng.range(-10..10) as isize * 0x200;
state.new_npcs.push(npc);
}
} }
} }
} }

View file

@ -323,7 +323,6 @@ impl GameScene {
fn draw_bullets(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { fn draw_bullets(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "Bullet")?; let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "Bullet")?;
let scale = state.scale;
let mut x: isize; let mut x: isize;
let mut y: isize; let mut y: isize;
let mut prev_x: isize; let mut prev_x: isize;
@ -373,7 +372,6 @@ impl GameScene {
fn draw_carets(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { fn draw_carets(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "Caret")?; let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "Caret")?;
let scale = state.scale;
for caret in state.carets.iter() { for caret in state.carets.iter() {
batch.add_rect(interpolate_fix9_scale(caret.prev_x - caret.offset_x - self.frame.prev_x, batch.add_rect(interpolate_fix9_scale(caret.prev_x - caret.offset_x - self.frame.prev_x,