目录
关于三角函数的图像
三角函数中,我们常见的是正弦(sin)、余弦(cos)、正切(tan)这三个函数。

通过观察可以发现,sin和cos函数,都是有上升又下降波形。而游戏里的击飞,恰巧也是上升又下降的过程。所以,我们不妨可以用这个函数来制作击飞效果。
(如果你需要绘画函数图像,可以前往数字帝国-函数图像绘制工具)
关于三角函数的应用
通过观察三角函数的图像,我们知道sin和cos函数可以用来制作击飞效果。
我这里使用sin函数来制作(sin和cos都可以)
我们先分析击飞,需要的具体参数。
1.击飞的高度
2.击飞的时间
我们只希望只代入这两个参数,就可以完成击飞。
那么我们再去观察sin函数的图像

波浪的最高点,就是我们需要设定的击飞高度,而图像在x轴上的交点之间的距离,就是我们的击飞时间(x轴看成时间t轴)
在进一步了解之前,我们先了解其函数的表达式:f(x)=Asin(ωx+φ)。你先要知道他的表达式里有A、ω、φ这三个参数,我们再去尝试改变参数达到目的。
1.击飞高度。
其实击飞高度其实就是直接由表达式里的参数A决定。sin(x)其实就是1*sin(x),所以你会在上图看到他的击飞高度是1而不是其他数。我们可以尝试改变A的值,如下图

可以发现,当A=5时,图像的最高处就是y=5。
很好,如何设定击飞的高度已经解决了。
2.击飞的时间。
我们说过,把x轴看成是时间t轴,时间从t=0开始,到下一个与t轴相交的地方结束。
到这里,我们需要知道一下sin的几个特殊值:
sin(0)=0,sin(π/2)=1、sin(π)=0

上图是5*sin(x)函数的图像,通过观察可以知道,击飞的起点在5*sin(0)=0,终点在5*sin(π)=0,而最高点在5*sin(π/2)=5。那么这个函数如果用到击飞里面说的话,就是击飞π秒(3.14159......秒),击飞高度是5。
我们击飞的时间t1是给定的,想要直接把时间t1代入函数中,我们需要知道另一个参数ω的作用。

通过图像可以发现,当x变成2*x的时候,击飞时间(两个交点之间的长度)变短了。
其实他有这么一个性质:
当ω从1变成2的时候,两个交点之前的长度就变成了原来的1/2;
当ω从1变成1/2的时候,两个交点之前的长度就变成了原来的2/1。
简单的说,缩短就乘大于1的数,延长就乘小于1的数。
如下图,

那么,我们击飞的时间,用秒作为单位,那我们可以先把函数的两个交点之间的长度由π变成1,这样我们直接把时间t1乘进去,这样就是我们的击飞时间了。
从π变成1,是缩短,所以函数sin(π*x),两个交点之间的长度就是1。
如下图

这时候,我们想让长度变成4,就需要除以4,想让他变成0.5,就需要除以0.5(除以0.5就是乘2),如下图

这样,如何设定击飞时间也解决了。
关于触发器(Trigger)的实现
cfq 002
事件
单位 - 步兵 0002 <预设> 接受伤害
条件
(伤害来源) 等于 步兵 0001 <预设>
动作
[逆天] - 设置 [单位] loc_dw = (伤害来源)
[逆天] - 设置 [单位] loc_dw2 = (触发单位)
如果(所有的条件成立) 则运行 (Then - 动作) 否则运行 (Else - 动作)
If - 条件
(获取 [单位] (loc_dw2) 的 zt) 等于 jf
Then - 动作
Else - 动作
[逆天] - 设置 [实数] loc_gd = 300.00
[逆天] - 设置 [实数] loc_sj = 2.00
[逆天] - 设置 [实数] loc_t = 0.00
[逆天] - 设置 [实数] loc_xzgd = ((loc_dw2) 的默认飞行高度)
[逆天] - 设置 [单位] (loc_dw2) 的 zt 为 [字符串]jf
-------- --------与击飞无关的变量↓↓↓ --------
[逆天] - 设置 [实数] loc_gd2 = 0.00
-------- --------与击飞无关的变量↑↑↑ --------
动画 - 改变 (loc_dw2) 的飞行高度为 (loc_zxgd) ,变换速率: 0.00
单位 - 设置 (loc_dw2) 暂停
单位 - 为 (loc_dw2) 添加 乌鸦形态
单位 - 为 (loc_dw2) 删除 乌鸦形态
[逆天] - 运行 (新建的计时器),周期: 0.03 秒,模式: 循环
参数
动作
如果(所有的条件成立) 则运行 (Then - 动作) 否则运行 (Else - 动作)
If - 条件
(loc_dw2) 等于 没有单位
Then - 动作
[逆天] - 清除当前逆天计时器
Else - 动作
[逆天] - 设置 [实数] loc_t = ((loc_t) + 0.03)
[逆天] - 设置 [实数] loc_y = ((loc_gd) x (Sin((转换实数 ((π / (loc_sj)) x (loc_t)) 为弧度))))
如果(所有的条件成立) 则运行 (Then - 动作) 否则运行 (Else - 动作)
If - 条件
(loc_y) 小于 0.00
Then - 动作
动画 - 改变 (loc_dw2) 的飞行高度为 (loc_zxgd) ,变换速率: 0.00
单位 - 设置 (loc_dw2) 恢复
[逆天] - 清空 [单位] (loc_dw2) 的[字符串] zt
[逆天] - 清除当前逆天计时器
Else - 动作
动画 - 改变 (loc_dw2) 的飞行高度为 (loc_y) ,变换速率: 0.00
-------- --------以下为与击飞无关的动作 --------
如果(所有的条件成立) 则运行 (Then - 动作) 否则运行 (Else - 动作)
If - 条件
(loc_y) 大于 (loc_gd2)
Then - 动作
[逆天] - 设置 [实数] loc_gd2 = (loc_y)
Else - 动作
游戏 - 清空 (所有玩家) 屏幕上的文本信息
游戏 - 对 (所有玩家) 发送显示 3600.00 秒的文本信息: 该"击飞"由 函...
游戏 - 对 (所有玩家) 发送显示 3600.00 秒的文本信息: (最高高度 - + (转换 (loc_gd2) 为字符串))
游戏 - 对 (所有玩家) 发送显示 3600.00 秒的文本信息: (高度 - + (转换 (loc_y) 为字符串))
游戏 - 对 (所有玩家) 发送显示 3600.00 秒的文本信息: (时间 - + (转换 (loc_t) 为字符串))

