游戏开发中的物理介绍(2)

简介: 游戏开发中的物理介绍

Area2D


区域节点提供检测和影响。它们可以检测物体何时重叠并在物体进入或离开时发出信号。区域还可以用于覆盖定义区域中的物理属性,例如重力或阻尼。


Area2D有三个主要用途:


给定区域中的替代物理参数(例如重力)。

检测其他物体何时进入或离开区域或当前区域中有哪些物体。

检查其他区域是否重叠。

默认情况下,区域还接收鼠标和触摸屏输入。


StaticBody2D


静态物体是物理引擎不会移动的物体。它参与碰撞检测,但不会响应碰撞而移动。但是,它可以利用其和属性为碰撞的物体提供运动或旋转,就好像它在运动一样。constant_linear_velocityconstant_angular_velocity


StaticBody2D 节点最常用于环境中的对象或不需要任何动态行为的对象。


示例用于StaticBody2D:


平台(包括移动平台)

输送带

墙壁和其他障碍

RigidBody2D


这是实现模拟2D物理的节点。您不能直接控制 RigidBody2D。取而代之的是,您对其施加力,然后物理引擎会计算出最终的运动,包括与其他物体的碰撞以及碰撞响应(如弹跳,旋转等)。


您可以通过“质量”,“摩擦”或“弹跳”之类的属性来修改刚体的行为,这些属性可以在检查器中设置。


人体的行为也会受到世界属性(如在“ 项目设置”->“物理”中设置的)的影响,或者受输入 覆盖全球物理属性的Area2D的影响。


当刚体处于静止状态并且一段时间未移动时,它将进入睡眠状态。睡眠物体的作用类似于静态物体,其力不是由物理引擎计算的。当通过碰撞或通过代码施加力时,身体将醒来。


刚体模式

刚体可以设置为以下四种模式之一:


刚性-身体表现为物理对象。它会与其他物体碰撞,并对其施加的力作出反应。这是默认模式。

静态-主体的行为类似于StaticBody2D,并且不会移动。

角色-与“刚性”模式相似,但身体无法旋转。

运动-身体的行为类似于KinematicBody2D,必须通过代码移动。

使用RigidBody2D

使用刚体的好处之一是无需编写任何代码即可“免费”获得许多行为。例如,如果您要制作带有下降块的“愤怒的小鸟”式游戏,则只需创建RigidBody2Ds并调整其属性。堆积,下落和弹跳将由物理引擎自动计算。


但是,如果你想有过身体有一定的控制,你应该照顾-改变position,linear_velocity,刚体的或其他物理性质可能会导致意外的行为。如果您需要更改任何与物理学相关的属性,则应使用_integrate_forces() 回调而不是_physics_process()。在此回调中,您可以访问人体的Physics2DDirectBodyState,它可以安全地更改属性并将其与物理引擎同步。


例如,以下是“小行星”式太空飞船的代码:


class Spaceship : RigidBody2D
{
    private Vector2 _thrust = new Vector2(0, 250);
    private float _torque = 20000;
    public override void _IntegrateForces(Physics2DDirectBodyState state)
    {
        if (Input.IsActionPressed("ui_up"))
            SetAppliedForce(_thrust.Rotated(Rotation));
        else
            SetAppliedForce(new Vector2());
        var rotationDir = 0;
        if (Input.IsActionPressed("ui_right"))
            rotationDir += 1;
        if (Input.IsActionPressed("ui_left"))
            rotationDir -= 1;
        SetAppliedTorque(rotationDir * _torque);
    }
}

请注意,我们不是 直接设置linear_velocity或angular_velocity属性,而是将力(thrust和torque)施加到物体上,然后让物理引擎计算出所产生的运动。


注意

当刚体进入睡眠状态时,_integrate_forces()

将不会调用该功能。要覆盖此行为,您将需要通过创建碰撞,向其施加力或禁用can_sleep

属性来使身体保持清醒状态。请注意,这可能会对性能产生负面影响。

联系人报告

默认情况下,刚体不跟踪接触,因为如果场景中有很多刚体,这可能需要大量的内存。若要启用联系人报告,请将contacts_reported 属性设置为非零值。然后可以通过Physics2DDirectBodyState.get_contact_count()和相关函数来获取联系人 。


可以通过contact_monitor 属性启用通过信号的接触监视。有关可用信号的列表,请参见RigidBody2D。


KinematicBody2D


