feat: touch movement controls

This commit is contained in:
Ryan Walters
2025-09-04 11:02:51 -05:00
parent 36a2f00d8c
commit 1f5af2cd96
3 changed files with 177 additions and 6 deletions

View File

@@ -1,6 +1,7 @@
use crate::constants::CANVAS_SIZE;
use crate::error::{GameError, TextureError};
use crate::map::builder::Map;
use crate::systems::input::TouchState;
use crate::systems::{
debug_render_system, BatchedLinesResource, Collider, CursorPosition, DebugState, DebugTextureResource, DeltaTime,
DirectionalAnimation, LinearAnimation, Position, Renderable, ScoreResource, StartupSequence, SystemId, SystemTimings,
@@ -114,6 +115,79 @@ pub struct MapTextureResource(pub Texture);
/// A non-send resource for the backbuffer texture. This just wraps the texture with a type so it can be differentiated when exposed as a resource.
pub struct BackbufferResource(pub Texture);
/// Renders touch UI overlay for mobile/testing.
pub fn touch_ui_render_system(
mut backbuffer: NonSendMut<BackbufferResource>,
mut canvas: NonSendMut<&mut Canvas<Window>>,
touch_state: Res<TouchState>,
mut errors: EventWriter<GameError>,
) {
if let Some(ref touch_data) = touch_state.active_touch {
let _ = canvas.with_texture_canvas(&mut backbuffer.0, |canvas| {
// Set blend mode for transparency
canvas.set_blend_mode(BlendMode::Blend);
// Draw semi-transparent circle at touch start position
canvas.set_draw_color(Color::RGBA(255, 255, 255, 100));
let center = Point::new(touch_data.start_pos.x as i32, touch_data.start_pos.y as i32);
// Draw a simple circle by drawing filled rectangles (basic approach)
let radius = 30;
for dy in -radius..=radius {
for dx in -radius..=radius {
if dx * dx + dy * dy <= radius * radius {
let point = Point::new(center.x + dx, center.y + dy);
if let Err(e) = canvas.draw_point(point) {
errors.write(TextureError::RenderFailed(format!("Touch UI render error: {}", e)).into());
return;
}
}
}
}
// Draw direction indicator if we have a direction
if let Some(direction) = touch_data.current_direction {
canvas.set_draw_color(Color::RGBA(0, 255, 0, 150));
// Draw arrow indicating direction
let arrow_length = 40;
let (dx, dy) = match direction {
crate::map::direction::Direction::Up => (0, -arrow_length),
crate::map::direction::Direction::Down => (0, arrow_length),
crate::map::direction::Direction::Left => (-arrow_length, 0),
crate::map::direction::Direction::Right => (arrow_length, 0),
};
let end_point = Point::new(center.x + dx, center.y + dy);
if let Err(e) = canvas.draw_line(center, end_point) {
errors.write(TextureError::RenderFailed(format!("Touch arrow render error: {}", e)).into());
}
// Draw arrowhead (simple approach)
let arrow_size = 8;
match direction {
crate::map::direction::Direction::Up => {
let _ = canvas.draw_line(end_point, Point::new(end_point.x - arrow_size, end_point.y + arrow_size));
let _ = canvas.draw_line(end_point, Point::new(end_point.x + arrow_size, end_point.y + arrow_size));
}
crate::map::direction::Direction::Down => {
let _ = canvas.draw_line(end_point, Point::new(end_point.x - arrow_size, end_point.y - arrow_size));
let _ = canvas.draw_line(end_point, Point::new(end_point.x + arrow_size, end_point.y - arrow_size));
}
crate::map::direction::Direction::Left => {
let _ = canvas.draw_line(end_point, Point::new(end_point.x + arrow_size, end_point.y - arrow_size));
let _ = canvas.draw_line(end_point, Point::new(end_point.x + arrow_size, end_point.y + arrow_size));
}
crate::map::direction::Direction::Right => {
let _ = canvas.draw_line(end_point, Point::new(end_point.x - arrow_size, end_point.y - arrow_size));
let _ = canvas.draw_line(end_point, Point::new(end_point.x - arrow_size, end_point.y + arrow_size));
}
}
}
});
}
}
/// Renders the HUD (score, lives, etc.) on top of the game.
pub fn hud_render_system(
mut backbuffer: NonSendMut<BackbufferResource>,