他的功能是:步兵 0002<预设>受到来自步兵 0001<预设>的伤害时,对接受伤害的单位(步兵 0002<预设>)造成击飞效果
触发中标注有:与击飞无关的变量、动作,是为了避免上一次击飞未结束时就进入第二次击飞。
如果两个击飞同时生效,那么步兵就会同时执行两个击飞进而造成上下抽动。
关于两个击飞效果的叠加,在这个触发里,我利用了一个变量去判定目标是否在击飞状态,如果在击飞状态,那么新的击飞就不生效。当目标的击飞完毕后,击飞状态才会移除。
(击飞状态实质是,给目标绑定了一个jf的字符串,移除便是移除绑定的字符串)

关于Jass的实现
function func_jifei_act takes nothing returns nothing
local timer t = GetExpiredTimer()
local unit u = LoadUnitHandle(hxb_bdsj,GetHandleId(t),0)
local real time = LoadReal(hxb_bdsj,GetHandleId(t),1)
local real height = LoadReal(hxb_bdsj,GetHandleId(t),2)
local real s = LoadReal(hxb_bdsj,GetHandleId(t),3)
local real y
call SaveReal(hxb_bdsj,GetHandleId(t),3,s + 0.03)
set y = height * Sin(3.14159 * s / time)
call SetUnitFlyHeight(u,y,0)//注意默认只有飞行单位才能设置高度,其他单位需要添加再删除技能乌鸦形态才能设置高度。
if s > time then
call SetUnitFlyHeight(u,GetUnitFlyHeight(u),0)
call RemoveSavedHandle(hxb_bdsj,GetHandleId(t),0)
call RemoveSavedReal(hxb_bdsj,GetHandleId(t),1)
call RemoveSavedReal(hxb_bdsj,GetHandleId(t),2)
call RemoveSavedReal(hxb_bdsj,GetHandleId(t),3)
call DestroyTimer(t)
endif
set t = null
set u = null
endfunction
function func_jifei takes nothing returns nothing
local unit u = GetTriggerUnit()
local real time = 2
local real height = 300
local timer t = CreateTimer()
call SaveUnitHandle(hxb_bdsj,GetHandleId(t),0,u)//单位-0
call SaveReal(hxb_bdsj,GetHandleId(t),1,time)//击飞时间-1
call SaveReal(hxb_bdsj,GetHandleId(t),2,height)//击飞高度-2
call SaveReal(hxb_bdsj,GetHandleId(t),3,0)//用于累积时间-3
call UnitAddAbility(u,'Amrf')
call UnitRemoveAbility(u,'Amrf')
call SetUnitFlyHeight(u,GetUnitFlyHeight(u),0)
call TimerStart(t,0.03,true,function func_jifei_act)
set u = null
set t = null
endfunction
function InitTrig_cfq_003 takes nothing returns nothing
set gg_trg_cfq_003 = CreateTrigger()
call TriggerAddAction(gg_trg_cfq_003,function func_jifei)
call TriggerRegisterUnitEvent(gg_trg_cfq_003,gg_unit_hfoo_0002,EVENT_UNIT_DAMAGED)
endfunction
globals
hashtable hxb_bdsj = InitHashtable()
endglobals
这是Jass代码实现高度300,持续4秒的击飞。这里我用了一个全局哈希表hxb_bdsj来储存数据并且没有做多个控制同时存在的举措。

关于多个控制效果叠加
我的建议是,下一个控制效果覆盖上一个控制效果。
如果是两个击飞叠加的话,按理说下一个击飞的初始高度应该是上一个击飞被打断时目标单位的高度,然后再降落至地面。
在击飞途中再击飞,然后落地。目前我还不懂是需要怎么计算他的高度的。
我的击飞中途再击飞,都是强制单位从0开始击飞,虽然看上去没有那么流畅,但对于War3来说,也足够了。