关于在War3里使用三角函数实现击飞效果

文章详细介绍了如何利用三角函数(如sin、cos)的图像特性来模拟游戏中的击飞效果,包括如何通过调整参数设定击飞高度和时间。同时,文章提供了Trigger的实现方法,展示了Jass代码示例,用于创建和控制击飞行为,并讨论了多个控制效果叠加的处理策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

关于三角函数的图像

关于三角函数的应用

1.击飞高度。

2.击飞的时间。

关于触发器(Trigger)的实现

关于Jass的实现

关于多个控制效果叠加

关于三角函数的图像

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

sin(x)、cos(x)、tan(x)的图像

通过观察可以发现,sin和cos函数,都是有上升又下降波形。而游戏里的击飞,恰巧也是上升又下降的过程。所以,我们不妨可以用这个函数来制作击飞效果。

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

关于三角函数的应用

通过观察三角函数的图像,我们知道sin和cos函数可以用来制作击飞效果。

我这里使用sin函数来制作(sin和cos都可以)

我们先分析击飞,需要的具体参数。

1.击飞的高度

2.击飞的时间

我们只希望只代入这两个参数,就可以完成击飞。

那么我们再去观察sin函数的图像

sin(x)函数的图像

 波浪的最高点,就是我们需要设定的击飞高度,而图像在x轴上的交点之间的距离,就是我们的击飞时间(x轴看成时间t轴)

在进一步了解之前,我们先了解其函数的表达式:f(x)=Asin(ωx+φ)。你先要知道他的表达式里有A、ω、φ这三个参数,我们再去尝试改变参数达到目的。

1.击飞高度。

其实击飞高度其实就是直接由表达式里的参数A决定。sin(x)其实就是1*sin(x),所以你会在上图看到他的击飞高度是1而不是其他数。我们可以尝试改变A的值,如下图

5*sin(x)函数的图像

 可以发现,当A=5时,图像的最高处就是y=5。

很好,如何设定击飞的高度已经解决了。

2.击飞的时间。

我们说过,把x轴看成是时间t轴,时间从t=0开始,到下一个与t轴相交的地方结束。

到这里,我们需要知道一下sin的几个特殊值:

sin(0)=0,sin(π/2)=1、sin(π)=0

5*sin(x)函数的图像

 上图是5*sin(x)函数的图像,通过观察可以知道,击飞的起点在5*sin(0)=0,终点在5*sin(π)=0,而最高点在5*sin(π/2)=5。那么这个函数如果用到击飞里面说的话,就是击飞π秒(3.14159......秒),击飞高度是5。

我们击飞的时间t1是给定的,想要直接把时间t1代入函数中,我们需要知道另一个参数ω的作用。

5*sin(x)和5*sin(2*x)函数的图像

通过图像可以发现,当x变成2*x的时候,击飞时间(两个交点之间的长度)变短了。

其实他有这么一个性质:

当ω从1变成2的时候,两个交点之前的长度就变成了原来的1/2;

当ω从1变成1/2的时候,两个交点之前的长度就变成了原来的2/1。

简单的说,缩短就乘大于1的数,延长就乘小于1的数。

如下图,

5*sin(x)、5*sin(2*x)、5*sin(0.5*x)函数的图像

 那么,我们击飞的时间,用秒作为单位,那我们可以先把函数的两个交点之间的长度由π变成1,这样我们直接把时间t1乘进去,这样就是我们的击飞时间了。

从π变成1,是缩短,所以函数sin(π*x),两个交点之间的长度就是1。

如下图

5*sin(π*x)函数的图像

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

5*sin(π*x/4)和5*sin(π*x/0.5)函数的图像

这样,如何设定击飞时间也解决了。

关于触发器(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) 为字符串))
 

实现击飞的触发cfq 002

 他的功能是:步兵 0002<预设>受到来自步兵 0001<预设>的伤害时,对接受伤害的单位(步兵 0002<预设>)造成击飞效果

触发中标注有:与击飞无关的变量、动作,是为了避免上一次击飞未结束时就进入第二次击飞。

如果两个击飞同时生效,那么步兵就会同时执行两个击飞进而造成上下抽动。

关于两个击飞效果的叠加,在这个触发里,我利用了一个变量去判定目标是否在击飞状态,如果在击飞状态,那么新的击飞就不生效。当目标的击飞完毕后,击飞状态才会移除。

(击飞状态实质是,给目标绑定了一个jf的字符串,移除便是移除绑定的字符串)

触发器(Trigger)的效果

 

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

Jass代码的效果

 

关于多个控制效果叠加

我的建议是,下一个控制效果覆盖上一个控制效果。

如果是两个击飞叠加的话,按理说下一个击飞的初始高度应该是上一个击飞被打断时目标单位的高度,然后再降落至地面。

在击飞途中再击飞,然后落地。目前我还不懂是需要怎么计算他的高度的。

我的击飞中途再击飞,都是强制单位从0开始击飞,虽然看上去没有那么流畅,但对于War3来说,也足够了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值