关于在War3里使用抛物线实现击飞效果

目录

关于抛物线的图像

关于抛物线的应用

1.击飞的高度

2.击飞的时间

关于触发器(Trigger)的实现

 关于Jass的实现


关于抛物线的图像

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

y=x^的抛物线图像
y=x^2的抛物线图像

 如果你想让你的游戏的击飞效果更加的“真实”,那么你也许会用抛物线去制作击飞效果。

(如果你需要绘画函数图像,可以前往数字帝国-函数图像绘制工具

关于抛物线的应用

我们希望我们在每次执行击飞的时候,只需要输入最高高度和击飞时间两个参数即可,所以我们得找出只需要我们输入这两个参数就可以决定出正确的抛物线的函数式

1.击飞的高度

通过观察不难发现,当我们将x^2乘上一个-1再随便增加一个固定值,那么抛物线在一、二象限里就是一个上升又下降的过程,此时这个固定值+2,就是我们的最高高度。

y=-x^2+2的图像
y=-x^2+2的图像

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

y=-x^2+2的图像
y=-x^2+2的图像

2.击飞的时间

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

y=-x^2+2和y=-(x-sqrt(2))^2+2的图像
y=-x^2+2和y=-(x-sqrt(2))^2+2的图像

 对于抛物线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-sqrt(2))^2+2和y=-(x-sqrt(2))^2+4的图像
y=-(x-sqrt(2))^2+2和y=-(x-sqrt(2))^2+4的图像

那又要怎么解决呢,我通过计算和猜想,得出这么一个公式。如下图

y=-(g/(t/2)^2)*(x-(t/2))^2+g

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

y=(g/(t/2)^2)*(x-(t/2))^2+g的图像
y=(g/(t/2)^2)*(x-(t/2))^2+g的图像

你会发现,“击飞高度”符合我们设定的值为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-高度 --------
 

实现击飞的触发cfq 001
实现击飞的触发cfq 001

实现击飞的触发cfq 003
实现击飞的触发cfq 003

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

触发器(Trigger)的效果
触发器(Trigger)的效果

 关于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来储存数据并且没有做多个控制同时存在的举措

Jass代码的效果
Jass代码的效果

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值