找回密码
 点一下
查看: 5710|回复: 26

模拟投射物轨迹——函数粗略版

[复制链接]
发表于 2009-9-1 22:20:15 | 显示全部楼层 |阅读模式
好吧……
下定决心减少来GA的时间了……
而且是大量的减少……
恩……
其实很早就有这样的打算了……
不过我这人一向是重视承诺的……
至少自己该做的……
绝对会做完……

这个函数本来时被小血逼着为位面消隐做的东西……
因为自己不会VJ,所以只是写了个简单的函数,用于测试高度公式以及效果,连排泄都没有做……
而且我也根本没有想将其发上来,至少在开始写这个帖子之前没有……
算了,还是不多说了……

演示下载: aim.w3x (22 KB, 下载次数: 110)
[jass]
function Getb takes real H0,real H1,real L,real K returns real
//b
return 2*((K*L-H0)+SquareRoot((K*L-H0)*(K*L-H1)))*10000/L
endfunction
function Geta takes real H0,real H1,real L,real K returns real
//a
local real b = Getb(H0,H1,L,K)
return b*b/40000/(H0-K*L)
endfunction
function MoveProjectileB takes nothing returns nothing
local timer udg_t = null
local unit udg_u = null
local integer udg_i = 0
local integer temp = 0
local real VX = 0
local real H1 = 0
local real H2 = 0
local real dis = 0
local real angle = 0
local unit Aim = null
local unit Projectile = null
local location Aimloc = null
local location Proloc = null
set udg_t = GetExpiredTimer()
set temp = udg_i
set VX = GetStoredReal(udg_W3V,I2S(temp),"VX")
set udg_i = GetStoredInteger(udg_W3V, I2S(temp), "AimUnitHandle")
set Aim = udg_u
set Aimloc = GetUnitLoc(Aim)
set udg_i = GetStoredInteger(udg_W3V, I2S(temp), "Projectile")
set Projectile = udg_u
set Proloc = GetUnitLoc(Projectile)
set dis = DistanceBetweenPoints(Proloc, Aimloc)
set angle = AngleBetweenPoints(Proloc, Aimloc)
if dis < VX then
call RemoveUnit(Projectile)
call PauseTimer(GetExpiredTimer())
//命中目标
//省略诸多排泄
endif
set H2 = GetUnitFlyHeight(Projectile)
set H1 = GetUnitFlyHeight(Aim)
call SetUnitFlyHeight(Projectile, H2-(H2-H1)*VX/dis, 0 )
set Proloc = PolarProjectionBJ(Proloc,VX, angle)
call SetUnitX(Projectile,GetLocationX(Proloc))
call SetUnitY(Projectile,GetLocationY(Proloc))
call SetUnitFacing( Projectile,angle)
endfunction
function MoveProjectileA takes nothing returns nothing
local timer udg_t = null
local unit udg_u = null
local integer udg_i = 0
local integer temp = 0
local real VX = 0
local real X = 0
local real Y = 0
local real H0 = 0
local real T = 0
local real a = 0
local real b = 0
local unit Aim = null
local unit Projectile = null
local location Aimloc = null
local location Proloc = null
local timer time
set udg_t = GetExpiredTimer()
set temp = udg_i
set udg_i = GetStoredInteger(udg_W3V, I2S(temp), "AimUnitHandle")
set Aim = udg_u
set Aimloc = GetUnitLoc(Aim)
set X = GetStoredReal(udg_W3V,I2S(temp),"X")
set Y = GetStoredReal(udg_W3V,I2S(temp),"Y")
set VX = GetStoredReal(udg_W3V,I2S(temp),"VX")
set H0 = GetStoredReal(udg_W3V,I2S(temp),"H0")
set udg_i = GetStoredInteger(udg_W3V, I2S(temp), "Projectile")
set Projectile = udg_u
if (GetLocationX(Aimloc) != X) or (GetLocationY(Aimloc) != Y) then
set udg_t = CreateTimer()
set temp = udg_i
set time =udg_t
call StoreReal(udg_W3V,I2S(temp),"VX",VX)
set udg_u = Aim
call StoreInteger(udg_W3V,I2S(temp),"AimUnitHandle",udg_i)
set udg_u = Projectile
call StoreInteger(udg_W3V,I2S(temp),"Projectile",udg_i)
call TimerStart(time,udg_interval,true,function MoveProjectileB)
call PauseTimer(GetExpiredTimer())
call DestroyTimer(GetExpiredTimer())
return
//进入第二种移动方式
//省略诸多排泄
endif
set a = GetStoredReal(udg_W3V,I2S(temp),"a")
set b = GetStoredReal(udg_W3V,I2S(temp),"b")
set Proloc = GetUnitLoc(Projectile)
if DistanceBetweenPoints(Proloc, Aimloc) < VX then
call RemoveUnit(Projectile)
call PauseTimer(GetExpiredTimer())
//命中目标
//省略诸多排泄
endif
set T = GetStoredReal(udg_W3V,I2S(temp),"T")
call SetUnitFlyHeight(Projectile,a*T*T/10000*VX*VX+b*T*VX/10000+H0, 0 )
set Proloc = PolarProjectionBJ(Proloc,VX, AngleBetweenPoints(Proloc, Aimloc))
call SetUnitX(Projectile,GetLocationX(Proloc))
call SetUnitY(Projectile,GetLocationY(Proloc))
call StoreReal(udg_W3V,I2S(temp),"T",T+1)
endfunction
function GetAim takes unit aim,location loc,integer ut,player p,real k,integer v,real h0 returns nothing//参数依次是 目标单位aim, 发动攻击单位位置loc, 投射物马甲的单位类型ut ,攻击单位的所有者(所有玩家)p, 射弹弧度k ,射弹速率v ,射弹初始高度h0
local timer udg_t = null
local unit udg_u = null
local integer udg_i = 0
local integer temp = 0
local location l = null
local timer temptimer
set udg_t = CreateTimer()
set temptimer = udg_t
set temp = udg_i
set udg_u = aim
call StoreInteger(udg_W3V,I2S(temp),"AimUnitHandle",udg_i)
call StoreReal(udg_W3V,I2S(temp),"VX",R2I(I2R(v) * udg_interval))
set l = GetUnitLoc(aim)
call CreateNUnitsAtLoc( 1, ut, p, loc, AngleBetweenPoints(loc,l) )
set udg_u = GetLastCreatedUnit()
call SetUnitFlyHeight( udg_u, h0, 0 )
call StoreInteger(udg_W3V,I2S(temp),"Projectile",udg_i)
call StoreReal(udg_W3V,I2S(temp),"b",Getb(h0,GetUnitFlyHeight(aim),DistanceBetweenPoints(l, loc),k))
call StoreReal(udg_W3V,I2S(temp),"a",Geta(h0,GetUnitFlyHeight(aim),DistanceBetweenPoints(l, loc),k))
call StoreReal(udg_W3V,I2S(temp),"X",GetLocationX(l))
call StoreReal(udg_W3V,I2S(temp),"Y",GetLocationY(l))
call StoreReal(udg_W3V,I2S(temp),"T",0)
call StoreReal(udg_W3V,I2S(temp),"H0",h0)
call TimerStart(temptimer,udg_interval,true,function MoveProjectileA)
endfunction

