|
楼主 |
发表于 2008-10-27 11:47:58
|
显示全部楼层
再举个例子吧,像我这类的新手们初次接触jass的时候都会遇到做单位移动的难题,需要用到return bug和缓存,举个例子,
就是推人,单位U1对单位U2施法后,U2开始向后移动,我们现在多一个要求,U2每次移动都要受到来自U1的伤害,移动
速度(R1)、距离(R2)伤害(D)是随机的,同时它要支持多个单位移动。好了,缓存方法如下:
[codes==jass]globals
gamecache udg_GC
endglobals
function H2I takes handle h returns integer
return h
return 0
endfunction
function I2U takes integer i returns unit
return i
return null
endfunction
function I2T takes integer i returns timer
return i
return null
endfunction
以上是预备。
function yd_tm takes nothing returns nothing
local timer t=GetExpiredTimer()
local string s=I2S(H2I(t))
local unit U1=I2U(GetStoredInteger(udg_GC,s,"U1"))
local unit U2=I2U(GetStoredInteger(udg_GC,s,"U2"))
local real R1=GetStoredReal(udg_GC,s,"R1")
local real D=GetStoredReal(udg_GC,s,"D")
local real F=GetStoredReal(udg_GC,s,"F")
local integer i=GetStoredInteger(udg_GC,s,"i")
local real x=GetUnitX(U2)+Cos(F)*R1
local real y=GetUnitY(U2)+Sin(F)*R1
local boolean b=IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY)
if not b then
call SetUnitX(U2,x)
call SetUnitY(U2,y)
call UnitDamageTarget(U1,U2,D,true,true,ATTACK_TYPE_MELEE,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
call DestroyEffect(AddSpecialEffectTarget("Abilities\\\\Weapons\\\\SteamTank\\\\SteamTankImpact.mdl",U2,"origin"))
set i=i-1
endif
if b or i==0 then
call PauseTimer(t)
call DestroyTimer(t)
call FlushStoredMission(udg_GC,s)
else
call StoreInteger(udg_GC,s,"i",i)
endif
set t=null
set U1=null
set U2=null
endfunction
function yd_tr takes nothing returns nothing
local unit U1=GetTriggerUnit()
local unit U2=GetSpellTargetUnit()
local real R1=GetRandomReal(10,35)
local real R2=GetRandomReal(1000,1800)
local real D=GetRandomReal(.5,3)
local integer i=R2I(R2/R1)
local timer t=CreateTimer()
local string s=I2S(H2I(t))
local real F=Atan2(GetUnitY(U2)-GetUnitY(U1),GetUnitX(U2)-GetUnitX(U1))
call StoreInteger(udg_GC,s,"U1",H2I(U1))
call StoreInteger(udg_GC,s,"U2",H2I(U2))
call StoreReal(udg_GC,s,"R1",R1)
call StoreReal(udg_GC,s,"D",D)
call StoreReal(udg_GC,s,"F",F)
call StoreInteger(udg_GC,s,"i",i)
call TimerStart(t,.02,true,function yd_tm)
set U1=null
set U2=null
set t=null
endfunction[/codes]
嗯,大家应该可以看出使用缓存时存取都会很麻烦。然后看使用Hash的方法。如下:
[codes==jass]globals
constant integer Ha=8191
constant integer Hb=1987
integer I
handle H
integer array Hi
endglobals
function Hash takes integer I,handle H,boolean b returns integer
local integer ha=I-I/Ha*Ha
local integer hb=(I/Hb+1)*Hb-I
loop
exitwhen (b and Hi[ha]==0)or(not b and Hi[ha]==I)
set ha=ha+hb
if ha>Ha then
set ha=ha-Ha-1
endif
endloop
if b then
set Hi[ha]=I
endif
return ha
endfunction
以上是预备。
globals
unit array yd_u1
unit array yd_u2
real array yd_r
real array yd_d
real array yd_f
integer array yd_i
endglobals
function yd_tm2 takes nothing returns nothing
local timer t=GetExpiredTimer()
local integer this=Hash(0,t,false)
local unit u=yd_u2[this]
local real x=GetUnitX(u)+Cos(yd_f[this])*yd_r[this]
local real y=GetUnitY(u)+Sin(yd_f[this])*yd_r[this]
local boolean b=IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY)
if not b then
call SetUnitX(u,x)
call SetUnitY(u,y)
call UnitDamageTarget(yd_u1[this],u,yd_d[this],true,true,ATTACK_TYPE_MELEE,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
call DestroyEffect(AddSpecialEffectTarget("Abilities\\\\Weapons\\\\SteamTank\\\\SteamTankImpact.mdl",u,"origin"))
set yd_i[this]=yd_i[this]-1
endif
if b or yd_i[this]==0 then
call PauseTimer(t)
call DestroyTimer(t)
set Hi[this]=0
endif
set t=null
set u=null
endfunction
function yd_tr2 takes nothing returns nothing
local timer t=CreateTimer()
local unit U1=GetTriggerUnit()
local unit U2=GetSpellTargetUnit()
local integer this=Hash(0,t,true)
local real r2=GetRandomReal(1000,1800)
set yd_r[this]=GetRandomReal(10,35)
set yd_i[this]=R2I(r2/yd_r[this])
set yd_d[this]=GetRandomReal(.5,3)
set yd_f[this]=Atan2(GetUnitY(U2)-GetUnitY(U1),GetUnitX(U2)-GetUnitX(U1))
set yd_u1[this]=U1
set yd_u2[this]=U2
call TimerStart(t,.02,true,function yd_tm2)
set U1=null
set U2=null
set t=null
endfunction[/codes]
嗯,大家可以比较一下区别。 |
-
-
移动.w3x
35 KB, 下载次数: 54
两种方法的比较
|