feat: Implement interact click logic (#25)

This commit is contained in:
demenik
2025-12-01 17:05:51 +01:00
parent e840e9a78b
commit 15ea976442
2 changed files with 103 additions and 4 deletions

View File

@@ -36,3 +36,8 @@ impl MovingState {
) )
} }
} }
#[derive(Component, Default)]
pub struct InteractionTarget {
pub target: Option<(u32, u32)>,
}

View File

@@ -1,7 +1,9 @@
use crate::prelude::*; use crate::prelude::*;
use components::*; use components::*;
use messages::InvalidMoveMessage; use messages::{InteractStartMessage, InvalidMoveMessage};
use std::collections::VecDeque;
use utils::find_path; use utils::find_path;
use utils::manhattan_distance;
pub mod components; pub mod components;
pub mod messages; pub mod messages;
@@ -16,7 +18,14 @@ impl Plugin for PomPlugin {
app.add_systems( app.add_systems(
Update, Update,
(handle_move, move_pom, update_pom).run_if(in_state(AppState::GameScreen)), (
handle_move,
handle_interact,
move_pom,
update_pom,
perform_interaction,
)
.run_if(in_state(AppState::GameScreen)),
); );
} }
} }
@@ -27,6 +36,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, config: Res<Gam
GridPosition { x: 0, y: 0 }, GridPosition { x: 0, y: 0 },
PathQueue::default(), PathQueue::default(),
MovingState::default(), MovingState::default(),
InteractionTarget::default(),
AseAnimation { AseAnimation {
aseprite: asset_server.load("pom/pom-sleep.aseprite"), aseprite: asset_server.load("pom/pom-sleep.aseprite"),
animation: Animation::tag("sleep-sit-start").with_repeat(AnimationRepeat::Loop), animation: Animation::tag("sleep-sit-start").with_repeat(AnimationRepeat::Loop),
@@ -53,10 +63,13 @@ fn handle_move(
mut invalid_move_messages: MessageWriter<InvalidMoveMessage>, mut invalid_move_messages: MessageWriter<InvalidMoveMessage>,
grid: Res<Grid>, grid: Res<Grid>,
tile_query: Query<&TileState>, tile_query: Query<&TileState>,
mut pom_query: Query<(&GridPosition, &mut PathQueue)>, mut pom_query: Query<(&GridPosition, &mut PathQueue, &mut InteractionTarget)>,
) { ) {
for message in move_messages.read() { for message in move_messages.read() {
for (grid_pos, mut path_queue) in pom_query.iter_mut() { for (grid_pos, mut path_queue, mut interaction_target) in pom_query.iter_mut() {
// Clear any pending interaction when moving manually
interaction_target.target = None;
let grid_start = (grid_pos.x, grid_pos.y); let grid_start = (grid_pos.x, grid_pos.y);
let start = path_queue.steps.front().unwrap_or(&grid_start); let start = path_queue.steps.front().unwrap_or(&grid_start);
let end = (message.x, message.y); let end = (message.x, message.y);
@@ -78,6 +91,86 @@ fn handle_move(
} }
} }
fn handle_interact(
mut interact_messages: MessageReader<InteractStartMessage>,
mut pom_query: Query<(&GridPosition, &mut PathQueue, &mut InteractionTarget)>,
grid: Res<Grid>,
tile_query: Query<&TileState>,
) {
for message in interact_messages.read() {
for (grid_pos, mut path_queue, mut interaction_target) in pom_query.iter_mut() {
let target_pos = (message.x, message.y);
let current_pos = (grid_pos.x, grid_pos.y);
// If we are already adjacent to the target, just set the target and clear path
if manhattan_distance(current_pos.0, current_pos.1, target_pos.0, target_pos.1) == 1 {
path_queue.steps.clear();
interaction_target.target = Some(target_pos);
continue;
}
// Find a path to an adjacent tile
let neighbors = [
(target_pos.0 as i32 + 1, target_pos.1 as i32),
(target_pos.0 as i32 - 1, target_pos.1 as i32),
(target_pos.0 as i32, target_pos.1 as i32 + 1),
(target_pos.0 as i32, target_pos.1 as i32 - 1),
];
let mut best_path: Option<VecDeque<(u32, u32)>> = None;
for (nx, ny) in neighbors {
if nx < 0 || ny < 0 {
continue;
}
let neighbor_pos = (nx as u32, ny as u32);
if let Some(path) = find_path(current_pos, neighbor_pos, &grid, &tile_query) {
// Pick the shortest path
if best_path.as_ref().map_or(true, |p| path.len() < p.len()) {
best_path = Some(path);
}
}
}
if let Some(path) = best_path {
path_queue.steps = path;
interaction_target.target = Some(target_pos);
} else {
println!("Cannot reach interaction target at {:?}", target_pos);
// Don't set target if unreachable
interaction_target.target = None;
}
}
}
}
fn perform_interaction(
mut pom_query: Query<(&GridPosition, &mut InteractionTarget, &PathQueue)>,
// grid: Res<Grid>,
// mut tile_query: Query<&mut TileState>,
) {
for (pos, mut target_component, path_queue) in pom_query.iter_mut() {
if let Some(target) = target_component.target {
// Wait until movement stops
if !path_queue.steps.is_empty() {
continue;
}
if manhattan_distance(pos.x, pos.y, target.0, target.1) == 1 {
println!(
"Performing interaction on tile ({}, {})",
target.0, target.1
);
// TODO: Implement interaction logic
}
target_component.target = None;
}
}
}
fn move_pom( fn move_pom(
time: Res<Time>, time: Res<Time>,
mut query: Query<( mut query: Query<(
@@ -153,3 +246,4 @@ fn update_pom(asset_server: Res<AssetServer>, mut query: Query<(&MovingState, &m
} }
} }
} }