Rust에서 게임 만들기 - 3부 - 바닥과 중력

14409 단어 rusttutorialrapierbevy
이제 , 및 가 있으므로 캐릭터를 쓰러뜨릴 차례입니다. 이 문서에서는 중력을 추가하여 플레이어가 공중에 있을 때 지면을 향해 당기고, 지면과 만나면 멈추게 하는 방법에 대해 설명합니다.

이론



우리의 최종 목표는 현실적인 움직임을 갖는 것입니다. 이것은 보기보다 복잡한 문제입니다. 다음과 같은 방법이 필요합니다.
  • 플레이어가 표면(바닥)과 접촉하고 있음을 감지합니다.
  • 플레이어가 땅에 닿지 않을 때 넘어지게 합니다.

  • 구현을 용이하게 하기 위해(물리학은 어려울 수 있음) 물리학 라이브러리를 가져올 것입니다: Rapier . Rapier를 사용하면 중력을 쉽게 시뮬레이션할 수 있고 충돌 감지(플레이어가 공중에 있거나 표면과 접촉할 때 감지)를 처리할 수 있습니다.

    중력 추가



    1단계: bevy_rapier2dcargo.toml 파일에 추가합니다.

    [dependencies]
    bevy = "0.5"
    bevy_rapier2d = "0.11.0"
    

    2단계: 애플리케이션에 Rapier 플러그인 등록:

    // main.rs
    use bevy_rapier2d::prelude::*;
    
    // ...
        App::build()
            // ...
            .add_plugin(RapierPhysicsPlugin::<NoUserData>::default())
    

    3단계: 플레이어에 충돌체 및 강체 구성요소 추가:

    fn spawn_player(mut commands: Commands, mut materials: ResMut<Assets<ColorMaterial>>) {
        let rigid_body = RigidBodyBundle {
            mass_properties: RigidBodyMassPropsFlags::ROTATION_LOCKED.into(),
            activation: RigidBodyActivation::cannot_sleep(),
            ccd: RigidBodyCcd { ccd_enabled: true, ..Default::default() },
            ..Default::default()
        };
        let collider = ColliderBundle {
            shape: ColliderShape::cuboid(0.5, 0.5),
            flags: ColliderFlags {
                active_events: ActiveEvents::CONTACT_EVENTS,
                ..Default::default()
            },
            ..Default::default()
        };
        commands
            .spawn_bundle(SpriteBundle {
                material: materials.add(Color::rgb(0.7, 0.7, 0.7).into()),
                sprite: Sprite::new(Vec2::new(1.0, 1.0)),
                ..Default::default()
            })
            .insert_bundle(rigid_body)
            .insert_bundle(collider)
            .insert(RigidBodyPositionSync::Discrete)
            .insert(Player);
    }
    

    여기에서 많은 일이 진행 중이므로 무슨 일이 일어나고 있는지 설명하겠습니다.

    Arigid body는 우리 개체의 역학 및 운동학(힘으로 인한 동작 및/또는 동작)을 담당합니다. 이 경우 다음 속성을 사용하여 기본RigidBodyBundle을 만들었습니다.
  • mass_properties : ROTATION_LOCKED 속성은 Rapier가 플레이어에 회전력을 적용하는 것을 방지합니다.
  • activation : Rapier는 움직이지 않는 물체가 충분히 움직이지 않으면 잠자는 것으로 표시합니다. Rapier는 물리학을 시뮬레이션할 때 "잠자는"개체를 무시합니다. 이 방지 설정은 잠자는 개체에 의해 트리거되는 원치 않는 동작을 방지합니다.
  • ccd : 플레이어에서 충돌 감지를 활성화합니다. 나중에 자세히 설명합니다.

  • Acollider는 충돌 감지를 담당합니다. 충돌기는 또한 물체의 모양과 질량을 정의합니다(물리를 시뮬레이션하는 경우 중요). 이 경우 다음 속성을 사용하여 기본ColliderBundle을 만들었습니다.
  • shape : 플레이어의 모양. 여기, 광장입니다. 충돌기 모양의 x 및 y 구성 요소는 길이가 절반입니다. 그걸 알아내는데 시간이 좀 걸렸다...
  • flags : 충돌기에서 활성화할 기능입니다. 제공된 코드는 CONTACT_EVENTS 를 활성화합니다. 자세한 내용은 나중에 설명합니다.

  • 우리의 코드는 RigidBodyPositionSync::Discrete 구성 요소와 함께 강체와 충돌기 번들을 플레이어에 추가합니다. 이 구성 요소는 Bevy의 변환(위치)을 강체의 위치와 동기화합니다.

    터미널에서 cargo run를 실행하면 플레이어가 창 하단의 심연으로 떨어지는 것을 볼 수 있습니다.

    바닥



    플레이어 아래에 층을 추가해 보겠습니다.

    // ...
    .add_startup_stage("floor_setup", SystemStage::single(spawn_floor.system()))
    // ...
    
    fn spawn_floor(mut commands: Commands, mut materials: ResMut<Assets<ColorMaterial>>) {
        let width = 10.;
        let height = 1.;
        let rigid_body = RigidBodyBundle {
            position: Vec2::new(0.0, -2.).into(),
            body_type: RigidBodyType::Static,
            ..Default::default()
        };
        let collider = ColliderBundle {
            shape: ColliderShape::cuboid(width / 2., height / 2.),
            ..Default::default()
        };
        commands
            .spawn_bundle(SpriteBundle {
                material: materials.add(Color::rgb(0.7, 0.7, 0.7).into()),
                sprite: Sprite::new(Vec2::new(width, height)),
                ..Default::default()
            })
            .insert_bundle(rigid_body)
            .insert_bundle(collider)
            .insert(RigidBodyPositionSync::Discrete);
    }
    
    cargo run를 실행하면 플레이어가 땅에 떨어지는 것을 보고 그대로 있어야 합니다.



    이 코드는 다른 코드와 매우 유사합니다. 한 가지 차이점은 강체의 body_type: RigidBodyType::Static 속성입니다. 이것은 Rapier에게 우리 바닥이 절대 움직이지 않을 것이라고 알려줍니다.

    모든 코드를 사용할 수 있습니다here.

    1 부:




    2 부:


    좋은 웹페이지 즐겨찾기