1
0
Fork 0
mirror of https://github.com/doukutsu-rs/doukutsu-rs synced 2025-12-04 02:47:50 +00:00

add moving blocks

This commit is contained in:
Alula 2020-10-03 01:53:32 +02:00
parent 705a47d61c
commit 46142a0efe
No known key found for this signature in database
GPG key ID: 3E00485503A1D8BA
4 changed files with 308 additions and 66 deletions

View file

@ -206,6 +206,8 @@ pub struct NPCConsts {
pub n078_pot: [Rect<usize>; 2],
pub n079_mahin: [Rect<usize>; 6],
pub n129_fireball_snake_trail: [Rect<usize>; 18],
pub n149_horizontal_moving_block: Rect<usize>,
pub n157_vertical_moving_block: Rect<usize>,
pub n211_small_spikes: [Rect<usize>; 4],
}
@ -993,27 +995,24 @@ impl EngineConstants {
Rect { left: 128, top: 48, right: 144, bottom: 64 },
Rect { left: 144, top: 48, right: 160, bottom: 64 },
Rect { left: 160, top: 48, right: 176, bottom: 64 },
Rect { left: 128, top: 64, right: 144, bottom: 80 },
Rect { left: 144, top: 64, right: 160, bottom: 80 },
Rect { left: 160, top: 64, right: 176, bottom: 80 },
Rect { left: 128, top: 80, right: 144, bottom: 96 },
Rect { left: 144, top: 80, right: 160, bottom: 96 },
Rect { left: 160, top: 80, right: 176, bottom: 96 },
Rect { left: 176, top: 48, right: 192, bottom: 64 },
Rect { left: 192, top: 48, right: 208, bottom: 64 },
Rect { left: 208, top: 48, right: 224, bottom: 64 },
Rect { left: 176, top: 64, right: 192, bottom: 80 },
Rect { left: 192, top: 64, right: 208, bottom: 80 },
Rect { left: 208, top: 64, right: 224, bottom: 80 },
Rect { left: 176, top: 80, right: 192, bottom: 96 },
Rect { left: 192, top: 80, right: 208, bottom: 96 },
Rect { left: 208, top: 80, right: 224, bottom: 96 },
],
n149_horizontal_moving_block: Rect { left: 16, top: 0, right: 48, bottom: 32 },
n157_vertical_moving_block: Rect { left: 16, top: 0, right: 48, bottom: 32 },
n211_small_spikes: [
Rect { left: 256, top: 200, right: 272, bottom: 216 },
Rect { left: 272, top: 200, right: 288, bottom: 216 },

5
src/npc/maze.rs Normal file
View file

@ -0,0 +1,5 @@
use crate::npc::NPC;
impl NPC {
}

View file

@ -7,6 +7,7 @@ use crate::npc::{NPC, NPCMap};
use crate::player::Player;
use crate::shared_game_state::SharedGameState;
use crate::stage::Stage;
use num_traits::clamp;
impl NPC {
pub(crate) fn tick_n000_null(&mut self) -> GameResult {
@ -621,6 +622,240 @@ impl NPC {
Ok(())
}
pub(crate) fn tick_n149_horizontal_moving_block(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult {
match self.action_num {
0 => {
self.x += 8 * 0x200;
self.y += 8 * 0x200;
self.npc_flags.set_solid_hard(true);
self.vel_x = 0;
self.vel_y = 0;
self.action_num = if self.direction == Direction::Right { 20 } else { 10 };
}
10 => {
self.npc_flags.set_rear_and_top_not_hurt(false);
self.damage = 0;
if (player.x < self.x + 25 * 0x200) && (player.x > self.x - 25 * 16 * 0x200)
&& (player.y < self.y + 25 * 0x200) && (player.y > self.y - 25 * 0x200) {
self.action_num = 11;
self.action_counter = 0;
}
}
11 => {
self.action_counter += 1;
if self.action_counter % 10 == 6 {
state.sound_manager.play_sfx(107);
}
if self.flags.hit_left_wall() {
self.vel_x = 0;
self.direction = Direction::Right;
self.action_num = 20;
state.quake_counter = 10;
state.sound_manager.play_sfx(26);
let mut npc = NPCMap::create_npc(4, &state.npc_table);
for _ in 0..3 {
npc.cond.set_alive(true);
npc.direction = Direction::Left;
npc.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
npc.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
state.new_npcs.push(npc);
}
} else {
if player.flags.hit_left_wall() {
self.npc_flags.set_rear_and_top_not_hurt(true);
self.damage = 100;
} else {
self.npc_flags.set_rear_and_top_not_hurt(false);
self.damage = 0;
}
self.vel_x -= 0x20;
}
}
20 => {
self.npc_flags.set_rear_and_top_not_hurt(false);
self.damage = 0;
if (player.x > self.x - 25 * 0x200) && (player.x < self.x + 25 * 16 * 0x200)
&& (player.y < self.y + 25 * 0x200) && (player.y > self.y - 25 * 0x200) {
self.action_num = 21;
self.action_counter = 0;
}
}
21 => {
self.action_counter += 1;
if self.action_counter % 10 == 6 {
state.sound_manager.play_sfx(107);
}
if self.flags.hit_right_wall() {
self.vel_x = 0;
self.direction = Direction::Left;
self.action_num = 10;
state.quake_counter = 10;
state.sound_manager.play_sfx(26);
let mut npc = NPCMap::create_npc(4, &state.npc_table);
for _ in 0..3 {
npc.cond.set_alive(true);
npc.direction = Direction::Left;
npc.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
npc.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
state.new_npcs.push(npc);
}
} else {
if player.flags.hit_right_wall() {
self.npc_flags.set_rear_and_top_not_hurt(true);
self.damage = 100;
} else {
self.npc_flags.set_rear_and_top_not_hurt(false);
self.damage = 0;
}
self.vel_x += 0x20;
}
}
_ => {}
}
self.vel_x = clamp(self.vel_x, -0x200, 0x200);
self.x += self.vel_x;
if self.anim_num != 149 {
self.anim_num = 149;
self.anim_rect = state.constants.npc.n149_horizontal_moving_block;
}
Ok(())
}
pub(crate) fn tick_n157_vertical_moving_block(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult {
match self.action_num {
0 => {
self.x += 8 * 0x200;
self.y += 8 * 0x200;
self.npc_flags.set_solid_hard(true);
self.vel_x = 0;
self.vel_y = 0;
self.action_num = if self.direction == Direction::Right { 20 } else { 10 };
}
10 => {
self.npc_flags.set_rear_and_top_not_hurt(false);
self.damage = 0;
if (player.y < self.y + 25 * 0x200) && (player.y > self.y - 25 * 16 * 0x200)
&& (player.x < self.x + 25 * 0x200) && (player.x > self.x - 25 * 0x200) {
self.action_num = 11;
self.action_counter = 0;
}
}
11 => {
self.action_counter += 1;
if self.action_counter % 10 == 6 {
state.sound_manager.play_sfx(107);
}
if self.flags.hit_top_wall() {
self.vel_y = 0;
self.direction = Direction::Right;
self.action_num = 20;
state.quake_counter = 10;
state.sound_manager.play_sfx(26);
let mut npc = NPCMap::create_npc(4, &state.npc_table);
for _ in 0..3 {
npc.cond.set_alive(true);
npc.direction = Direction::Left;
npc.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
npc.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
state.new_npcs.push(npc);
}
} else {
if player.flags.hit_top_wall() {
self.npc_flags.set_rear_and_top_not_hurt(true);
self.damage = 100;
} else {
self.npc_flags.set_rear_and_top_not_hurt(false);
self.damage = 0;
}
self.vel_y -= 0x20;
}
}
20 => {
self.npc_flags.set_rear_and_top_not_hurt(false);
self.damage = 0;
if (player.y > self.y - 25 * 0x200) && (player.y < self.y + 25 * 16 * 0x200)
&& (player.x < self.x + 25 * 0x200) && (player.x > self.x - 25 * 0x200) {
self.action_num = 21;
self.action_counter = 0;
}
}
21 => {
self.action_counter += 1;
if self.action_counter % 10 == 6 {
state.sound_manager.play_sfx(107);
}
if self.flags.hit_bottom_wall() {
self.vel_x = 0;
self.direction = Direction::Left;
self.action_num = 10;
state.quake_counter = 10;
state.sound_manager.play_sfx(26);
let mut npc = NPCMap::create_npc(4, &state.npc_table);
for _ in 0..3 {
npc.cond.set_alive(true);
npc.direction = Direction::Left;
npc.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
npc.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
state.new_npcs.push(npc);
}
} else {
if player.flags.hit_bottom_wall() {
self.npc_flags.set_rear_and_top_not_hurt(true);
self.damage = 100;
} else {
self.npc_flags.set_rear_and_top_not_hurt(false);
self.damage = 0;
}
self.vel_y += 0x20;
}
}
_ => {}
}
self.vel_y = clamp(self.vel_y, -0x200, 0x200);
self.y += self.vel_y;
if self.anim_num != 149 {
self.anim_num = 149;
self.anim_rect = state.constants.npc.n149_horizontal_moving_block;
}
Ok(())
}
pub(crate) fn tick_n211_small_spikes(&mut self, state: &mut SharedGameState) -> GameResult {
if self.action_num == 0 {
self.action_num = 1;

View file

@ -16,12 +16,12 @@ use crate::entity::GameEntity;
use crate::frame::Frame;
use crate::ggez::{Context, GameResult};
use crate::map::NPCData;
use crate::npc::boss::BossNPCMap;
use crate::physics::PhysicalEntity;
use crate::player::Player;
use crate::shared_game_state::SharedGameState;
use crate::stage::Stage;
use crate::str;
use crate::npc::boss::BossNPCMap;
pub mod balrog;
pub mod boss;
@ -29,6 +29,7 @@ pub mod characters;
pub mod egg_corridor;
pub mod first_cave;
pub mod grasstown;
pub mod maze;
pub mod mimiga_village;
pub mod misc;
pub mod misery;
@ -102,7 +103,7 @@ impl NPC {
0
}
}
pub fn empty() -> NPC {
NPC {
id: 0,
@ -140,65 +141,67 @@ impl NPC {
impl GameEntity<(&mut Player, &HashMap<u16, RefCell<NPC>>, &mut Stage)> for NPC {
fn tick(&mut self, state: &mut SharedGameState, (player, map, stage): (&mut Player, &HashMap<u16, RefCell<NPC>>, &mut Stage)) -> GameResult {
match self.npc_type {
0 => { self.tick_n000_null() }
1 => { self.tick_n001_experience(state) }
2 => { self.tick_n002_behemoth(state) }
3 => { self.tick_n003_dead_enemy() }
4 => { self.tick_n004_smoke(state) }
5 => { self.tick_n005_green_critter(state, player) }
6 => { self.tick_n006_green_beetle(state) }
7 => { self.tick_n007_basil(state, player) }
8 => { self.tick_n008_blue_beetle(state, player) }
9 => { self.tick_n009_balrog_falling_in(state) }
10 => { self.tick_n010_balrog_shooting(state, player) }
11 => { self.tick_n011_balrogs_projectile(state) }
12 => { self.tick_n012_balrog_cutscene(state, player, map, stage) }
13 => { self.tick_n013_forcefield(state) }
14 => { self.tick_n014_key(state) }
15 => { self.tick_n015_chest_closed(state) }
16 => { self.tick_n016_save_point(state) }
17 => { self.tick_n017_health_refill(state) }
18 => { self.tick_n018_door(state) }
19 => { self.tick_n019_balrog_bust_in(state) }
20 => { self.tick_n020_computer(state) }
21 => { self.tick_n021_chest_open(state) }
22 => { self.tick_n022_teleporter(state) }
27 => { self.tick_n027_death_trap(state) }
30 => { self.tick_n030_gunsmith(state) }
32 => { self.tick_n032_life_capsule(state) }
34 => { self.tick_n034_bed(state) }
37 => { self.tick_n037_sign(state) }
38 => { self.tick_n038_fireplace(state) }
39 => { self.tick_n039_save_sign(state) }
41 => { self.tick_n041_busted_door(state) }
43 => { self.tick_n043_chalkboard(state) }
46 => { self.tick_n046_hv_trigger(state, player) }
52 => { self.tick_n052_sitting_blue_robot(state) }
55 => { self.tick_n055_kazuma(state) }
59 => { self.tick_n059_eye_door(state, player) }
60 => { self.tick_n060_toroko(state, player) }
61 => { self.tick_n061_king(state) }
62 => { self.tick_n062_kazuma_computer(state) }
63 => { self.tick_n063_toroko_stick(state) }
64 => { self.tick_n064_first_cave_critter(state, player) }
65 => { self.tick_n065_first_cave_bat(state, player) }
66 => { self.tick_n066_misery_bubble(state, map) }
67 => { self.tick_n067_misery_floating(state) }
68 => { self.tick_n068_balrog_running(state, player) }
69 => { self.tick_n069_pignon(state) }
70 => { self.tick_n070_sparkle(state) }
71 => { self.tick_n071_chinfish(state) }
72 => { self.tick_n072_sprinkler(state, player) }
73 => { self.tick_n073_water_droplet(state, stage) }
74 => { self.tick_n074_jack(state) }
75 => { self.tick_n075_kanpachi(state, player) }
76 => { self.tick_n076_flowers() }
77 => { self.tick_n077_yamashita(state) }
78 => { self.tick_n078_pot(state) }
79 => { self.tick_n079_mahin(state, player) }
129 => { self.tick_n129_fireball_snake_trail(state) }
211 => { self.tick_n211_small_spikes(state) }
_ => { Ok(()) }
0 => self.tick_n000_null(),
1 => self.tick_n001_experience(state),
2 => self.tick_n002_behemoth(state),
3 => self.tick_n003_dead_enemy(),
4 => self.tick_n004_smoke(state),
5 => self.tick_n005_green_critter(state, player),
6 => self.tick_n006_green_beetle(state),
7 => self.tick_n007_basil(state, player),
8 => self.tick_n008_blue_beetle(state, player),
9 => self.tick_n009_balrog_falling_in(state),
10 => self.tick_n010_balrog_shooting(state, player),
11 => self.tick_n011_balrogs_projectile(state),
12 => self.tick_n012_balrog_cutscene(state, player, map, stage),
13 => self.tick_n013_forcefield(state),
14 => self.tick_n014_key(state),
15 => self.tick_n015_chest_closed(state),
16 => self.tick_n016_save_point(state),
17 => self.tick_n017_health_refill(state),
18 => self.tick_n018_door(state),
19 => self.tick_n019_balrog_bust_in(state),
20 => self.tick_n020_computer(state),
21 => self.tick_n021_chest_open(state),
22 => self.tick_n022_teleporter(state),
27 => self.tick_n027_death_trap(state),
30 => self.tick_n030_gunsmith(state),
32 => self.tick_n032_life_capsule(state),
34 => self.tick_n034_bed(state),
37 => self.tick_n037_sign(state),
38 => self.tick_n038_fireplace(state),
39 => self.tick_n039_save_sign(state),
41 => self.tick_n041_busted_door(state),
43 => self.tick_n043_chalkboard(state),
46 => self.tick_n046_hv_trigger(state, player),
52 => self.tick_n052_sitting_blue_robot(state),
55 => self.tick_n055_kazuma(state),
59 => self.tick_n059_eye_door(state, player),
60 => self.tick_n060_toroko(state, player),
61 => self.tick_n061_king(state),
62 => self.tick_n062_kazuma_computer(state),
63 => self.tick_n063_toroko_stick(state),
64 => self.tick_n064_first_cave_critter(state, player),
65 => self.tick_n065_first_cave_bat(state, player),
66 => self.tick_n066_misery_bubble(state, map),
67 => self.tick_n067_misery_floating(state),
68 => self.tick_n068_balrog_running(state, player),
69 => self.tick_n069_pignon(state),
70 => self.tick_n070_sparkle(state),
71 => self.tick_n071_chinfish(state),
72 => self.tick_n072_sprinkler(state, player),
73 => self.tick_n073_water_droplet(state, stage),
74 => self.tick_n074_jack(state),
75 => self.tick_n075_kanpachi(state, player),
76 => self.tick_n076_flowers(),
77 => self.tick_n077_yamashita(state),
78 => self.tick_n078_pot(state),
79 => self.tick_n079_mahin(state, player),
129 => self.tick_n129_fireball_snake_trail(state),
149 => self.tick_n149_horizontal_moving_block(state, player),
157 => self.tick_n157_vertical_moving_block(state, player),
211 => self.tick_n211_small_spikes(state),
_ => Ok(()),
}?;
if self.shock > 0 {