diff --git a/app/src/main.rs b/app/src/main.rs index 3ff8460..55237e3 100644 --- a/app/src/main.rs +++ b/app/src/main.rs @@ -22,7 +22,10 @@ fn main() { )) .insert_resource(Time::::default().with_relative_speed(5.0)) .insert_resource(DefaultRestitution( - Restitution::PERFECTLY_ELASTIC.with_combine_rule(CoefficientCombine::Max), + Restitution { + coefficient: 0.5, + combine_rule: CoefficientCombine::Average, + } )) .add_systems(Startup, setup) .add_systems( @@ -51,11 +54,50 @@ fn setup( ) { commands.spawn(Camera2d); + setup_pachinko_rail(&mut commands, &mut meshes, &mut materials); + if let Ok(window) = window.single() { spawn_screen_edges(&mut commands, &mut meshes, &mut materials, window.size()); } } +#[derive(Component)] +pub struct PachinkoRail { + pub points: Vec, +} + +fn setup_pachinko_rail(commands: &mut Commands, meshes: &mut Assets, materials: &mut Assets) { + // Control points in world space (y up). The spline passes through each one. + // Bottom-left entry -> straight up the left wall -> arc over the top -> into the pin zone. + let control_points = [ + Vec2::new(-320.0, -260.0), // rail entry (launch point) + Vec2::new(-330.0, -120.0), + Vec2::new(-330.0, 60.0), + Vec2::new(-320.0, 200.0), + Vec2::new(-260.0, 280.0), // start of the top arc + Vec2::new(-160.0, 310.0), + Vec2::new(-60.0, 290.0), // crest, curving down + Vec2::new(0.0, 240.0), // exit: ball drops into the pins here + ]; + + // Catmull-Rom is a cardinal spline with tension 0.5. + // Lower tension = rounder, higher = tighter corners. + let curve = CubicCardinalSpline::new(0.5, control_points) + .to_curve() + .expect("need at least 2 control points"); + + let points: Vec = curve.iter_positions(128).collect(); + + commands.spawn(( + RigidBody::Static, + Collider::polyline(points.clone(), None), + Mesh2d(meshes.add(Polyline2d::new(points.iter().copied()))), + MeshMaterial2d(materials.add(Color::srgb_u8(255, 255, 255))), + Transform::from_xyz(0.0, 0.0, 0.0), + PachinkoRail { points }, + )); +} + #[derive(Component, Clone, Copy)] struct Ball; @@ -75,10 +117,12 @@ fn spawn_ball( && let Some(cursor_position) = window.cursor_position() && let Ok(world_position) = camera.viewport_to_world_2d(camera_transform, cursor_position) { + println!("world_position: {:?}", world_position); + commands.spawn(( RigidBody::Dynamic, Collider::circle(CIRCLE_RADIUS), - LinearVelocity(Vec2::new(time.elapsed_secs().sin(), time.elapsed_secs().cos()) * 100.0), + LinearVelocity(Vec2::new(-100.0, 200.0)), Mesh2d(meshes.add(Circle::new(CIRCLE_RADIUS))), MeshMaterial2d(materials.add(Color::hsl(time.elapsed_secs().sin() * 360.0, 1.0, 0.5))), Transform::from_xyz(world_position.x, world_position.y, 0.0),