use anyhow::{bail, Result}; use rtchallenge::{ canvas::Canvas, tuples::{Color, Tuple}, Float, }; #[derive(Debug)] struct Environment { gravity: Tuple, wind: Tuple, } #[derive(Debug)] struct Projectile { position: Tuple, velocity: Tuple, } fn tick(env: &Environment, proj: &Projectile) -> Projectile { let position = proj.position + proj.velocity; let velocity = proj.velocity + env.gravity + env.wind; Projectile { position, velocity } } fn draw_dot(c: &mut Canvas, x: usize, y: usize) { let red = Color::new(1., 0., 0.); c.set(x.saturating_sub(1), y.saturating_sub(1), red); c.set(x, y.saturating_sub(1), red); c.set(x + 1, y.saturating_sub(1), red); c.set(x.saturating_sub(1), y, red); c.set(x, y, red); c.set(x + 1, y, red); c.set(x.saturating_sub(1), y + 1, red); c.set(x, y + 1, red); c.set(x + 1, y + 1, red); } fn main() -> Result<()> { let position = Tuple::point(0., 1., 0.); let velocity = Tuple::vector(1., 1.8, 0.).normalize() * 11.25; let mut p = Projectile { position, velocity }; let gravity = Tuple::vector(0., -0.1, 0.); let wind = Tuple::vector(-0.01, 0., 0.); let e = Environment { gravity, wind }; let w = 800; let h = 600; let bg = Color::new(0.2, 0.2, 0.2); let mut c = Canvas::new(w, h, bg); let mut i = 0; let w = w as Float; let h = h as Float; while p.position.y > 0. { p = tick(&e, &p); println!("tick {}: proj {:?}", i, p); let x = p.position.x; let y = p.position.y; if x > 0. && x < w && y > 0. && y < h { let x = x as usize; let y = (h - y) as usize; draw_dot(&mut c, x, y) } i += 1; if i > 1000 { bail!("too many iterations"); } } let path = "/tmp/output.png"; println!("saving output to {}", path); c.write_to_file(path)?; Ok(()) }