[/jass]

以上是最简单的代码,GC版,无排泄,无变量声明(声明看最后的演示吧)。反正诸位也许会用的GAer大约也能自己改成完好的。
其中:
[jass]
function Getb takes real H0,real H1,real L,real K returns real
//b
return 2*((K*L-H0)+SquareRoot((K*L-H0)*(K*L-H1)))*10000/L
endfunction
function Geta takes real H0,real H1,real L,real K returns real
//a
local real b = Getb(H0,H1,L,K)
return b*b/40000/(H0-K*L)
endfunction
[/jass]
这两个函数的返回值是投射物曲线的抛物线方程Y=aX2+bX+c中的a、b参数,而参数c是H0,也就是投射物的初始高度。

之后的三个函数是具体模拟投射物效果的函数:
GetAim是记录各种参数,然后开始曲线方案1的计时器。具体需要绑定的参数有:
Aim,(目标,函数中保存的是Handle),
Projectile,(投射物单位,在函数里创建的,类型通过 GetAim 函数的参数获得,演示里也是用Handle值传递的)
VX,(水平方向的速度,就是每间隔时间内投射物的移动距离,其值是投射速率这个系数乘以移动间隔时间)
b,(Getb获得的,  b=2*[(K*L-H0)+√((H0-K*L)*(H1-K*L)) ] 其中√代表平方根)
√a,(Geta获得的,a=b2/4/(H0-K*L)  ,b用Getb获得)

