|
一般的跳躍寫法,在碰到懸崖峭壁的時候,跳躍的曲線會被擾亂,變得不漂亮
而如何製作一個即使碰到懸崖峭壁,也能保持跳躍曲線的函數,就是本篇的重點
這個系統可以給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] |
评分
-
查看全部评分
|