Project1

标题: 公共事件的一个疑问 [打印本页]

作者: y967    时间: 2019-11-28 09:55
标题: 公共事件的一个疑问
公共事件并行处理为什么不卡,而地图并行有时候事件多了就会崩溃,这样来看,似乎可以用公共事件制作套装效果,也不至于卡。
作者: ppspssss    时间: 2019-11-28 17:55
公共事件多了一樣会卡, 就算全腳本化一樣会卡, 不过你使用轉換VX,和VX ACE引擎的話可以流暢
作者: guoxiaomi    时间: 2019-12-3 02:01
地图上的事件远比普通的公共事件要复杂,带来的计算量也是非常高的。
比如:
1. Game_Character 1中150行的 passable? 方法内。此处对全部的事件进行了循环处理,判断此事件是否位于Player的正前方。
2. Game_Event的 refresh 方法会便利整个事件的全部事件页,并选出满足触发条件的唯一事件页。
3. Game_Player中120行的check_event_trigger_here方法内,此处同样对全部的事件进行了循环,判断此事件是否在角色脚下。

以上1会在每次事件或主角移动时触发,2和3会在每帧触发,这些都会拖累执行效率。
作者: YukiYukidesu    时间: 2019-12-3 15:58
guoxiaomi 发表于 2019-12-3 02:01
地图上的事件远比普通的公共事件要复杂,带来的计算量也是非常高的。
比如:
1. Game_Character 1中150行的 ...


(写给楼主)
针对上述1、3点有个行之有效的方法(前提你听得懂)
在Game_Map里维护一个至少定义了读方法的二维数组或一个Hash,以下简称坐标容器吧
在Event定义时将event对象加入到坐标容器中它的坐标的下标/键的位置
覆盖Game_Event的所有能使坐标变化的方法(为了保证坐标变化反映的实时性)(这些方法得从父类Game_Character找起,VA封装得不错,很多方法最终汇集到寥寥几个方法中改变坐标如move_straight,XP明显就分散多了,改坐标的方法一大堆……)
在变化前以坐标为索引删除Game_Map中坐标容器中的self引用,在变化后以新坐标插入self引用(如果你知道super的话一定懂怎么实现),无论坐标是否真的改变都这样做
最后将所有判断事件位置的地方都改为使用这个坐标容器参考

下面是我在VA上用的例子:
  1. class Game_Map
  2.   def setup_events
  3.     @events = {}
  4.     ...
  5.     @event_point = {}
  6.     @map.events.each do |id, event|
  7.         ...
  8.         @events[id] = Game_Event.new(@map_id, event)
  9.       end
  10.       if @events[id]
  11.         @event_point[[@events[id].x, @events[id].y]] ||= []
  12.         @event_point[[@events[id].x, @events[id].y]] << @events[id]
  13.       end
  14.     end
  15.     ...
  16.   end
复制代码
  1. class Game_Event < Game_Character
  2.   ...
  3.   def moveto(x, y)
  4.     location_remove
  5.     super
  6.     location_insert
  7.   end
  8.   def move_straight(d, turn_ok = true)
  9.     location_remove
  10.     super
  11.     location_insert
  12.   end
  13.   def move_diagonal(horz, vert)
  14.     location_remove
  15.     super
  16.     location_insert
  17.   end
  18.   def jump(x_plus, y_plus)
  19.     location_remove
  20.     super
  21.     location_insert
  22.   end
  23.   def location_remove
  24.     return if !$game_map.event_point[[@x, @y]]
  25.     $game_map.event_point[[@x, @y]].delete(self)
  26.   end
  27.   def location_insert
  28.     $game_map.event_point[[@x, @y]] ||= []
  29.     $game_map.event_point[[@x, @y]].push(self)
  30.   end
  31. end
复制代码
  1. class Game_Map
  2.   def events_xy(x, y)
  3.     @event_point[[x, y]] ||= []
  4.   end
  5.   def events_xy_any?(x, y, except = nil)
  6.     events_xy(x, y).any? {|event| event != except }
  7.   end
  8.   def events_xy_nt(x, y)
  9.     events_xy(x, y).select {|event| !event.through }
  10.   end
  11.   ............
  12. end
复制代码

可以简化坐标判定的计算,实测在VA上200事件的50*50地图都不会掉帧,当然这个可能有着RGD的加成
至于XP上那些坐标判断或坐标修改的方法具体在哪,一般多出现于Game_Map Game_Character Game_Event Game_Player(甚至Interpreter?),运用好全局搜索(就是在左边的脚本库栏目里右键搜索),关键字一般是@x =,@y =,for event in events.values之类的,更多的看你的理解吧。
作者: SixRC    时间: 2019-12-3 22:48
本帖最后由 SixRC 于 2019-12-3 22:50 编辑
guoxiaomi 发表于 2019-12-3 02:01
地图上的事件远比普通的公共事件要复杂,带来的计算量也是非常高的。
比如:
1. Game_Character 1中150行的 ...


我想的和四楼几乎一样
然后被抢先啦
那我就写一个
开始测试的时候和原版效率几乎一样 后来发现是我创建事件的时候选了可穿透...
event_opt.zip (211.94 KB, 下载次数: 62)

仅用于测试思路效果

默认打开是没有任何优化的
在 测试用 代码页 $EVEOPT = false
决定了是否开启按坐标切分事件
其后四个代码页分别是对
Game_Map    Game_Character   Game_Event   Game_Player  的覆盖修改
涉及到的地方其实并不多
保留了旧的 @events 新加了个 @events_new
因为只有涉及坐标判定的地方需要优化  别的可以照旧
思路 应该还算清晰吧..
在改动的地方我注出来了

很好奇为什么之前没有人写这个...

fps_unlimit 代码页是之前写的 防卡有奇效 用于103J dll




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