X,(目标X轴坐标,用于判断目标是否移动)
Y,(同X,不过是Y轴的)
H0,(投射物的初始高度)
T,(执行次数,用于计算的,每次循环要+1)

因为不是成品,所以还是仔细说明下。
特别要提到的是
我并没有让投射物创建在攻击单位头上,而是向着目标移动一个移动间隔(VX),这是因为感觉这样效果真实。
MoveProjectileA,MoveProjectileB是两个投射物运行方式A是目标不移动的轨迹,B是移动后的,具体请自己看真实投射物曲线吧(下载 投射物.w3x (18 KB, 下载次数: 92) )。 调用MoveProjectileB时,你只要将VX,Aim和Projectile传递过去即可。

MoveProjectileB的调用在MoveProjectileA中(函数上面有注释),无论哪种方式,当命中目标(判断目标和投射物之间的距离小于VX)后,需要运行其他函数,请插入函数中相关注释的部分
演示采用的方法是不考虑地面的,也就是未曾考虑地面不平的问题。,如果诸位需要考虑,可以将H0和H1(目标高度)都加上对应点的GetLocationZ。设置投射物高度时要减去 GetLocationZ。另外还有判断计算出来的高度是否高于地面,如果高于地面,请将投射物隐藏或替换,取消投射物模型,这样更真实些。(正常地图不必考虑这些)

[jass]
if DistanceBetweenPoints(Proloc, Aimloc) < VX then
call RemoveUnit(Projectile)
call PauseTimer(GetExpiredTimer())
//命中目标
//省略诸多排泄
endif
[/jass]

中调用即可。

关于目标不移动时投射物的曲线的方程,
还有个计算用的解释图:
FMYYJR`$DP@8O`4Z@~07@}2.jpg
  


如果有谁要完整能用的函数……
找小血要吧……
嘿嘿……

函数是未完整的……
感觉还是很对不起大家……
恩恩……
于是躲起来……
也许会偶尔上来看看的……

评分

参与人数 1威望 +5 收起 理由
血戮魔动冰 + 5 (*^__^*) 嘻嘻……

查看全部评分

发表于 2009-9-1 22:25:29 | 显示全部楼层
怎么可能……
阿。还是多回来罢。
还有那啥。投射的角度呢。
回复

使用道具 举报

 楼主| 发表于 2009-9-1 22:33:17 | 显示全部楼层
忘记了……
投射角度相关的数据室K
为单位的射弹弧度这项数值
实际上就是最高点高度与攻击单位到目标之间距离的比值
回复

使用道具 举报

发表于 2009-9-1 22:35:10 | 显示全部楼层
你竟然对你的帖子用了强效置顶无视器……
回复

使用道具 举报

 楼主| 发表于 2009-9-1 22:35:46 | 显示全部楼层
好吧……
用错道具结果置顶了……
回复

使用道具 举报

发表于 2009-9-1 22:41:57 | 显示全部楼层
苦命呢……宝贵的置顶器……
好久没和你水了
回复

使用道具 举报

 楼主| 发表于 2009-9-1 23:09:23 | 显示全部楼层
……
还有很多……
19+
你不知道
我醒目灯也用了3个……
回复

