设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 1886|回复: 3
打印 上一主题 下一主题

[已经过期] 求更简便的检索法

 关闭 [复制链接]

Lv1.梦旅人

虱子

梦石
0
星屑
121
在线时间
1782 小时
注册时间
2010-6-19
帖子
3597
跳转到指定楼层
1
发表于 2011-6-6 19:56:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 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的距离的远近来进行排序(不要跟我说得到数组后再排序,这样会慢很多)

http://rpg.blue/thread-175056-1-2.html
PVZ型塔防物一个
http://rpg.blue/thread-155199-1-2.html
RMXP技术讨论区手动认可帖,得到答案请认可

Lv1.梦旅人

梦石
0
星屑
55
在线时间
323 小时
注册时间
2010-8-21
帖子
666
2
发表于 2011-6-7 13:46:13 | 只看该作者
本人脑袋笨,没懂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可自行修改...

点评

厄~没看到这个,以半经为100慢0.4秒,很快了!我相信LZ的判断应该没100。  发表于 2011-6-9 01:12
这脚本一帧可能会处理10多次,你可以试试每次都慢0.4秒  发表于 2011-6-8 12:36
>>猛戳>>MetalSagaR游戏主页<<这里<<
欢迎提供您的意见
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
7976
在线时间
1183 小时
注册时间
2007-7-29
帖子
2055
3
发表于 2011-6-9 01:10:41 | 只看该作者
用圆形方程式:
(x-a)^2 + (x-b)^2 = r^2
a,b 是圆形中心点。
用这个方程式比对半经,一边侦测一边排序即可。
纯理论,没测试,不过应该会快一点,以前写slg时是使用这个方法计算的,估计差不多。

点评

表示用这个方法计算那排列有问题么?你在谷歌叔搜索insert和sort,不要用默认那效率中等的排列,使用insert的方式可以一边计算一边排列的,绝对无问  发表于 2011-6-10 12:58
表示我就是用这个方法计算的,但是要把格子按照离某事件的距离由近到远的排列...  发表于 2011-6-9 16:24

评分

参与人数 1星屑 +200 梦石 +2 收起 理由
「旅」 + 200 + 2

查看全部评分

回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
55
在线时间
323 小时
注册时间
2010-8-21
帖子
666
4
发表于 2011-6-10 17:31:21 | 只看该作者
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查表吧!

评分

参与人数 1星屑 +600 梦石 +2 收起 理由
「旅」 + 600 + 2

查看全部评分

>>猛戳>>MetalSagaR游戏主页<<这里<<
欢迎提供您的意见
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2025-7-22 23:37

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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