找回密码
 点一下
查看: 2841|回复: 10

[WB]套用物理學公式的跳斬系統!V008

[复制链接]
发表于 2009-10-19 14:53:50 | 显示全部楼层 |阅读模式
一般的跳躍寫法,在碰到懸崖峭壁的時候,跳躍的曲線會被擾亂,變得不漂亮
而如何製作一個即使碰到懸崖峭壁,也能保持跳躍曲線的函數,就是本篇的重點

這個系統可以給GUI使用,移植相當方便,支援多重施展
想簡單做出跳斬的人可以試試看!

==============================

如何解決起跳點與目的地的高度不同的問題呢?

首先複習一下物理學的加速度公式

X = V0t + (AT^2)/2
位移距離 = 初速x時間 + ( 加速度 x 時間^2 ) / 2

V0t在此忽略

由此公式推得兩個不同高度的時間比
T1 / T2 = 更號 ( X1 / X2 )

末速度AT = 2*X/T
加速度A = AT/T


X1與X2代表加速度運動的位移距離,在此視為跳躍高度

設 X1 > X2 的情況,我們把X1視為一個完整的跳躍
而X2代表角色在高地,跳躍高度短,視為一個不完整的跳躍

若完成一個起跳X1高度,落下X1高度的跳躍,需要時間T1x2
那麼完成一個起跳X1高度,落下X2高度的跳躍,則需時間T1+T2

若起跳點與落地點不等高,我們的跳躍就不完整,因此要對時間做出修正
完整跳躍時間=T1x2,不完整跳躍時間=T1+T2

設函數傳入的時間為 time,設T1 = 0.5 x time
則修正後的時間為 mT0 = 1/(T2+0.5) * time

修正後的半個完整跳躍的時間為 mT1 = 0.5 x mT0

經過此一修正,若傳入的time為0.8
則無論起跳與落地的高低差為多少,整個跳躍都花費0.8秒,利於觸發技能撰寫


因為時間軸是以0.02秒為單位

所以我們可以獲得這個式子,取得mT1
    mT1 = 0.5/((T2+0.5) * time * 0.02 )

簡化得到    mT1 = 25/(T2+0.5) * time

再來剩下的就很簡單了
 AT = 2*X1/T
 A = AT/T

取得加速度與末速度之後剩下的就非常簡單了

最後只要判定起跳點高於落地點,還是低於落地點
套上不同的起跳速度,就大功告成了

==============================

決定跳躍高度的Z軸數值,並不使用二次函數或Sin函數
而是使用簡單的加法來模擬加速度運動
當時間軸分割的夠細的時候,獲得的答案會趨近於二次函數
有微積分概念的人,應該不難理解這些


接下來用
        call MoveLocation(udg_GetZ,x,y)

還有
        GetLocationZ(udg_GetZ)

就能簡單的取得Z軸,用來調整因為地表Z而影響到的飛行高度



==============================



[jass]
function LineJump_Core takes nothing returns nothing
local integer K     = LoadK()
local unit U        = udg__Uni0[K]               
local real time     = udg__ReaT[K] + 0.02      
local real tpst     = time / udg__Rea5[K]
local real dis      = udg__ReaR[K] * tpst      
local real ang      = udg__ReaA[K]            
local real x = udg__Lcx0[K] + dis * Cos(ang * bj_DEGTORAD)
local real y = udg__Lcy0[K] + dis * Sin(ang * bj_DEGTORAD)
local real high = -1

    if tpst <= 1.00001 then
        set high = udg__Rea4[K] + udg__Rea2[K]
        set udg__Rea4[K] = high
        set udg__Rea2[K] = udg__Rea2[K] + udg__Rea3[K]
    endif

    if high != -1 and x > udg_MAP_MinX and x < udg_MAP_MaxX and y > udg_MAP_MinY and y < udg_MAP_MaxY then
        call MoveLocation(udg_GetZ,x,y)
        call SetUnitX(U,x)
        call SetUnitY(U,y)
        call SetUnitFlyHeight(U,high-GetLocationZ(udg_GetZ),999999.9)
        set udg__ReaT[K] = time
    else
        call SetUnitFlyHeight(U,0,999999.9)
        call SetUnitInvulnerable(U,false)
        call SetUnitPathing(U,true)
        call PauseUnit(U,false)
        call SetUnitPosition(U,GetUnitX(U),GetUnitY(U))
        if udg__Trg0[K] != null then
            set udg_T_IntK = K
            call TriggerExecute(udg__Trg0[K])
        endif
        call EndK(K)
    endif
    set U = null
endfunction

function LineJump takes unit U1,real dis,real ang,real high,real time,trigger AFunc returns integer
local integer K = GetK()
local real Z1
local real Z2
local real MaxH
local real AT
local real T
local real T2
local real A
local real V0

    set udg__Uni0[K] = U1                    
    set udg__ReaR[K] = dis                 
    set udg__ReaA[K] = ang                  
    set udg__ReaT[K] = 0.00               

    set udg__Lcx0[K] = GetUnitX(U1)
    set udg__Lcy0[K] = GetUnitY(U1)
    set udg__Trg0[K] = AFunc               

    call MoveLocation(udg_GetZ,udg__Lcx0[K],udg__Lcy0[K])
    set udg__Rea0[K] = GetLocationZ(udg_GetZ)
    call MoveLocation(udg_GetZ,udg__Lcx0[K] + dis * Cos(ang * bj_DEGTORAD),udg__Lcy0[K] + dis * Sin(ang * bj_DEGTORAD))   
    set udg__Rea1[K] = GetLocationZ(udg_GetZ)

    if udg__Rea0[K] > udg__Rea1[K] then
        set Z1 = udg__Rea0[K]
        set Z2 = udg__Rea1[K]
    else
        set Z1 = udg__Rea1[K]
        set Z2 = udg__Rea0[K]
    endif
    set MaxH = Z1-Z2+high
    set T2 = 0.5*Pow(high/MaxH,0.5)
    set T = 25/(T2+0.5) * time
    set AT = 2*MaxH/T
    set A = AT/T

    if udg__Rea0[K] > udg__Rea1[K] then
        set V0 = AT * T2 * 2
    else
        set V0 = AT
    endif

    set udg__Rea2[K] = V0
    set udg__Rea3[K] = -A
    set udg__Rea4[K] = udg__Rea0[K]
    set udg__Rea5[K] = time


    call SetUnitInvulnerable(U1,true)
    call SetUnitPathing(U1,false)
    call PauseUnit(U1,true)
    call UnitAddAbility(U1,'Arav')
    call UnitRemoveAbility(U1,'Arav')
    call TimerStart(udg__TimK[K], 0.02, true, function LineJump_Core )
    return K
endfunction
[/jass]

[WB]JumpFuncV008_20091019.w3x

33 KB, 下载次数: 74

评分

参与人数 1威望 +1 收起 理由
疯人¢衰人 + 1 这个东西……

查看全部评分

发表于 2009-10-19 15:33:47 | 显示全部楼层
我好像没有看到常量G
回复

使用道具 举报

发表于 2009-10-19 15:52:17 | 显示全部楼层
实际上在悬崖边上曲线自然是因为飞行单位在悬崖附近会逐渐的改变高度
而高度调整的函数没这个功能
我自己在做投射物模拟函数也考虑了这个问题
回复

使用道具 举报

 楼主| 发表于 2009-10-19 16:21:55 | 显示全部楼层
掉落速度取決於觸發傳入的time,套了常量G就無法自由控制掉落時間

曲線會順暢是因為這段,若單純套高度,肯定不是這結果
        call SetUnitFlyHeight(U,high-GetLocationZ(udg_GetZ),999999.9)

載量0難道這東西有這麼差嗎?
回复

使用道具 举报

发表于 2009-10-19 17:07:50 | 显示全部楼层
SetUnitFlyHeight的速度设为0就是立即调整高度了……
至于没下载量……
是因为GA里都是高手
然后GA也很冷清……
基本上常驻人口都会自己写除非没学抛物线的小loli小正太
不过还是支持LZ的研究……
回复

使用道具 举报

发表于 2009-10-19 18:51:01 | 显示全部楼层
LZ悲剧了……
回复

使用道具 举报

发表于 2009-10-19 18:56:13 | 显示全部楼层
这个函数倒是没啥问题,关键是,如果把高度和移动速度挂钩,会掉线的(地形在w3并不同步)。
回复

使用道具 举报

发表于 2009-10-22 16:05:52 | 显示全部楼层
补充一下
GA还有很多懒人
比如我,虽然代码不长却也懒得看
回复

使用道具 举报

发表于 2009-10-22 18:08:22 | 显示全部楼层
也不是说别的,我大概看了一下似乎是把飞行高度计算进运动轨迹了
回复

使用道具 举报

发表于 2009-10-28 01:05:30 | 显示全部楼层
妈哟,强子的头像怎么像被揍过一样?

顺便支持楼主!!
回复

使用道具 举报

发表于 2009-11-14 20:33:29 | 显示全部楼层
这两天正在学匀加速直线运动的某人路过……
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 点一下

本版积分规则

Archiver|移动端|小黑屋|地精研究院

GMT+8, 2024-4-27 14:15 , Processed in 0.221016 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表