use vertra::camera::Camera;
use vertra::geometry::Geometry;
use vertra::objects::Object;
use vertra::transform::Transform;
use vertra::window::Window;
struct AppState {
ball_id: Option<usize>,
cube_id: Option<usize>,
ball_vy: f32,
}
fn main() {
Window::new(AppState {
ball_id: None,
cube_id: None,
ball_vy: 8.0, })
.with_title("Fixed Update — Bouncing Ball")
.with_camera(
Camera::new()
.with_position([0.0, 3.0, -8.0])
.with_rotation(90.0, -15.0),
)
.on_startup(|state, scene, _| {
let ball_id = scene.spawn(
Object {
name: "Ball".to_string(),
str_id: "ball".to_string(),
geometry: Some(Geometry::Sphere {
radius: 0.5,
subdivisions: 20,
}),
color: [0.3, 0.7, 1.0, 1.0],
transform: Transform::from_position(0.0, 4.0, 0.0),
..Default::default()
},
None,
);
scene.spawn(
Object {
name: "Ground".to_string(),
str_id: "ground".to_string(),
geometry: Some(Geometry::Plane { size: 12.0 }),
color: [0.3, 0.6, 0.3, 1.0],
transform: Transform::from_position(0.0, 0.0, 0.0),
..Default::default()
},
None,
);
let cube_id = scene.spawn(
Object {
name: "Spinner".to_string(),
str_id: "spinner".to_string(),
geometry: Some(Geometry::Cube { size: 1.0 }),
color: [1.0, 0.5, 0.2, 1.0],
transform: Transform::from_position(3.5, 1.0, 0.0),
..Default::default()
},
None,
);
state.ball_id = Some(ball_id);
state.cube_id = Some(cube_id);
})
.on_fixed_update(|state, scene, ctx| {
const GRAVITY: f32 = -12.0; const RESTITUTION: f32 = 0.78; const GROUND_Y: f32 = 0.5;
if let Some(id) = state.ball_id {
state.ball_vy += GRAVITY * ctx.dt;
if let Some(ball) = scene.world.get_mut(id) {
ball.transform.position[1] += state.ball_vy * ctx.dt;
if ball.transform.position[1] < GROUND_Y {
ball.transform.position[1] = GROUND_Y;
state.ball_vy = state.ball_vy.abs() * RESTITUTION;
if state.ball_vy < 0.2 {
state.ball_vy = 0.0;
}
}
}
}
})
.on_update(|state, scene, ctx| {
if let Some(spinner) = state.cube_id.and_then(|id| scene.world.get_mut(id)) {
spinner.transform.rotation[1] += 90.0 * ctx.dt;
spinner.transform.rotation[0] += 45.0 * ctx.dt;
}
})
.create();
}