From 75a51a60b4bce655e57091b4b8010a30bf949ade Mon Sep 17 00:00:00 2001 From: Mikhail Mitrofanov Date: Sat, 12 Apr 2025 15:36:12 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B8=D1=81=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BB=D0=B8=D0=BD=D0=B8=D0=B8,=20=D0=BD=D0=BE?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=BB=D0=BE=D0=B2=D0=B8=D0=BD?= =?UTF-8?q?=D1=83=20=D0=BD=D0=B5=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0?= =?UTF-8?q?=D0=B5=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 236 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 212 insertions(+), 24 deletions(-) diff --git a/src/main.rs b/src/main.rs index 85f5e7e..db8f6d6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,20 +1,23 @@ use sdl3::event::Event; use sdl3::keyboard::Keycode; use sdl3::pixels::Color; +use sdl3::rect::Point; use sdl3::render::{FPoint, WindowCanvas}; use std::f32::consts::PI; use std::ops; -use std::ops::Rem; -use std::time::Instant; +use std::ops::{AddAssign, Mul, Rem, Sub}; +use std::time::{Duration, Instant}; const SIZE: u32 = 400; const SIZE_F: f32 = 400.0; -pub fn main() { - let point = Point2D::new(0.0, 0.0); - let mut cycle = 0_f32; - let radius = 100_f32; - let mut pasted_points: Vec = vec![point.to_cartesian().to_sdl()]; +pub fn main() { + let mut point_a = Point2D::new(-5.0, 0.0); + let mut point_b = Point2D::new(5.0, 0.0); + + let line = Line2D::new(&mut point_a, &mut point_b); + + let mut selection = 1; let sdl_context = sdl3::init().unwrap(); let video_subsystem = sdl_context.video().unwrap(); @@ -25,7 +28,13 @@ pub fn main() { .build() .unwrap(); - let mut canvas = window.into_canvas(); + let mut canvas = window.clone().into_canvas(); + + sdl_context.mouse().show_cursor(false); + sdl_context.mouse().capture(true); + sdl_context + .mouse() + .warp_mouse_in_window(&window, SIZE_F, SIZE_F); canvas.set_draw_color(Color::RGB(0, 0, 0)); canvas.clear(); @@ -43,32 +52,68 @@ pub fn main() { keycode: Some(Keycode::Escape), .. } => break 'running, + Event::KeyDown { + keycode: Some(Keycode::_1), + .. + } => { + selection = 1; + } + Event::KeyDown { + keycode: Some(Keycode::_2), + .. + } => { + selection = 2; + } + Event::KeyDown { + keycode: Some(Keycode::D), + .. + } => { + println!("Debug") + } + Event::MouseMotion { .. } => { + if let Event::MouseMotion { + timestamp: _, + window_id: _, + which: _, + mousestate: _, + x, + y, + xrel, + yrel, + } = event + { + let mut cursor: &mut Point2D; + if selection == 1 { + cursor = line.a; + } else { + cursor = line.b; + } + + cursor += (xrel, yrel); + cursor.optimize(); + cursor = &mut cursor.abs(); + } + } _ => {} } } + + sdl_context + .mouse() + .warp_mouse_in_window(&window, SIZE_F, SIZE_F); // The rest of the game loop goes here... - let cos = cycle.cos() * radius; - let sin = cycle.sin() * radius; - let mut next = Point2D::new(cos + cycle * 2.0 * PI, sin); - next.optimize(); - - - pasted_points.push(next.to_cartesian().to_sdl()); count += 1; - canvas.set_draw_color(Color::RGB(255, 255, 255)); - Point2D::draw_point(&mut canvas, &pasted_points); + line.draw(&mut canvas, 1.0); canvas.present(); - cycle -= 0.01; - if count == 10000 { println!("Time for 10000 is {} ms", time.elapsed().as_millis()); } - // std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 200)); + std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 600)); } } @@ -84,8 +129,13 @@ impl Point2D { Point2D { x, y, spin: false } } - pub fn distance(&self, point: &Point2D) -> f32 { - (self.x - point.x).hypot(self.y - point.y) + pub fn new_with_spin(x: f32, y: f32, spin: bool) -> Point2D { + Point2D { x, y, spin } + } + pub fn distance_abs(&self, point: &Point2D) -> f32 { + let a_abs = self.optimized().abs(); + let b_abs = point.optimized().abs(); + (a_abs.x - b_abs.x).hypot(a_abs.y - b_abs.y) } pub fn distance_sq(&self, point: &Point2D) -> f32 { @@ -93,7 +143,7 @@ impl Point2D { } pub fn alt_distance(&self, point: &Point2D) -> f32 { - 2.0 * SIZE_F - self.distance(point) + 2.0 * SIZE_F - self.distance_abs(point) } pub fn to_cartesian(&self) -> Point2D { @@ -147,6 +197,11 @@ impl Point2D { remainder } + pub fn normalized(&self) -> Point2D { + let len = self.x.hypot(self.y); + Point2D::new_with_spin(self.x / len, self.y / len, self.spin) + } + pub fn optimize(&mut self) { if self.x.abs() > SIZE_F { self.x = Self::lapped(self.x); @@ -160,6 +215,24 @@ impl Point2D { } } + pub fn optimized(&self) -> Point2D { + let mut x: f32 = self.x; + let mut y: f32 = self.y; + let mut spin: bool = self.spin; + if self.x.abs() > SIZE_F { + x = Self::lapped(self.x); + } + + if self.y.abs() > SIZE_F { + let side = self.y.signum(); + y += -side * 2.0 * (self.y.abs() - SIZE_F); + x = self.x + SIZE_F; + spin = !spin; + } + + Point2D::new_with_spin(x, y, spin) + } + pub fn draw_point(canvas: &mut WindowCanvas, points: &Vec) { // canvas.draw_points(&points).unwrap() canvas.draw_points(&points[..]).unwrap(); @@ -172,6 +245,32 @@ impl Point2D { pub fn eq_spin(&self, point: &Point2D) -> bool { self.eq(point) && self.spin == point.spin } + + pub fn abs(&self) -> Point2D { + let x: f32; + let y: f32; + if self.x < 0.0 { + x = self.x.rem_euclid(SIZE_F * 2.0); + } else { + x = self.x; + } + if self.y < 0.0 { + y = self.y.rem_euclid(SIZE_F * 2.0); + } else { + y = self.y; + } + + Point2D::new(x, y) + } + + pub fn relative(&self) -> Point2D { + Point2D::new(Self::lapped(self.x), Self::lapped(self.y)) + } + + pub fn add(&mut self, x: f32, y: f32) { + self.x += x; + self.y += y; + } } impl ops::AddAssign for Point2D { @@ -181,12 +280,101 @@ impl ops::AddAssign for Point2D { } } -impl ops::AddAssign<(f32, f32)> for Point2D { +impl AddAssign<(f32, f32)> for Point2D { fn add_assign(&mut self, rhs: (f32, f32)) { self.x += rhs.0 * bool_to_int(self.spin) as f32; self.y += rhs.1 * bool_to_int(self.spin) as f32; } } + +impl AddAssign<(f32, f32)> for &mut Point2D { + fn add_assign(&mut self, rhs: (f32, f32)) { + self.x += rhs.0 * bool_to_int(self.spin) as f32; + self.y += rhs.1 * bool_to_int(self.spin) as f32; + } +} + fn bool_to_int(flag: bool) -> i32 { if !flag { 1 } else { -1 } } + +impl Clone for Point2D { + fn clone(&self) -> Self { + Point2D::new_with_spin(self.x, self.y, self.spin) + } +} + +struct Line2D<'a> { + a: &'a mut Point2D, + b: &'a mut Point2D, + ending: Color, + fill: Color, + segments: u32, +} + +impl Sub for Point2D { + type Output = Self; + fn sub(self, rhs: Self) -> Self::Output { + Point2D::new_with_spin(self.x - rhs.x, self.y - rhs.y, self.spin) + } +} + +impl Mul for Point2D { + type Output = Point2D; + + fn mul(self, rhs: f32) -> Self::Output { + Point2D::new_with_spin(self.x * rhs, self.y * rhs, self.spin) + } +} + +impl<'a> Line2D<'a> { + pub fn new(a: &'a mut Point2D, b: &'a mut Point2D) -> Self { + Self { + a, + b, + ending: Color::WHITE, + fill: Color::YELLOW, + segments: 13, + } + } + + pub fn draw<'b>(&'a self, canvas: &mut WindowCanvas, pow: f32) { + let distance: f32; + if pow < 0.0 { + distance = self.a.alt_distance(self.b); + } else { + distance = self.b.distance_abs(self.a); + } + + let a_abs = self.a.abs(); + let b_abs = self.b.abs(); + let vec = (b_abs - a_abs).normalized() * (distance / self.segments as f32) * pow; + let mut cursor = self.a.clone(); + canvas.set_draw_color(self.fill); + for i in 1..self.segments { + cursor.add(vec.x, vec.y); + cursor.optimize(); + cursor.draw(canvas); + } + canvas.set_draw_color(self.ending); + self.a.draw(canvas); + self.b.draw(canvas); + } + + pub fn draw_alt<'b>(&'a self, canvas: &mut WindowCanvas) { + let mut local_a = self.a.clone().abs(); + let mut local_b = self.b.clone().abs(); + + let x_step = (local_a.x - local_b.x) / self.segments as f32; + let y_step = (local_a.y - local_b.y) / self.segments as f32; + canvas.set_draw_color(self.fill); + for i in 1..self.segments { + let pt = Point2D::new(local_b.x + x_step * i as f32, local_b.y + y_step * i as f32); + pt.draw(canvas); + } + + canvas.set_draw_color(self.ending); + local_b.draw(canvas); + local_a.draw(canvas); + } +}