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,
|
direction: Direction,
|
||||||
can_turn_around: bool,
|
can_turn_around: bool,
|
||||||
push_depth: i32,
|
push_depth: i32,
|
||||||
|
entities_that_have_moved: &mut Vec<(EntityKey, Direction)>,
|
||||||
) -> (bool, bool, bool) {
|
) -> (bool, bool, bool) {
|
||||||
let mut hero_has_died = false;
|
let mut hero_has_died = false;
|
||||||
let mut win_has_triggered = false;
|
let mut win_has_triggered = false;
|
||||||
|
@ -153,6 +154,7 @@ impl EntityMap {
|
||||||
direction,
|
direction,
|
||||||
true,
|
true,
|
||||||
depth,
|
depth,
|
||||||
|
entities_that_have_moved,
|
||||||
);
|
);
|
||||||
|
|
||||||
if !can_move_result {
|
if !can_move_result {
|
||||||
|
@ -176,89 +178,19 @@ impl EntityMap {
|
||||||
if let Some(e) = self.map.get_mut(entity_to_update_key) {
|
if let Some(e) = self.map.get_mut(entity_to_update_key) {
|
||||||
e.location = desired_location;
|
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 {
|
let Some(entity_to_update) = self.map.get(entity_to_update_key) else {
|
||||||
return (can_move, hero_has_died, win_has_triggered);
|
return (can_move, hero_has_died, win_has_triggered);
|
||||||
};
|
};
|
||||||
|
|
||||||
let move_effect = entity_to_update.move_effect();
|
let move_effect = entity_to_update.move_effect();
|
||||||
|
|
||||||
let overlap_resolutions: Vec<_> = self
|
animations.push(AnimationInstruction::Move(
|
||||||
.whats_at(desired_location)
|
entity_to_update_key,
|
||||||
.filter(|(k, _)| *k != entity_to_update_key)
|
desired_location,
|
||||||
.map(|(key, other_entity)| (key, resolve_overlap(entity_to_update, other_entity)))
|
move_effect,
|
||||||
.collect();
|
));
|
||||||
|
|
||||||
if !overlap_resolutions
|
|
||||||
.iter()
|
|
||||||
.any(|x| matches!(x.1, OverlapResolution::MoveAgain))
|
|
||||||
{
|
|
||||||
animations.push(AnimationInstruction::Move(
|
|
||||||
entity_to_update_key,
|
|
||||||
desired_location,
|
|
||||||
move_effect,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (other_entity_key, move_resolution) in overlap_resolutions {
|
|
||||||
match move_resolution {
|
|
||||||
OverlapResolution::Pickup => {
|
|
||||||
animations.push(AnimationInstruction::Attach(
|
|
||||||
entity_to_update_key,
|
|
||||||
other_entity_key,
|
|
||||||
self.map
|
|
||||||
.get(other_entity_key)
|
|
||||||
.and_then(|x| x.pickup_sound_effect()),
|
|
||||||
));
|
|
||||||
let other = self.map.remove(other_entity_key).unwrap();
|
|
||||||
|
|
||||||
if let Some((location, dropped)) = self
|
|
||||||
.map
|
|
||||||
.get_mut(entity_to_update_key)
|
|
||||||
.and_then(|x| x.pickup(other.entity).map(|y| (x.location, y)))
|
|
||||||
{
|
|
||||||
let new_key = self.map.insert(Entity {
|
|
||||||
location,
|
|
||||||
entity: dropped,
|
|
||||||
});
|
|
||||||
|
|
||||||
animations.push(AnimationInstruction::Detatch(
|
|
||||||
entity_to_update_key,
|
|
||||||
new_key,
|
|
||||||
self.map.get(new_key).and_then(|x| x.drop_effect()),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OverlapResolution::CoExist => {}
|
|
||||||
OverlapResolution::Win => {
|
|
||||||
win_has_triggered = true;
|
|
||||||
}
|
|
||||||
OverlapResolution::ToggleSystem(system) => {
|
|
||||||
for (k, e) in self.map.iter_mut() {
|
|
||||||
if let Some(change) = e.switch(system) {
|
|
||||||
animations.push(AnimationInstruction::Change(
|
|
||||||
k,
|
|
||||||
change,
|
|
||||||
e.change_effect(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OverlapResolution::Die => {
|
|
||||||
hero_has_died |= self.kill_entity(entity_to_update_key, animations);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
OverlapResolution::MoveAgain => {
|
|
||||||
self.attempt_move_in_direction(
|
|
||||||
map,
|
|
||||||
animations,
|
|
||||||
entity_to_update_key,
|
|
||||||
direction,
|
|
||||||
false,
|
|
||||||
push_depth,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if explicit_stay_put
|
} else if explicit_stay_put
|
||||||
&& can_turn_around
|
&& can_turn_around
|
||||||
&& self.map.get(entity_to_update_key).map(|e| e.turns_around()) == Some(true)
|
&& self.map.get(entity_to_update_key).map(|e| e.turns_around()) == Some(true)
|
||||||
|
@ -281,6 +213,7 @@ impl EntityMap {
|
||||||
-direction,
|
-direction,
|
||||||
false,
|
false,
|
||||||
push_depth,
|
push_depth,
|
||||||
|
entities_that_have_moved,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -305,13 +238,99 @@ impl EntityMap {
|
||||||
(can_move, hero_has_died, win_has_triggered)
|
(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 {
|
||||||
|
OverlapResolution::Pickup => {
|
||||||
|
animations.push(AnimationInstruction::Attach(
|
||||||
|
entity_to_update_key,
|
||||||
|
other_entity_key,
|
||||||
|
self.map
|
||||||
|
.get(other_entity_key)
|
||||||
|
.and_then(|x| x.pickup_sound_effect()),
|
||||||
|
));
|
||||||
|
let other = self.map.remove(other_entity_key).unwrap();
|
||||||
|
|
||||||
|
if let Some((location, dropped)) = self
|
||||||
|
.map
|
||||||
|
.get_mut(entity_to_update_key)
|
||||||
|
.and_then(|x| x.pickup(other.entity).map(|y| (x.location, y)))
|
||||||
|
{
|
||||||
|
let new_key = self.map.insert(Entity {
|
||||||
|
location,
|
||||||
|
entity: dropped,
|
||||||
|
});
|
||||||
|
|
||||||
|
animations.push(AnimationInstruction::Detatch(
|
||||||
|
entity_to_update_key,
|
||||||
|
new_key,
|
||||||
|
self.map.get(new_key).and_then(|x| x.drop_effect()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OverlapResolution::CoExist => {}
|
||||||
|
OverlapResolution::Win => {
|
||||||
|
win_has_triggered = true;
|
||||||
|
}
|
||||||
|
OverlapResolution::ToggleSystem(system) => {
|
||||||
|
for (k, e) in self.map.iter_mut() {
|
||||||
|
if let Some(change) = e.switch(system) {
|
||||||
|
animations.push(AnimationInstruction::Change(
|
||||||
|
k,
|
||||||
|
change,
|
||||||
|
e.change_effect(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OverlapResolution::Die => {
|
||||||
|
hero_has_died |= self.kill_entity(entity_to_update_key, animations);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
OverlapResolution::MoveAgain => {
|
||||||
|
if let Some(existing_animation) = animations.iter().position(|x| {
|
||||||
|
if let AnimationInstruction::Move(entity, _, _) = x {
|
||||||
|
*entity == entity_to_update_key
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
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>) {
|
pub fn tick(&mut self, map: &Map, hero: Action) -> (Outcome, Vec<AnimationInstruction>) {
|
||||||
let mut hero_has_died = false;
|
let mut hero_has_died = false;
|
||||||
let mut win_has_triggered = false;
|
let mut win_has_triggered = false;
|
||||||
|
|
||||||
let mut animations = Vec::new();
|
let mut animations = Vec::new();
|
||||||
|
|
||||||
let entities_to_try_update = self
|
let mut entities_to_try_update = self
|
||||||
.map
|
.map
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(key, entity)| (key, entity.desired_action(hero)))
|
.map(|(key, entity)| (key, entity.desired_action(hero)))
|
||||||
|
@ -321,22 +340,39 @@ impl EntityMap {
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
for (entity_to_update_key, direction) in entities_to_try_update.iter().copied() {
|
while !entities_to_try_update.is_empty() {
|
||||||
let (_, hero_has_died_result, win_has_triggered_result) = self
|
let mut entities_that_have_moved = Vec::new();
|
||||||
.attempt_move_in_direction(
|
|
||||||
map,
|
|
||||||
&mut animations,
|
|
||||||
entity_to_update_key,
|
|
||||||
direction,
|
|
||||||
true,
|
|
||||||
self.map
|
|
||||||
.get(entity_to_update_key)
|
|
||||||
.and_then(|e| e.push_depth())
|
|
||||||
.unwrap_or(0),
|
|
||||||
);
|
|
||||||
|
|
||||||
hero_has_died |= hero_has_died_result;
|
for (entity_to_update_key, direction) in entities_to_try_update.drain(..) {
|
||||||
win_has_triggered |= win_has_triggered_result;
|
let (_, hero_has_died_result, win_has_triggered_result) = self
|
||||||
|
.attempt_move_in_direction(
|
||||||
|
map,
|
||||||
|
&mut animations,
|
||||||
|
entity_to_update_key,
|
||||||
|
direction,
|
||||||
|
true,
|
||||||
|
self.map
|
||||||
|
.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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
|
|
Loading…
Reference in a new issue