Skip to content

Instantly share code, notes, and snippets.

@zeddash
Created August 9, 2025 22:58
Show Gist options
  • Save zeddash/a52735835396ca3c67824dbf014aa264 to your computer and use it in GitHub Desktop.
Save zeddash/a52735835396ca3c67824dbf014aa264 to your computer and use it in GitHub Desktop.
fn midpoint_of_points(
points: &Vec<Vec2>,
) -> Vec2 {
if points.is_empty() {
return Vec2::ZERO;
}
let mut min_point = points[0];
let mut max_point = points[0];
for &point in points.iter().skip(1) {
min_point = Vec2::new(
min_point.x.min(point.x),
min_point.y.min(point.y),
);
max_point = Vec2::new(
max_point.x.max(point.x),
max_point.y.max(point.y),
);
}
(min_point + max_point) * 0.5
}
/// Round polyline with translation such that coordinates given line up with the placement in the world
fn round_polyline(
points: Vec<Vec2>,
radius: f32,
) -> Option<(Collider, Transform)> {
match points.len() {
0 => None,
1 => Some((
Collider::circle(radius),
Transform::from_xyz(points[0].x, points[0].y, 0.0),
)),
_ => {
let midpoint = midpoint_of_points(&points);
let mapped: Vec<Vec2> = points
.iter()
.map(|point| point - midpoint)
.collect();
let capsules: Vec<_> =
mapped
.windows(2)
.map(|w| {
(
Position::from_xy(0.0, 0.0),
Rotation::radians(0.0),
Collider::capsule_endpoints(radius, w[0], w[1]),
)
}
).collect();
Some((
Collider::compound(capsules),
Transform::from_xyz(midpoint.x, midpoint.y, 0.0),
))
}
}
}
/// Round polyline to create a shape, only preserves relative distances
fn round_polyline_shape(
points: Vec<Vec2>,
radius: f32,
) -> Option<Collider> {
match points.len() {
0 => None,
1 => Some(
Collider::circle(radius)
),
_ => {
let capsules: Vec<_> =
points
.windows(2)
.map(|w| {
(
Position::from_xy(0.0, 0.0),
Rotation::radians(0.0),
Collider::capsule_endpoints(radius, w[0], w[1]),
)
}
).collect();
Some(
Collider::compound(capsules),
)
}
}
}
fn usage(
mut commands: Commands,
) {
if let Some((collider, transform)) = round_polyline(
vec![Vec2::new(-200.0,100.0), Vec2::new(-150.0,0.0), Vec2::new(0.0,-100.0), Vec2::new(150.0,0.0), Vec2::new(200.0,100.0)],
1.0,
) {
commands.spawn((
collider,
transform, // Points line up to what is given
RigidBody::Static,
));
}
if let Some(collider) = round_polyline_shape(
vec![Vec2::new(-200.0,100.0), Vec2::new(-150.0,0.0), Vec2::new(0.0,-100.0), Vec2::new(150.0,0.0), Vec2::new(200.0,100.0)],
1.0,
) {
commands.spawn((
collider,
Transform::from_xyz(50.0, 0.0, 0.0),
RigidBody::Static,
));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment