目录
关于抛物线的图像
抛物线,是我们生活中很常见的一个函数。一个物体的抛出,又有竖抛,平抛,斜抛等。在这里,我们并不去讨论他的物理性质,我们需要知道抛物线的图像。

如果你想让你的游戏的击飞效果更加的“真实”,那么你也许会用抛物线去制作击飞效果。
(如果你需要绘画函数图像,可以前往数字帝国-函数图像绘制工具)
关于抛物线的应用
我们希望我们在每次执行击飞的时候,只需要输入最高高度和击飞时间两个参数即可,所以我们得找出只需要我们输入这两个参数就可以决定出正确的抛物线的函数式
1.击飞的高度
通过观察不难发现,当我们将x^2乘上一个-1再随便增加一个固定值,那么抛物线在一、二象限里就是一个上升又下降的过程,此时这个固定值+2,就是我们的最高高度。

抛物线和x轴相交的两个点,我们可以认为是击飞的开始和结束,如此,抛物线的顶点就是击飞的最高高度了。如下图

2.击飞的时间
在游戏War3中,我们对于计时器理解的“计时”一般都会从0开始计时(或者从某个数倒计时至0),所以我们把图像与x轴相交的左焦点移动到原点更便于我们绘制。

对于抛物线y=-x^2+2,我做了一个操作,就是让x变为x-sqrt(2),那有人也许会问,那我怎么知道x是需要减去sqrt(2)而不是减去1、2、3、4呢。
其实很简单,我减去的sqrt(2)其实是抛物线(y=-x^2+2)与x轴的两个交点之间的距离的一半。也就是“击飞的时间的一半”,而击飞的时间是我们填入参数的其中之一。
(sqrt是数字帝国里平方根的函数,即sqrt(2),就是根号2)
此时你会发现,如果就着这个击飞时间不变,只增加他的击飞高度,你会发现抛物线与x轴的左交点又不在原点了。如下图

那又要怎么解决呢,我通过计算和猜想,得出这么一个公式。如下图
我们上面推到的式子仅仅只是y=-(x-(t/2))^2+g这部分。这个系数(g/(t/2)^2)是我以前通过计算和猜,碰巧得出来的。现在我也尝试过去推导它,不过目前推导不出来了,不过还好,我保留有结果。如果定义g=4,t=2,代入公式,如下图

你会发现,“击飞高度”符合我们设定的值为4,“击飞时间”也符合我们设定的值2。
关于触发器(Trigger)的实现
cfq 001
事件
条件
动作
[逆天] - 设置 [单位] loc_u = (loc_u)
[逆天] - 设置 [实数] loc_cxsj = (loc_cxsj)
[逆天] - 设置 [实数] loc_gd = (loc_gd)
如果(所有的条件成立) 则运行 (Then - 动作) 否则运行 (Else - 动作)
If - 条件
([单位] (loc_u) 拥有 [实数] gd2) 等于 TRUE
Then - 动作
[逆天] - 设置 [实数] loc_gd2 = (获取 [单位] (loc_u) 的 gd2)
Else - 动作
[逆天] - 设置 [实数] loc_gd2 = ((loc_u) 的当前飞行高度)
[逆天] - 设置 [单位] (loc_u) 的 gd2 为 [实数]0.00
-------- x^2的系数a(调整抛物线) --------
[逆天] - 设置 [实数] loc_a = ((loc_gd) / (((loc_cxsj) / 2.00) 的 2.00 次幂))
-------- 变量x --------
[逆天] - 设置 [实数] loc_x = 0.00
-------- 记录整数(以此判定击飞再击飞时,前一个击飞终止) --------
设置 i = (i + 1)
[逆天] - 设置 [整数] loc_i = i
[逆天] - 运行 (新建的计时器),周期: 0.03 秒,模式: 循环
参数
动作
[逆天] - 设置 [实数] loc_x = ((loc_x) + 0.03)
游戏 - 清空玩家屏幕上的文本信息
游戏 - 对 玩家1(红色) 在屏幕位移(0.00,0.00)处显示 3600.00 秒的文本信息: 该击飞为独立...
游戏 - 对 玩家1(红色) 在屏幕位移(0.00,0.00)处显示文本: (x= + (转换 (loc_x) 为字符串))
如果(所有的条件成立) 则运行 (Then - 动作) 否则运行 (Else - 动作)
If - 条件
Or - 任意条件成立
条件
(loc_x) 大于或等于 (loc_cxsj)
(loc_i) 不等于 i
Then - 动作
游戏 - 对 玩家1(红色) 在屏幕位移(0.00,0.00)处显示文本: 击飞结束
如果(所有的条件成立) 则运行 (Then - 动作) 否则运行 (Else - 动作)
If - 条件
(loc_i) 不等于 i
Then - 动作
Else - 动作
动画 - 改变 (loc_u) 的飞行高度为 (loc_gd2) ,变换速率: 0.00
[逆天] - 清空 [单位] (loc_u) 的[实数] gd2
[逆天] - 清除当前逆天计时器
Else - 动作
[逆天] - 设置 [实数] loc_y = (((-1.00 x (loc_a)) x (((loc_x) - ((loc_cxsj) / 2.00)) 的 2.00 次幂)) + (loc_gd))
动画 - 改变 (loc_u) 的飞行高度为 ((loc_gd2) + (loc_y)) ,变换速率: 0.00
游戏 - 对 玩家1(红色) 在屏幕位移(0.00,0.00)处显示文本: (y= + (转换 (loc_y) 为字符串))
cfq 003
事件
玩家 - 玩家1(红色) 按下Esc键(跳过电影)
条件
动作
-------- 采用逆天运行触发器代入参数直接可以击飞 --------
[逆天] - 运行 cfq 001 <预设>, 无视条件
参数
[逆天] - 设置 [单位] loc_u = 步兵 0000 <预设>
[逆天] - 设置 [实数] loc_cxsj = 1.00
[逆天] - 设置 [实数] loc_gd = 400.00
-------- u-进行击飞的单位 --------
-------- cxsj-持续时间 --------
-------- gd-高度 --------


