rust 如何在Bevy中使用平铺编辑器和Rapier进行多边形碰撞?

5f0d552i  于 2023-05-29  发布在  其他
关注(0)|答案(1)|浏览(175)

我是游戏开发和Rust的新手,所以我可能走错了路。我使用bevy 0.10.1、bevy_ecs_tilemap、bevy_rapier2d和tiled来创建一个包含.tsx文件中指定的冲突的tilemap。我的一些瓷砖使用多边形来定义碰撞对象。我能够让矩形碰撞工作,但多边形碰撞是在错误的位置,有时错误的形状。

if let Some(object_layer) = layer_tile.collision.clone() {
                            let shapes = object_layer
                                .object_data()
                                .iter()
                                .filter_map(|object_data| {
                                    let pos = Vect::new(object_data.x / 2., -object_data.y / 2.);
                                    let rot = object_data.rotation;
                                    let shape = match &object_data.shape {
                                        tiled::ObjectShape::Rect { width, height } => {
                                            Collider::cuboid(width / 2., height / 2.)
                                        }
                                        tiled::ObjectShape::Ellipse { width, height } => {
                                            Collider::capsule_x(width / 2., height / 2.)
                                        }
                                        tiled::ObjectShape::Polyline { points } => {
                                            Collider::polyline(
                                                points
                                                    .iter()
                                                    .map(|(x, y)| Vect::new(*x, *y))
                                                    .collect(),
                                                None,
                                            )
                                        }
                                        tiled::ObjectShape::Polygon { points } => {
                                            Collider::convex_hull(
                                                &points
                                                    .iter()
                                                    .map(|(x, y)| Vect::new(*x, *y))
                                                    .collect::<Vec<_>>(),
                                            )?
                                        }
                                        _ => {
                                            return None;
                                        }
                                    };
                                    Some((pos, rot, shape))
                                })
                                .collect::<Vec<_>>();
                            let world_pos = tile_pos.center_in_world(&grid_size, &map_type);
                            let transform =
                                get_tilemap_center_transform(&map_size, &grid_size, &map_type, 0.)
                                    * Transform::from_xyz(
                                        world_pos.x + offset_x,
                                        world_pos.y - offset_y,
                                        0.,
                                    );
                            if shapes.len() == 1 {
                                let (pos, rot, collider) = shapes[0].clone();
                                let transform = transform
                                    * Transform {
                                        translation: Vec3::new(pos.x, pos.y, 0.),
                                        rotation: Quat::from_rotation_x(rot),
                                        ..default()
                                    };
                                commands
                                    .entity(tile_entity)
                                    .insert((collider, TransformBundle::from_transform(transform)));
                            } else if shapes.len() > 1 {
                                commands.entity(tile_entity).insert((
                                    Collider::compound(shapes),
                                    TransformBundle::from_transform(transform),
                                ));
                            }
                        }

如何将平铺的多边形碰撞数据转换为Rapier碰撞器?还是我把不属于我的工具组合在一起了?

rm5edbpk

rm5edbpk1#

经过多次试验和错误,我想出了如何做到这一点。多边形是颠倒的,我需要把矩形和多边形区别对待。(我的平铺图目前没有椭圆或折线,所以我假设它们的工作原理与其他形状相同。)

if let Some(object_layer) = layer_tile.collision.clone() {
                            let shapes = object_layer
                                .object_data()
                                .iter()
                                .filter_map(|object_data| {
                                    let pos = Vect::new(object_data.x, -object_data.y);
                                    let rot = object_data.rotation;
                                    match &object_data.shape {
                                        tiled::ObjectShape::Rect { width, height } => {
                                            let shape = Collider::cuboid(width / 2., height / 2.);
                                            Some((
                                                pos + Vec2::new(
                                                    (-grid_size.x + width) / 2.,
                                                    (grid_size.y - height) / 2.,
                                                ),
                                                rot,
                                                shape,
                                            ))
                                        }
                                        tiled::ObjectShape::Ellipse { width, height } => {
                                            let shape =
                                                Collider::capsule_x(width / 2., height / 2.);
                                            Some((
                                                pos + Vec2::new(
                                                    (-grid_size.x + width) / 2.,
                                                    (grid_size.y - height) / 2.,
                                                ),
                                                rot,
                                                shape,
                                            ))
                                        }
                                        tiled::ObjectShape::Polyline { points } => {
                                            let shape = Collider::polyline(
                                                points
                                                    .iter()
                                                    .map(|(x, y)| Vect::new(*x, -*y))
                                                    .collect(),
                                                None,
                                            );
                                            Some((
                                                pos + Vec2::new(
                                                    -grid_size.x / 2.,
                                                    grid_size.y / 2.,
                                                ),
                                                rot,
                                                shape,
                                            ))
                                        }
                                        tiled::ObjectShape::Polygon { points } => {
                                            let shape = Collider::convex_hull(
                                                &points
                                                    .iter()
                                                    .map(|(x, y)| Vect::new(*x, -*y))
                                                    .collect::<Vec<_>>(),
                                            )?;
                                            Some((
                                                pos + Vec2::new(
                                                    -grid_size.x / 2.,
                                                    grid_size.y / 2.,
                                                ),
                                                rot,
                                                shape,
                                            ))
                                        }
                                        _ => {
                                            return None;
                                        }
                                    }
                                })
                                .collect::<Vec<_>>();
                            let world_pos = tile_pos.center_in_world(&grid_size, &map_type);
                            let transform =
                                get_tilemap_center_transform(&map_size, &grid_size, &map_type, 0.)
                                    * Transform::from_xyz(
                                        world_pos.x + offset_x,
                                        world_pos.y - offset_y,
                                        0.,
                                    );
                            if shapes.len() == 1 {
                                let (pos, rot, collider) = shapes[0].clone();
                                let transform = transform
                                    * Transform {
                                        translation: Vec3::new(pos.x, pos.y, 0.),
                                        rotation: Quat::from_rotation_x(rot),
                                        ..default()
                                    };
                                commands
                                    .entity(tile_entity)
                                    .insert((collider, TransformBundle::from_transform(transform)));
                            } else if shapes.len() > 1 {
                                commands.entity(tile_entity).insert((
                                    Collider::compound(shapes),
                                    TransformBundle::from_transform(transform),
                                ));
                            }
                        }

相关问题