c++20协程下

参考地址
先看py实现的火球/闪电技能.用协程更函数式,而面向对象则要存储中间状态.

#创建实例
定义 技能实例跑函数(实例,用户,技能数据,目标,目标位置,完成函数):
    #此处置`中回调`
    产生 任务置退出回调(完成函数)
    #...
    从 常见.游戏时间 导入 游戏时间
    初化时间=游戏时间.现在时间
    对 技能步 在 步列表:
        步开始时间=游戏时间.现在时间
        #...
        #1,处理任务
        如 技能步.转换类型==转换技能步.转换类型时期:
            如 长度(技能步.转换动作组列表)>0:
                动作组=技能步.转换动作组列表[0]
                对 i 在 区间(技能步.转换数):
                    #产生休息
                    产生 休息任务(技能步.转换时期)
                    中值=干花费技能(技能数据,用户,实例)
                    如 不 中值:
                        中
                    干一转换技能(技能数据,技能步,动作组,用户,实例,目标标识,目标位置)

        #2,导弹技能
        异如 技能步.转换类型==转换技能步.转换类型导弹到目标:
            如 长度(技能步.转换动作组列表)>0:
                动作组=技能步.转换动作组列表[0]
                对 i 在 区间(技能步.转换数):
                    #产生休息
                    产生 休息任务(技能步.转换时期)
                    中值=干花费技能(技能数据,用户,实例)
                    如 不 中值:
                        中
                    #子协程(导弹处理函数)
                    任务标识=产生 新任务(导弹处理函数(技能数据,实例,用户,技能步,动作组,目标标识,目标位置))
                    实例.加子任务标识(任务标识)

        #3,导引技能
        异如 技能步.转换类型==转换技能步.转换类型导引到目标:
            如 长度(技能步.转换动作组列表)>0:
                #...
                对 i 在 区间(技能步.转换数):
                    #产生休息
                    产生 休息任务(技能步.转换时期)
                    中值=干花费技能(技能数据,用户,实例)
                    如 不 中值:
                        中
                    干一转换技能(技能数据,技能步,动作组,用户,实例,第一目标.对象标识,第一目标.取位置())
                    起始位置=技能步.导引信息.取目标位置(用户,开始标识,起始位置)[0]
                    尾位置=技能步.导引信息.取目标位置(用户,第一目标.对象标识,第一目标.取位置())[0]
                    尾标识=第一目标.对象标识
                    #子协程(导引处理函数)
                    任务标识=产生 新任务(导引处理函数(技能数据,实例,用户,技能步,起始位置,尾标识,尾位置))
                    起始位置=尾位置
                    开始标识=尾标识
                    实例.加子任务标识(任务标识)

                    第一目标=无
                    如 导引目标列表:
                        弹索引=随机.随机区间(0,长度(导引目标列表))
                        第一目标=导引目标列表.弹(弹索引)
                    如 不 第一目标:
                        断

        现在时间=游戏时间.现在时间
        步过时间=现在时间-步开始时间
        需要休息时间=技能步.步总时间-步过时间
        如 需要休息时间>0:
            产生 休息任务(需要休息时间)

        实例.一步完成时(技能步)

    如 技能数据.延时尾时间>0:
        产生 休息任务(技能数据.延时尾时间)

    #等待完成子.
    对 任务标识 在 实例.子任务列表:
        产生 等待任务(任务标识)

    实例.任务标识=0

实现简单,由多个技能步来配置,循环执行技能步,处理多种技能.根据技能步.转换类型来分别处理:休息/导弹/引导等.
上面导弹技能,按固定速度逼近,利用产生实现每帧执行一次的效果.

#处理导弹
定义 导弹处理函数(技能数据,实例,用户,技能步,动作组,目标标识,目标位置):
    效果=实例.创建效果(技能步.导弹信息.导弹飞行路径)
    效果.置缩放(技能步.导弹信息.缩放导弹)

    当前目标位置,是有效目标=技能步.导弹信息.取目标位置(用户,目标标识,目标位置)
    起始位置=技能步.导弹信息.取开始位置(用户,目标标识,目标位置)

    是达到目标=假
    从 常见.游戏时间 导入 游戏时间
    初化时间=游戏时间.现在时间
    当 真:
        #...
        飞距离=技能步.导弹信息.飞速度*游戏时间.消逝时间

        如 飞距离<总距离:
            起始位置+=飞方向*3维数学.向量(飞距离,飞距离,飞距离)
            效果.置位置(起始位置)
        异:
            是达到目标=真
            断

        #产生,直到下一帧
        产生

    效果.消灭()

    如 是达到目标:
        目标列表=技能数据.取目标列表(用户.转换器,目标标识,目标位置)
        对 目标 在 目标列表:
            动作组.干(用户.转换器,目标)