使用道具 举报

发表于 2009-9-1 23:21:42 | 显示全部楼层
为啥用这末多呢~不是一次可以选中包括粗斜亮加上一个颜色的嘛
回复

使用道具 举报

 楼主| 发表于 2009-9-1 23:26:13 | 显示全部楼层
改了两回都感觉不好
回复

使用道具 举报

发表于 2009-9-1 23:30:27 | 显示全部楼层
终于还是决定用你最喜欢的黄~色~了末~
回复

使用道具 举报

发表于 2009-9-2 07:33:42 | 显示全部楼层
为什么这个帖子没有投影仪的标记呢?
猜想是用了置顶之后再用了其他道具,把置顶的标记覆盖了,然后置顶结束会消除标记,结果就把其他的标记取消了。
回复

使用道具 举报

发表于 2009-9-2 22:25:59 | 显示全部楼层
魔兽的投射物是如此判定的:arc若不为0时,投射物会无视目标单位是否移动强制性飞向发射时所记录的目标的x,y,z,如果到达时没有击中(只判断x,y),则以arc为0的轨迹移动,高度会重新判断,但貌似不会对过快的变化做出反应。
疯人的函数是怎么写的?手机实在是看得太难受。
话说当初我就是因为那个口胡的SetUnitLookAt无效所以就放弃这系统了……
回复

使用道具 举报

 楼主| 发表于 2009-9-3 09:04:25 | 显示全部楼层
引用第11楼louter于2009-09-02 22:25发表的 :
魔兽的投射物是如此判定的:arc若不为0时,投射物会无视目标单位是否移动强制性飞向发射时所记录的目标的x,y,z,如果到达时没有击中(只判断x,y),则以arc为0的轨迹移动,高度会重新判断,但貌似不会对过快的变化做出反应。
疯人的函数是怎么写的?手机实在是看得太难受。
话说当初我就是因为那个口胡的SetUnitLookAt无效所以就放弃这系统了……

我做过测试……
但是并非按阁下所说的轨迹呢……
实际上如果arc为0
那么无论目标是否移动,都是在三维坐标中从投射物到目标的直线……(这个没测试,猜的)
如果arc不为0
那么投射物会如你所说:飞向发射时所记录的目标的x,y,z
然而一旦目标移动,投射物会直线追踪目标……
我这帖子里有演示的
回复

使用道具 举报

发表于 2009-9-3 12:45:06 | 显示全部楼层
用gc者死
回复

使用道具 举报

发表于 2009-9-3 13:17:54 | 显示全部楼层
又学会了一招。
回复

使用道具 举报

发表于 2009-9-3 13:18:44 | 显示全部楼层
…………………………………………………………!!
传说中的……吐槽?
回复

使用道具 举报

发表于 2009-9-3 15:20:58 | 显示全部楼层
因为是很早以前写的,所以测试的结果什么的记得就不是很清楚了,外加现在没电脑。

如果没错的话应该所有的投射物在z轴上都是一个方向……
回复

使用道具 举报

 楼主| 发表于 2009-9-3 17:13:13 | 显示全部楼层
引用第16楼louter于2009-09-03 15:20发表的  :
因为是很早以前写的,所以测试的结果什么的记得就不是很清楚了,外加现在没电脑。

如果没错的话应该所有的投射物在z轴上都是一个方向……
一个方向?
这个理解不能……
总之是轨迹是个抛物线吧……
其实这个帖子的重要意义在于计算抛物线轨迹的公式……
很多比较小的GAER没学过抛物线
所以没法做
用公式就可以了……
其他内容诸位无视吧……
回复

使用道具 举报

发表于 2009-9-3 17:33:57 | 显示全部楼层
不懂JASS的路过iu·············
回复

使用道具 举报

发表于 2009-9-5 16:44:10 | 显示全部楼层
呀……突然发现这个在教学区有投影,呜。
竟然把水带进来了
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-4 21:26 , Processed in 0.289115 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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