resolve overlaps after all moves

This commit is contained in:
Corwin 2023-08-29 20:51:42 +01:00
parent d781a41357
commit 346f62f328
No known key found for this signature in database

View file

@ -93,6 +93,7 @@ impl EntityMap {
direction: Direction,
can_turn_around: bool,
push_depth: i32,
entities_that_have_moved: &mut Vec<(EntityKey, Direction)>,
) -> (bool, bool, bool) {
let mut hero_has_died = false;
let mut win_has_triggered = false;
@ -153,6 +154,7 @@ impl EntityMap {
direction,
true,
depth,
entities_that_have_moved,
);
if !can_move_result {
@ -176,28 +178,86 @@ impl EntityMap {
if let Some(e) = self.map.get_mut(entity_to_update_key) {
e.location = desired_location;
}
entities_that_have_moved.push((entity_to_update_key, direction));
let Some(entity_to_update) = self.map.get(entity_to_update_key) else {
return (can_move, hero_has_died, win_has_triggered);
};
let move_effect = entity_to_update.move_effect();
let overlap_resolutions: Vec<_> = self
.whats_at(desired_location)
.filter(|(k, _)| *k != entity_to_update_key)
.map(|(key, other_entity)| (key, resolve_overlap(entity_to_update, other_entity)))
.collect();
if !overlap_resolutions
.iter()
.any(|x| matches!(x.1, OverlapResolution::MoveAgain))
{
animations.push(AnimationInstruction::Move(
entity_to_update_key,
desired_location,
move_effect,
));
} else if explicit_stay_put
&& can_turn_around
&& self.map.get(entity_to_update_key).map(|e| e.turns_around()) == Some(true)
{
if let Some((Some(change), change_effect)) = self
.map
.get_mut(entity_to_update_key)
.map(|e| (e.change_direction(), e.change_effect()))
{
animations.push(AnimationInstruction::PriorityChange(
entity_to_update_key,
change,
change_effect,
));
return self.attempt_move_in_direction(
map,
animations,
entity_to_update_key,
-direction,
false,
push_depth,
entities_that_have_moved,
);
}
} else {
animations.push(AnimationInstruction::FakeOutMove(
entity_to_update_key,
direction,
self.map.get(entity_to_update_key).map(|e| e.location),
if explicit_stay_put {
self.map
.get(entity_to_update_key)
.and_then(|e| e.fake_out_wall_effect())
} else {
fake_out_effect.or_else(|| {
self.map
.get(entity_to_update_key)
.and_then(|e| e.fake_out_effect())
})
},
));
}
(can_move, hero_has_died, win_has_triggered)
}
fn resolve_overlap_from_move(
&mut self,
animations: &mut Vec<AnimationInstruction>,
entity_to_update_key: EntityKey,
) -> (bool, bool, bool) {
let mut win_has_triggered = false;
let mut hero_has_died = false;
let mut should_move_again = false;
let Some(entity_to_update) = self.map.get(entity_to_update_key) else {
return (should_move_again, hero_has_died, win_has_triggered);
};
let location = entity_to_update.location;
let overlap_resolutions: Vec<_> = self
.whats_at(location)
.filter(|(k, _)| *k != entity_to_update_key)
.map(|(key, other_entity)| (key, resolve_overlap(entity_to_update, other_entity)))
.collect();
for (other_entity_key, move_resolution) in overlap_resolutions {
match move_resolution {
@ -248,61 +308,20 @@ impl EntityMap {
break;
}
OverlapResolution::MoveAgain => {
self.attempt_move_in_direction(
map,
animations,
entity_to_update_key,
direction,
false,
push_depth,
);
}
}
}
} else if explicit_stay_put
&& can_turn_around
&& self.map.get(entity_to_update_key).map(|e| e.turns_around()) == Some(true)
{
if let Some((Some(change), change_effect)) = self
.map
.get_mut(entity_to_update_key)
.map(|e| (e.change_direction(), e.change_effect()))
{
animations.push(AnimationInstruction::PriorityChange(
entity_to_update_key,
change,
change_effect,
));
return self.attempt_move_in_direction(
map,
animations,
entity_to_update_key,
-direction,
false,
push_depth,
);
}
if let Some(existing_animation) = animations.iter().position(|x| {
if let AnimationInstruction::Move(entity, _, _) = x {
*entity == entity_to_update_key
} else {
animations.push(AnimationInstruction::FakeOutMove(
entity_to_update_key,
direction,
self.map.get(entity_to_update_key).map(|e| e.location),
if explicit_stay_put {
self.map
.get(entity_to_update_key)
.and_then(|e| e.fake_out_wall_effect())
} else {
fake_out_effect.or_else(|| {
self.map
.get(entity_to_update_key)
.and_then(|e| e.fake_out_effect())
})
},
));
false
}
(can_move, hero_has_died, win_has_triggered)
}) {
animations.swap_remove(existing_animation);
}
should_move_again = true;
}
}
}
(should_move_again, hero_has_died, win_has_triggered)
}
pub fn tick(&mut self, map: &Map, hero: Action) -> (Outcome, Vec<AnimationInstruction>) {
@ -311,7 +330,7 @@ impl EntityMap {
let mut animations = Vec::new();
let entities_to_try_update = self
let mut entities_to_try_update = self
.map
.iter()
.map(|(key, entity)| (key, entity.desired_action(hero)))
@ -321,7 +340,10 @@ impl EntityMap {
})
.collect::<Vec<_>>();
for (entity_to_update_key, direction) in entities_to_try_update.iter().copied() {
while !entities_to_try_update.is_empty() {
let mut entities_that_have_moved = Vec::new();
for (entity_to_update_key, direction) in entities_to_try_update.drain(..) {
let (_, hero_has_died_result, win_has_triggered_result) = self
.attempt_move_in_direction(
map,
@ -333,12 +355,26 @@ impl EntityMap {
.get(entity_to_update_key)
.and_then(|e| e.push_depth())
.unwrap_or(0),
&mut entities_that_have_moved,
);
hero_has_died |= hero_has_died_result;
win_has_triggered |= win_has_triggered_result;
}
for (entity_to_update_key, direction) in entities_that_have_moved {
let (should_move_again, hero_has_died_result, win_has_triggered_result) =
self.resolve_overlap_from_move(&mut animations, entity_to_update_key);
if should_move_again {
entities_to_try_update.push((entity_to_update_key, direction));
}
hero_has_died |= hero_has_died_result;
win_has_triggered |= win_has_triggered_result;
}
}
(
if hero_has_died {
Outcome::Loss