然后是引导(闪电)类技能.利用好产生 休息任务就可以了.

#处理`引导`,闪电.
定义 导引处理函数(技能数据,实例,用户,技能步,起始位置,目标标识,目标位置):
    效果=实例.创建效果(技能步.导引信息.导引飞行路径)
    效果.置缩放(技能步.导引信息.导引缩放)
    效果.置位置(起始位置)

    效果.置导引尾位置(目标位置-起始位置)
    #休息
    产生 休息任务(技能步.导引信息.导引时间)
    效果.消灭()

现在,用C++20来实现.

//测试协程
m调度器.创建任务20([实例]()->r工作室::逻辑::协恢复任务c++20{
  r工作室::逻辑::i预定任务*任务=r协本任务();
  任务->置中函数([](常 r工作室::逻辑::协中对象*){
    //这里处理返回函数.
  });

  对(动&技能步:步列表)
  {
    动 步开始时间=g游戏->取时管().取时间硬件毫秒();
    开关(技能步.转换类型)
    {
      若 转换技能步::转换类型时期:
        {
          如(技能步.转换动作组列表.大小()>0)
          {
            动&动作组=技能步.转换动作组列表[0];
            对(整 i=0;i<技能步.转换数;i++)
            {
              协待 r工作室::逻辑::协任务::休息(技能步.转换时期);
              极 中值=干花费技能(技能数据,用户,实例);
              如(!中值)
              {
                协中 r工作室::逻辑::协无效;
              }
              干一转换技能(技能数据,技能步,动作组,用户,实例,目标标识,目标位置);
            }
          }
        }
        断;
      若 转换技能步::转换类型导弹到目标:
        {
          如(技能步.转换动作组列表.大小()>0)
          {
            动&动作组=技能步.转换动作组列表[0];
            对(整 i=0;i<技能步.转换数;i++)
            {
              协待 r工作室::逻辑::协任务::休息(技能步.转换时期);
              极 中值=干花费技能(技能数据,用户,实例);
              如(!中值)
              {
                协中 r工作室::逻辑::协无效;
              }
              动 任务标识=协待 r工作室::逻辑::协任务::创建任务(真,[&技能步]()->r工作室::逻辑::协恢复任务c++20{
                动 当前目标位置=技能步.导弹信息.取目标位置(用户,目标标识,目标位置);
                动 起始位置=技能步.导弹信息.取开始位置(用户,目标标识,目标位置);

                极 是达到目标=假;
                动 初化时间=g游戏->取时管().取时间硬件毫秒();
                动 上次=初化时间;
                干
                {
                  动 现在时间=g游戏->取时管().取时间硬件毫秒();
                  动 消逝时间=现在时间-上次;
                  上次=现在时间;
                  如(现在时间-初化时间>=技能步.导弹信息.长飞时间)
                  {
                    断;
                  }

                  动 当前目标位置=技能步.导弹信息.取目标位置(用户,目标标识,目标位置);

                  r工作室::数学::向量3 飞方向=当前目标位置-起始位置;
                  动 总距离=飞方向.正规化();
                  动 飞距离=技能步.导弹信息.飞速度*消逝时间;
                  如(飞距离<总距离)
                  {
                    起始位置+=飞方向*飞距离;
                  }
                  异
                  {
                    是达到目标=真;
                    断;
                  }

                  协待 r工作室::逻辑::协任务::下一帧{};
                }当(真);
                如(是达到目标)
                {
                  //计算损失,
                }

              });
              实例.加子任务标识(任务标识);
            }
          }
        }
        断;
      若 转换技能步::转换类型导引到目标:
        {
          //忽略.
        }
        断;
      默认:
        断;
    }

    动 现在时间=g游戏->取时管().取时间硬件毫秒();
    动 步过时间=现在时间-步开始时间;
    动 需要休息时间=技能步.步总时间-步过时间;
    如(需要休息时间>0)
    {
      协待 r工作室::逻辑::协任务::休息(需要休息时间);
    }

    实例.一步完成时(技能步);
  }

  如(技能数据.延时尾时间>0)
  {
    协待 r工作室::逻辑::协任务::休息(技能数据.延时尾时间);
  }

  对(动 线标:实例.子任务列表)
  {
    协待 r工作室::逻辑::协任务::等待完成任务(线标,10000);
  }
});

可见,协程的优点有:

序号优点
1不会有大量抽象,基于过程实现主体功能即可
2更易实现数据驱动
3避免过多回调,干扰主体逻辑.

自动处理变量等,已经算不错了.

posted @   zjh6  阅读(9)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示