他的功能是,玩家1摁下esc键后,步兵就会进行持续1秒,高度为400的击飞。在触发器cfq 001里我直接用了一个全局变量x去判断多个击飞同时作用的效果(即后一个击飞覆盖前一个击飞)

关于Jass的实现
function Trig_cfq_jifei_act takes nothing returns nothing
local timer t = GetExpiredTimer()
local unit u = LoadUnitHandle(hxb_bdsj,GetHandleId(t),0)
local real s = LoadReal(hxb_bdsj,GetHandleId(t),1)
local real g = LoadReal(hxb_bdsj,GetHandleId(t),2)
local real x = LoadReal(hxb_bdsj,GetHandleId(t),3) + 0.03
local real y = -1 * (g / Pow(s / 2,2)) * Pow(x - (s / 2),2) + g
call SetUnitFlyHeight(u,y,0)
call SaveReal(hxb_bdsj,GetHandleId(t),3,x)
if x > s then
call KillUnit(u)
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 Trig_cfq_jifei takes nothing returns nothing
local timer t = CreateTimer()
local unit u = CreateUnit(GetTriggerPlayer(),'hfoo',0,0,270)
call UnitAddAbility(u,'Amrf')//添加乌鸦形态
call UnitRemoveAbility(u,'Amrf')//删除乌鸦形态
call SaveUnitHandle(hxb_bdsj,GetHandleId(t),0,u)
call SaveReal(hxb_bdsj,GetHandleId(t),1,1)//击飞时间
call SaveReal(hxb_bdsj,GetHandleId(t),2,GetUnitFlyHeight(u) + 400)//击飞高度
call SaveReal(hxb_bdsj,GetHandleId(t),3,0)//计时
call TimerStart(t,0.03,true,function Trig_cfq_jifei_act)
set u = null
set t = null
endfunction
function InitTrig_cfq_001 takes nothing returns nothing
local trigger trg = CreateTrigger()
call TriggerAddAction(trg,function Trig_cfq_jifei)
call TriggerRegisterPlayerEvent(trg,Player(0),EVENT_PLAYER_END_CINEMATIC)
set trg = null
endfunction
globals
hashtable hxb_bdsj = InitHashtable()
endglobals
(这里不小心点到了选择语言,改不回去了,所以选用了Bash代码显示高亮)
这个Jass代码实现高度400,持续1秒的击飞,这里我用了一个全局哈希表hxb_bdsj来储存数据并且没有做多个控制同时存在的举措
