74 lines
1.9 KiB
Rust
74 lines
1.9 KiB
Rust
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(())
|
|
}
|