mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 08:11:33 +11:00
resolve overlaps after all moves
This commit is contained in:
parent
d781a41357
commit
346f62f328
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue