AI - Steering behaviors(转向系统)

游戏AI角色的转向系统(Steering behaviors)实现

一些向量的接口是cocos2dx的。但从名字上应该能理解做了什么向量操作

Seek:

获取当前位置指向目标点的向量,转化为单位向量后再乘以速度值,即为所需速度desired velocity,所需速度减去当前速度current velocity,即为seek的转向力,将角色推向目标
在这里插入图片描述

//追逐转向力
Vec2 MoveNode::seek(Vec2 seekPos){
   
   
    if (seekPos == Vec2(-1, -1)) return Vec2::ZERO;
    Vec2 normalVector = (seekPos - this->getPosition()).getNormalized();
    float dist = this->getPosition().getDistance(seekPos);
    Vec2 desiredVelocity = normalVector * _dtSpeed;
    Vec2 steering;
    if (MoveSmooth) steering = desiredVelocity - _velocity;
    else steering = desiredVelocity;
    return steering;
}

在这里插入图片描述

物体在追逐目标时,会有一个逐渐转弯的过程
请添加图片描述

如果,没有转向力的话,物体就是直接切换方向
请添加图片描述

Flee

与seek类似,只是所需速度desired velocity的方向,是由目标点指向当前位置。
在这里插入图片描述
这里在逃离目标点加了个检测半径,在这个范围里的物体将会受到逃离力。

//躲避转向力
Vec2 MoveNode::flee() {
   
   
    Vec2 steering = Vec2::ZERO;
    if(_fleePos == Vec2::ZERO) return steering;
    if (this->getPosition().getDistance(_fleePos) < _fleeRadius) {
   
   
        Vec2 normalVector = (this->getPosition() - _fleePos).getNormalized();
        Vec2 desiredVelocity = normalVector * _dtSpeed;
        if (MoveSmooth) steering = desiredVelocity - _velocity;
        else steering = desiredVelocity;
    }
    return steering;
}

在这里插入图片描述
逃离时的转向效果
请添加图片描述
与没有转向力直接逃离的效果对比
请添加图片描述

Arrive

因为seek力的存在,所以在到达目标点时,会在目标点附近来回弹跳
请添加图片描述
为此在目标点周围添加一个减速场slowing area。在目标点周围一定范围内,当物体越靠近目标时,seek力会越小。seek力大小在减速带范围内线性减小,与目标点的距离成反比。而在范围外,则是正常的seek力大小
在这里插入图片描述

//追逐转向力
Vec2 MoveNode::seek(Vec2 seekPos){
   
   
    if (seekPos == Vec2(-1, -1)) return Vec2::ZERO;
    Vec2 normalVector = (seekPos - this->getPosition()).getNormalized();
    float dist = this->getPosition().getDistance(seekPos);
    Vec2 desiredVelocity = normalVector * _dtSpeed;

    //靠近目标减速带
    if (dist < _tarSlowRadius) desiredVelocity *= (dist / _tarSlowRadius);

    Vec2 steering;
    if (MoveSmooth) steering = desiredVelocity - _velocity;
    else steering = desiredVelocity;
    return steering;
}

请添加图片描述

Wander

漫游:巡逻,在物体前进方向的前方一定范围_circleDistance内,画个圆,用来计算受力行为。位移力 以圆心为原点,受半径_circleRadius约束。半径越大以及角色到圆圈的距离越大,角色在每个游戏帧中受到的“推力”就越强。

在这里插入图片描述
初始会给一个方向wander angle,之后每帧会在一定的转向范围_changeAngle内随机一个转角方向。改变物体巡逻的方向wander angle在这里插入图片描述在这里插入图片描述在这里插入图片描述
我在这里加了一个巡逻范围_wanderPullBackSteering,当偏离一定范围时,会受到回拉的力

Vec2 MoveNode::changeAngle(Vec2 vector, float angle) {
   
   
    float rad = angle * M_PI / 180;
    float len = vector.getLength();
    Vec2 v;
    v.x = len * cos(rad);
    v.y = len * sin(rad);
    return v;
}

Vec2 MoveNode::wander() {
   
   
    if (_wanderPos == Vec2(-1, -1)) return Vec2::ZERO;
    Vec2 circleCenter = _velocity.getNormalized();
    circleCenter *= _circleDistance;

    Vec2 displacement = Vec2(0, -1);
    displacement *= _circleRadius;
    displacement = changeAngle(displacement, _wanderAngle);

    float randomValue = RandomHelper::random_real<float>(-0.5f, 0.5f);
    _wanderAngle = _wanderAngle + randomValue * _changeAngle;

    Vec2 wanderForce 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值