游戏开发中的物理之运动角色(2D)

举报
海拥 发表于 2021/12/06 15:17:55 2021/12/06
【摘要】 🌊 作者主页:海拥🌊 简介:🏆CSDN全栈领域优质创作者、🥇HDZ核心组成员、🥈蝉联C站周榜前十🌊 粉丝福利:粉丝群 每周送六本书,不定期送各种小礼品,往期获奖公布 介绍是的,这个名字听起来很奇怪。“运动角色”。那是什么?该名称的原因是,当物理引擎问世时,它们被称为“动态”引擎(因为它们主要处理碰撞响应)。为了使用动态引擎创建角色控制器,已经进行了许多尝试,但是这并不像看起来那样...

🌊 作者主页:海拥
🌊 简介:🏆CSDN全栈领域优质创作者、🥇HDZ核心组成员、🥈蝉联C站周榜前十
🌊 粉丝福利:粉丝群 每周送六本书,不定期送各种小礼品,往期获奖公布

介绍

是的,这个名字听起来很奇怪。“运动角色”。那是什么?该名称的原因是,当物理引擎问世时,它们被称为“动态”引擎(因为它们主要处理碰撞响应)。为了使用动态引擎创建角色控制器,已经进行了许多尝试,但是这并不像看起来那样容易。Godot是您可以找到的最佳动态角色控制器实现之一(如在2d / platformer演示中所见),但是使用它需要相当水平的技能和对物理引擎的理解(或者非常耐心尝试错误)。

诸如Havok之类的某些物理引擎似乎认为动态角色控制器是最佳选择,而其他物理引擎(PhysX)则更愿意推广运动学引擎。

那么区别是什么呢?:

甲动态字符控制器采用刚性体具有无限惯性张量。这是一个不能旋转的刚体。物理引擎总是让物体移动和碰撞,然后一起解决它们的碰撞。如平台游戏演示所示,这使动态角色控制器能够与其他物理对象无缝交互。但是,这些交互并非总是可预测的。碰撞可能需要一帧以上的时间才能解决,因此一些碰撞似乎只位移了一小部分。这些问题可以解决,但需要一定的技能。
一个运动人物控制器被假定为总是在非碰撞状态开始,并且会一直移动到非冲突状态。如果它开始处于碰撞状态,它将尝试像刚体一样释放自身,但这是例外,而不是规则。这使得它们的控制和运动更加可预测且易于编程。但是,不利的是,除非手动编写代码,否则它们无法直接与其他物理对象进行交互。
这个简短的教程将集中于运动字符控制器。基本上,这是老式的处理冲突的方式(不一定在幕后变得更简单,而是被很好地隐藏起来并作为一个很好的简单API呈现)。

物理过程

为了管理运动体或角色的逻辑,始终建议使用物理过程,因为它在物理步骤之前被调用,并且其执行与物理服务器同步,也总是被称为每秒相同的次数。与使用常规过程相比,这使物理和运动计算的工作方式更具可预测性,如果帧率太高或太低,则常规过程可能会出现尖峰或失去精度。

using Godot;
using System;

public class PhysicsScript : KinematicBody2D
{
    public override void _PhysicsProcess(float delta)
    {
    }
}

场景设定

有一些测试,这里的场景(从tilemap的教程) kbscene.zip。我们将为角色创建一个新场景。使用机器人精灵创建一个这样的场景:

../../_images/kbscene.png

您会注意到,我们的CollisionShape2D节点旁边有一个警告图标。这是因为我们尚未为其定义形状。在CollisionShape2D的shape属性中创建一个新的CircleShape2D。单击<CircleShape2D>转到其选项,并将半径设置为30:

../../_images/kbradius.png

注意:如之前在物理教程中所述,物理引擎无法处理大多数形状的比例(仅碰撞多边形,平面和线段有效),因此请始终更改形状的参数(例如半径),而不是缩放它。运动/刚体/静态物体本身也是如此,因为它们的比例会影响形状比例。

现在,为角色创建一个脚本,上面用作示例的脚本应作为基础。

最后,在tilemap中实例化该角色场景,并将其作为主要场景,以便在按下play时运行。

../../_images/kbinstance.png

运动学特征

回到角色场景,打开脚本,魔术开始了!运动体默认情况下不执行任何操作,但它具有一个有用的功能,称为 KinematicBody2D.move_and_collide()。此函数将Vector2用作参数,然后尝试将该运动应用于运动体。如果发生碰撞,它会在碰撞发生时立即停止。

因此,让我们向下移动精灵,直到它掉到地上:

using Godot;
using System;

public class PhysicsScript : KinematicBody2D
{
    public override void _PhysicsProcess(float delta)
    {
        // Move down 1 pixel per physics frame
        MoveAndCollide(new Vector2(0, 1));
    }
}

结果是角色将移动,但在撞击地板时会立即停止。太酷了吧?

下一步是将重力添加到混合中,这样,它的行为就有点像常规游戏角色:

using Godot;
using System;

public class PhysicsScript : KinematicBody2D
{
    const float gravity = 200.0f;
    Vector2 velocity;

    public override void _PhysicsProcess(float delta)
    {
        velocity.y += delta * gravity;

        var motion = velocity * delta;
        MoveAndCollide(motion);
    }
}

现在,角色平稳滑落。让我们在触摸方向键时向左右两侧行走。请记住,所使用的值(至少对于速度而言)是像素/秒。

这可以通过向左和向右按下来增加简单的步行支撑:

using Godot;
using System;

public class PhysicsScript : KinematicBody2D
{
    const float gravity = 200.0f;
    const int walkSpeed = 200;

    Vector2 velocity;

    public override void _PhysicsProcess(float delta)
    {
        velocity.y += delta * gravity;

        if (Input.IsActionPressed("ui_left"))
        {
            velocity.x = -walkSpeed;
        }
        else if (Input.IsActionPressed("ui_right"))
        {
            velocity.x = walkSpeed;
        }
        else
        {
            velocity.x = 0;
        }
        MoveAndSlide(velocity, new Vector2(0, -1));
    }
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。