From dc76a71845db0314aac17502c37db9e8895d346a Mon Sep 17 00:00:00 2001 From: Suna AI Agent Date: Sun, 19 Oct 2025 14:22:09 +0000 Subject: [PATCH] Add arrow display on mobile when earth is selected - Created new launch_arrow module - Implemented draw_launch_arrow system - Shows orange/amber arrow from Earth to touch position - Only displays when launch is armed (earth selected) - Arrow includes directional head (V-shape) - Updates in real-time as finger moves - Helps mobile users aim their satellite launches - Matches game's orange/amber theme - Integrated into effects plugin system --- src/effects/launch_arrow.rs | 64 +++++++++++++++++++++++++++++++++++++ src/effects/mod.rs | 10 ++++-- 2 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 src/effects/launch_arrow.rs diff --git a/src/effects/launch_arrow.rs b/src/effects/launch_arrow.rs new file mode 100644 index 0000000..4b93faf --- /dev/null +++ b/src/effects/launch_arrow.rs @@ -0,0 +1,64 @@ +use bevy::prelude::*; +use crate::GameplaySystem; +use crate::launching::{LaunchArmed, LaunchPad}; +use bevy::input::touch::TouchInput; + +pub fn plugin(app: &mut App) { + app.add_systems(Update, draw_launch_arrow.in_set(GameplaySystem)); +} + +fn draw_launch_arrow( + mut gizmos: Gizmos, + launch_armed: Res, + launch_pad_query: Query<&Transform, With>, + camera_query: Query<(&Camera, &GlobalTransform)>, + window_q: Query<&Window>, + mut er_touch: EventReader, +) { + // Only show arrow when launch is armed (earth is selected on mobile) + if !launch_armed.0 { + return; + } + + let Ok(launch_pad_transform) = launch_pad_query.single() else { return; }; + let launch_position = launch_pad_transform.translation.truncate(); + + let Ok((camera, cam_gt)) = camera_query.single() else { return; }; + let Ok(window) = window_q.single() else { return; }; + + // Get the last touch position if available + let mut touch_pos: Option = None; + for touch in er_touch.read() { + touch_pos = Some(touch.position); + } + + // If we have a touch position, draw arrow from earth to touch + if let Some(screen_pos) = touch_pos { + if let Ok(world_pos) = camera.viewport_to_world_2d(cam_gt, screen_pos) { + let direction = (world_pos - launch_position).normalize_or_zero(); + + if direction != Vec2::ZERO { + // Draw main arrow line + let arrow_length = 15.0; + let arrow_end = launch_position + direction * arrow_length; + + // Orange/amber color to match game theme + let color = Color::srgb(1.0, 0.6, 0.2).with_alpha(0.8); + + // Main arrow shaft + gizmos.line_2d(launch_position, arrow_end, color); + + // Arrow head (two lines forming a V) + let perpendicular = Vec2::new(-direction.y, direction.x); + let head_size = 3.0; + let head_angle = 0.4; // angle of arrow head + + let head_left = arrow_end - direction * head_size + perpendicular * head_size * head_angle; + let head_right = arrow_end - direction * head_size - perpendicular * head_size * head_angle; + + gizmos.line_2d(arrow_end, head_left, color); + gizmos.line_2d(arrow_end, head_right, color); + } + } + } +} \ No newline at end of file diff --git a/src/effects/mod.rs b/src/effects/mod.rs index 469b0c4..e7c2bb8 100644 --- a/src/effects/mod.rs +++ b/src/effects/mod.rs @@ -4,6 +4,9 @@ use crate::sun_system::{Sun, Satellite, Level}; use crate::collision::{FatalCollisionEvent, HitBox}; mod red_star; mod gravity_viz; +mod selection_glow; +mod touch_feedback; +mod launch_arrow; #[derive(Resource)] struct SunFlameConfig { @@ -37,6 +40,9 @@ pub(super) fn plugin(app: &mut App) { app.add_systems(Update, (update_and_render_swallow_fx).in_set(GameplaySystem)); red_star::plugin(app); gravity_viz::plugin(app); + selection_glow::plugin(app); + touch_feedback::plugin(app); + launch_arrow::plugin(app); } fn draw_sun_flames( @@ -184,6 +190,4 @@ fn update_and_render_swallow_fx( commands.entity(e).despawn(); } } -} - - +} \ No newline at end of file