Project1

标题: 求更简便的检索法 [打印本页]

作者: Wind2010    时间: 2011-6-6 19:56
标题: 求更简便的检索法
本帖最后由 Wind2010 于 2011-6-6 20:04 编辑
  1. def get_xy_array(actor,kind,max,min=[])
  2.   get = []
  3.   # ...................中间省略几百行脚本
  4.   if kind == "圆"
  5.     min = [0] if min.size != 1
  6.     for x in -max[0]-1..max[0]+1
  7.       next if actor.x+x < 0
  8.       break if actor.x+x >= $game_map.width
  9.       for y in -max[0]..max[0]
  10.         next if actor.y+y < 0
  11.         break if actor.y+y >= $game_map.height
  12.         next if (x**2 + y**2) >= (max[0]+1)**2
  13.         next if (x**2 + y**2) < min[0]**2
  14.         get.push([actor.x+x,actor.y+y])
  15.       end
  16.     end
  17.   end
  18.   return get
  19. end
复制代码
这个是获得一个圆的数组,求一种写法,可以将数组按照与actor的距离的远近来进行排序(不要跟我说得到数组后再排序,这样会慢很多)
作者: 沙漠点灰    时间: 2011-6-7 13:46
本人脑袋笨,没懂lz看懂意思,得到数组后再排序慢...?的确会慢,不过可以无视掉...
以半径100为例,会耗时0.4秒(约3.14w个单位),而我用的是inject,相对于for..in,效率低了那么一点点,
0.4秒完全可以无视...测试代码如下:
  1. #==============================================================================
  2. # ■ Game_Character (分割定义 1)
  3. #------------------------------------------------------------------------------
  4. #  处理角色的类。本类作为 Game_Player 类与 Game_Event
  5. # 类的超级类使用。
  6. #==============================================================================

  7. class Game_Character
  8.   #--------------------------------------------------------------------------
  9.   # ● 获取圆坐标(整数)的
  10.   #--------------------------------------------------------------------------
  11.   def make_circle(ox, oy, r)
  12.     raise(RGSSError,"无用半径") if r < 1
  13.     h=(-r..r).inject({}){|a,x|(-r..r).each{|y|key=(self.x-x-ox)**2+(self.y-y-oy)**2;a[key]||=[];a[key]<<[x+ox,y+oy] if x**2+y**2<r**2};a}
  14.     h.keys.sort.inject([]){|a,i|a+h[i]}
  15.   end
  16. end
复制代码
ox, oy为圆初始x,y坐标,r为半径...
$game_player.make_circle(0,0,100)=>........此处略去几万行脚本..
没有对超过地图范围删除,lz可自行修改...
作者: enghao_lim    时间: 2011-6-9 01:10
用圆形方程式:
(x-a)^2 + (x-b)^2 = r^2
a,b 是圆形中心点。
用这个方程式比对半经,一边侦测一边排序即可。
纯理论,没测试,不过应该会快一点,以前写slg时是使用这个方法计算的,估计差不多。
作者: 沙漠点灰    时间: 2011-6-10 17:31
1帧处理10多次...?先汗一下...就算这个脚本耗时0.01秒,1帧处理10多次,FPS可以掉到1位数(理论)....,
比起什么什么函数来说,查表是最快的(貌似查表也算函数,f(x)嘛!返回一个值),
我之所以把所有坐标列出来,就是为了查表,所以,这个脚本只运行1次就好了,
重要的相对坐标,因为不知道lz到底干什么,我现在假设lz是排列100个事件...脚本如下:
  1. #==============================================================================
  2. # ■ Game_Map
  3. #------------------------------------------------------------------------------
  4. #  处理地图的类。包含卷动以及可以通行的判断功能。
  5. # 本类的实例请参考 $game_map 。
  6. #==============================================================================

  7. class Game_Map
  8.   attr_reader      :hash
  9.   alias _setup setup #可以不写什么unless,因为 ||=
  10.   def setup(map_id)
  11.     _setup(map_id)
  12.     @hash ||= make_hash
  13.   end
  14.   #--------------------------------------------------------------------------
  15.   # ● 远近坐标...
  16.   #--------------------------------------------------------------------------
  17.   def make_hash(w=self.width, h=self.height)
  18.     t = 0
  19.     z=(-w..w).inject({}){|a,x|(-h..h).each{|y|k=x*x+y*y;a[k]||=[];a[k]<<[x,y]};a}
  20.     @hash = z.keys.sort.inject({}){|a,i|z[i].each{|j|a[j]=t;t+=1};a}
  21.   end
  22.   #--------------------------------------------------------------------------
  23.   # ● 事件排序
  24.   #--------------------------------------------------------------------------
  25.   def sort_events(e_id, x=$game_player)
  26.     (e_id.inject([]){|a,i|a[@hash[[x.x-@events[i].x,x.y-@events[i].y]]]=i;a}).compact
  27.   end
  28. end
复制代码
本人测试80*80地图,因为相对坐标原因会计算80*80*4个坐标出来,每次换地图计算一次,建议加入Loading画面,因为超过
100000个地图单位(314*315左右)会计算超过10秒(可能,没测试),
测试代码如下:
  1. p $game_map.sort_events(1..100)
复制代码
不过严格来说应该是
  1. p $game_map.sort_events((1..100).to_a, $game_player)
复制代码
是数组,而非范围,表示事件编号,100个事件耗时0.0秒(没法计算..太短了..)
所以,lz尝试用Hash查表吧!




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1