参考地址
先看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);
}
});
可见,协程
的优点有:
| 优点 |
| 不会有大量抽象,基于过程实现 |
| 更易实现数据驱动 |
| 避免过多 |
自动处理栈
变量等,已经算不错了.