use anyhow::{bail, Result}; use rtchallenge::{ canvas::{canvas, Canvas}, tuples::{color, point, vector, Tuple}, }; #[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(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 = point(0., 1., 0.); let velocity = vector(1., 1.8, 0.).normalize() * 11.25; let mut p = Projectile { position, velocity }; let gravity = vector(0., -0.1, 0.); let wind = vector(-0.01, 0., 0.); let e = Environment { gravity, wind }; let w = 800; let h = 600; let mut c = canvas(w, h); let mut i = 0; let w = w as f32; let h = h as f32; 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(()) }