• 怪物AI(复习)


    怪物AI执行
    //-----------------------------------------------主动攻击------------------------------------------------------
    初始状态
    attack_style      Enum攻击方式              Enum主动攻击
    MonsterStat          EnumMonsterStat          EnumMonster游荡
    Monter被动Stat    EnumMonster被动Stat     EnumMonster被动NULL
    
    玩家移动或者进入地图,都会通知附近玩家以及在怪物的map_nearby_player容器中加入此玩家
    然后在action中_updateAttachObjsAndStat()中扫描扫描附近玩家,如果怪物是主动攻击类型就将其加入m_attach_objs容器中,并置curStat当前状态为EnumMonster追击
    然后根据相应的状态执行相应的动作
    追击过程:
    1.auto pl = get_attach_obj(m_attach_objs);//根据仇恨值获取攻击对象
    2.加载路线
    不在四周,加载路线,单步的,如果遇到障碍则会执行传奇的绕道算法,这种算法是单步比A*算法效率高,A*算法图相对是固定的,但游戏中怪物是移动的。
    3.怪物发现人物在四周,开始攻击:
    if(pl->second.distance <= 1)//如何玩家在怪物的四周
    {
        if(!(rand() % 2))
        {//攻击玩家
            AttackPt att;
            att.srcID = objId;
            att.tgtID = pl->second.obj->objId;
            att.skill_id =  普通攻击;//(nBodyID == 1003)? 9004 : 9005;
            att.way = 1;//直接攻击
            m_map->attach(att, this, pl->second.obj);
            //找到目标,取消追踪路线
            m_trace_line.clear();
            is_move = false;        
        }
        if(pl->second.obj->stat.cur_hp <= 0)
        {
            cancle_attached();//此时人被打死,
        }
        return false;
    }
    
    void MonsterObj::cancle_attached()
    {
        m_is_attached = false;//玩家已死,取消攻击记录
        m_attach_objs.clear();//取消攻击记录
        m_trace_line.clear();
        is_move = false;
        MonsterStat = EnumMonsterStat::EnumMonster回家;
    }
    4.当把人打死了就把状态置为回家,回到怪物的出生地
    void MonsterObj::回家()
    {
        if(rand() % 100 > 30)//30%的概率移动
            return;
        pos2d obj_t_mpos = _getTgtMapPos();
        if(!is_move)
        {
            if(!m_finder->FindPath(obj_t_mpos.x, obj_t_mpos.y, base_mpos.x, base_mpos.y))
                return;
            m_finder->GetPath(m_trace_line);
        }
    
        //路线走完 或者 在出生点周围
        if(m_trace_line.empty() /*|| isAround(当前位置,base_mpos)*/)
        {
            cancle_goback();
            return;
        }
        pos2d next_mpos = m_trace_line.front();
        //如果下一步不可以通过则(临时有怪物阻挡,所以要加判断)
        if(isFreeMap(next_mpos.x, next_mpos.y))
        {
            auto old_bpos = _getBlockPos();
            if(execute_trace_line())
                _notify(old_bpos, _getBlockPos());
        }
    }
    
    5.线路走完
    if(m_trace_line.empty() /*|| isAround(当前位置,base_mpos)*/)
    {
        cancle_goback();//取消回家
        return;
    }
    
    6.又开始游荡
    void MonsterObj::cancle_goback()//取消回家计划
    {
        //①取消回家路线
        m_trace_line.clear();
        is_move = false;
        MonsterStat = EnumMonsterStat::EnumMonster游荡;
    }
    
    //---------------------------------------------胆小的--------------------------------------------------------
    胆小的
    刚开始时游荡和没有被动状态
    当收到攻击时就把状态为逃跑
    当逃跑线路走完时就取消攻击
    void MonsterObj::cancle_attached()
    {
        m_is_attached = false;//玩家已死,取消攻击记录
        m_attach_objs.clear();//取消攻击记录
        m_trace_line.clear();
        is_move = false;
        MonsterStat = EnumMonsterStat::EnumMonster回家;
    }
    然后就回家
    回家之后开始游荡
    
    //----------------------------------------------被动的----------------------------------------------------------
    //被动的(类似的)
    被动的
    游荡->被打了(追击)->把人打死了->回家->游荡
    
    //-----------------------------------------------关于怪物被玩家打-----------------------------------------------
    //关于被动的被玩家打
    playchannel中attach,然后
    auto pl_old = m_attach_objs.find(attacher->objId);
    if(pl_old != m_attach_objs.end())
        pl_old->second.hurt += hurt;//伤害积累,仇恨
    else//
    {
        AttObject attobj = {hurt, -1, att_pl};
        m_attach_objs[att_pl->objId] = attobj;//加入了攻击对象
    }
    m_is_attached = true;
    is_move = false;//优先追踪被攻击的玩家。
    
    if(Monster被动State != EnumMonster被冲撞) //因为被撞和被打回产生冲突
        Monster被动State = EnumMonster被攻击; //停顿下
    
    死亡之后经过60秒,这样根据运行AI的速度,如果运行速度是1000ms那就是,60s
    
    置为重生状态
    
    重生之后使其游荡

    今天看到那个定时器是100ms,然后运行60次怎么回事1分钟,找了半天原来现在怪物有了速度的概念

    bool NPC::isRunAI()
    {
        unsigned int now = GetTickCount();
        if(now - cur_run_time < cur_run_speed//当时看这个正好是1000,所以本来是100ms的,强制成了1s,我找了半天才知道咋回事。
        {
            return false;
        }
        cur_run_time = now;
        return true;
    }
  • 相关阅读:
    CentOS下用yum命令安装jdk【转】
    Maven中的-D(Properties属性)和-P(Profiles配置文件)
    Mac Maven配置
    MVC从路由到Controller运行机制
    IIS与ASP.NET对请求的处理
    免费SSL证书(支持1.0、1.1、1.2)
    C#创建服务及使用程序自动安装服务,.NET创建一个即是可执行程序又是Windows服务的exe
    InstallShield Limited Edition Project 打包windows服务解析
    InstallShield Limited Edition使用说明
    因为数据库正在使用,所以无法获得对数据库的独占访问权---还原或删除数据库的解决方法
  • 原文地址:https://www.cnblogs.com/zzyoucan/p/3925480.html
Copyright © 2020-2023  润新知