KinematicBody2D实体可以检测与其他实体的碰撞,但不受重力或摩擦等物理属性的影响。相反,它们必须由用户通过代码控制。物理引擎不会移动运动体。


移动运动机构时,请勿position直接设置它。而是使用move_and_collide()ormove_and_slide()方法。这些方法沿着给定的矢量移动物体,如果检测到与另一个物体的碰撞,它将立即停止。身体碰撞后,任何碰撞响应都必须手动编码。


运动碰撞响应

发生碰撞后,您可能希望身体反弹,沿墙滑动或改变其撞击的对象的属性。处理碰撞响应的方式取决于您用来移动KinematicBody2D的方法。


move_and_collide

使用时move_and_collide(),该函数返回 KinematicCollision2D对象,该对象包含有关碰撞和碰撞体的信息。您可以使用此信息来确定响应。


例如,如果要查找空间中发生碰撞的点:


class Body : KinematicBody2D
{
    private Vector2 _velocity = new Vector2(250, 250);
    public override void _PhysicsProcess(float delta)
    {
        var collisionInfo = MoveAndCollide(_velocity * delta);
        if (collisionInfo != null)
        {
            var collisionPoint = collisionInfo.GetPosition();
        }
    }
}


或从碰撞对象反弹:


class Body : KinematicBody2D
{
    private Vector2 _velocity = new Vector2(250, 250);
    public override void _PhysicsProcess(float delta)
    {
        var collisionInfo = MoveAndCollide(_velocity * delta);
        if (collisionInfo != null)
            _velocity = _velocity.Bounce(collisionInfo.Normal);
    }
}
move_and_slide


滑动是一种常见的碰撞反应。想象一个玩家在自上而下的游戏中沿着墙壁移动,或者在平台游戏中在斜坡上上下移动。虽然可以使用后,自己编写这种反应move_and_collide(), move_and_slide()提供了实现滑动,而无需编写大量代码的便捷方式。


警告

move_and_slide()自动包括在计算中时间步长,所以应该没有乘法的速度矢量通过delta。

例如,使用以下代码制作一个可以在地面上行走(包括斜坡)并在站立在地面上时可以跳跃的角色:

class Body : KinematicBody2D
{
    private float _runSpeed = 350;
    private float _jumpSpeed = -1000;
    private float _gravity = 2500;
    private Vector2 _velocity = new Vector2();
    private void GetInput()
    {
        _velocity.x = 0;
        var right = Input.IsActionPressed("ui_right");
        var left = Input.IsActionPressed("ui_left");
        var jump = Input.IsActionPressed("ui_select");
        if (IsOnFloor() && jump)
            _velocity.y = _jumpSpeed;
        if (right)
            _velocity.x += _runSpeed;
        if (left)
            _velocity.x -= _runSpeed;
    }
    public override void _PhysicsProcess(float delta)
    {
        _velocity.y += _gravity * delta;
        GetInput();
        _velocity = MoveAndSlide(velocity, new Vector2(0,-1));
    }
}


有关使用的更多详细信息,请参见运动字符(2D)move_and_slide(),包括带有详细代码的演示项目。

目录
相关文章
游戏开发中的物理之使用KinematicBody2D(02)
游戏开发中的物理之使用KinematicBody2D
211 0
游戏开发中的物理之使用KinematicBody2D(02)
|
1天前
|
vr&ar Python
物理电学:基础概念与模拟实践
物理电学:基础概念与模拟实践
|
1天前
|
Python
物理力学:基本概念、原理及计算机模拟实践
物理力学:基本概念、原理及计算机模拟实践
|
1月前
|
数据采集 算法 C++
物理电学的编程
物理电学的编程
14 1
|
1月前
|
存储 人工智能 并行计算
计算机架构:漫游CPU的奥秘世界(二)
计算机架构:漫游CPU的奥秘世界
53 0
|
1月前
|
存储 人工智能 缓存
计算机架构:漫游CPU的奥秘世界(一)
计算机架构:漫游CPU的奥秘世界
62 0
|
1月前
|
C++ 开发者 Python
物理力学的编程
物理力学的编程
11 0
游戏开发中的物理介绍(1)
游戏开发中的物理介绍
139 0
游戏开发中的物理介绍(1)
|
存储
游戏开发中的物理之使用KinematicBody2D(01)
游戏开发中的物理之使用KinematicBody2D
191 0
游戏开发中的物理之使用KinematicBody2D(01)
游戏开发中的物理之布娃娃系统
游戏开发中的物理之布娃娃系统
281 0
游戏开发中的物理之布娃娃系统