Project1

标题: 【更新】提高游戏运行速度_v1.01 [打印本页]

作者: 一箭烂YiJL    时间: 2011-4-22 17:00
标题: 【更新】提高游戏运行速度_v1.01
本帖最后由 一箭烂YiJL 于 2011-4-25 11:55 编辑

-1.序前序
我还是第一次在XP区发布(我是VX区驻扎人员,偶然探望XP区= =),由于这一帖:【更新】提高游戏运行速度(v1.01)
需要在XP的移植,因为XP并没有Scene_Base,所以用了也无效。
于是"下手"在了Graphics.update。这种手法既能用于XP,又能用于VX
在XP的非"平滑模式"下,会卡着,具体原因是用了Graphics.frame_count来判断"跳帧",
后来我又用了另外的解决办法,但是当非"平滑模式"下,将倍数x2后,(其他的都没问题)
fps会莫名其妙的增加至40帧,于是这个只是应用在游戏测试中而已。
之后以下的句子跟VX的帖子一样:
(ps:VX没有XP的v1.01更新内容,因为VX没有F12问题= =)


0.序
往往游戏过程因为太慢,所以想高速测试有难度。
最简单的办法是将帧频率调高,但是不能超过120。
这办法适用在游戏测试中(尤其是破关时间),请不要发布于游戏中,
因为速度不等于效率,极快会感觉一卡一卡。


1.讲解
当删掉Graphics.update时,会出现画面不更新,但是操作极快的问题。
loop do绝对超过一秒60次(帧频率)。于是这是我的猜测
Graphics.update除了有更新画面的基本动作外,还会有:
  1. sleep(1/Graphics.frame_rate - 更新画面的时间 - 逻辑运算的时间)    # 此处经过修正
复制代码
所以不用Graphics.update就会高速不断地循环计算。

2.脚本
综合以上,脚本如下:

  1. #==============================================================================
  2. # ■ 提高游戏速度(v1.0.1)    by 一箭烂
  3. #------------------------------------------------------------------------------
  4. #  设置Graphics的@speed_lv以提高游戏速度,
  5. #    请插在main以上的位置
  6. #
  7. #  属性:
  8. #
  9. #    Graphics.speed_lv
  10. #      加快速度(倍数), 可修改
  11. #
  12. #  更新:
  13. #
  14. #    - *1.0.1* (2011-04-21) By 一箭烂(YiJL)
  15. #      *改了些东西, 解决F12问题
  16. #      *换了速度变量的方式
  17. #
  18. #    - *1.0.0* (2011-04-21) By 一箭烂(YiJL)
  19. #      *初版
  20. #      *对Graphics.frame_count的修正
  21. #
  22. #==============================================================================
  23. module Graphics
  24.   @speed_lv     = 5            # 加快速度(倍数)
  25.   @timer        = 0
  26.   @speed_update = method("update") unless @speed_update
  27.   #--------------------------------------------------------------------------
  28.   # ● Graphics.update
  29.   #--------------------------------------------------------------------------
  30.   def self.update
  31.     @timer += 1
  32.     @timer %= @speed_lv
  33.     if @timer >= (@speed_lv - 1)
  34.       @speed_update.call             # 更新游戏画面
  35.       Graphics.frame_count -= 1
  36.     end
  37.     Graphics.frame_count += 1
  38.   end
  39.   #--------------------------------------------------------------------------
  40.   # ● Graphics.speed_lv
  41.   #--------------------------------------------------------------------------
  42.   def self.speed_lv
  43.     @speed_lv
  44.   end
  45.   #--------------------------------------------------------------------------
  46.   # ● Graphics.speed_lv=
  47.   #--------------------------------------------------------------------------
  48.   def self.speed_lv=(value)
  49.     @speed_lv = value
  50.   end
  51. end
复制代码
用#------
 #------包着的这些是外加的意思。

3.其他
实质上帧频率不变,但是做一次Graphics.update(画面更新)就等于做了x次的其他数据运算。
当数据运算量太大时就可能会有卡的状况。(Speed_Lv影响着数据运算比起平常倍数!)
还有现在的版本只能加速/不加速,不能减速!

4.范例
没什么范例可给的,一插脚本就见效嘛~伸手要范例的回帖去吧。
算了,有些无谓的回帖,但是又不是下载的,慢慢在草原奔跑吧~
提高游戏运行速度_v1.01.zip (203.58 KB, 下载次数: 1655)

作者: Wind2010    时间: 2011-4-22 17:21
我想知道这样alias按F12会出错么?
作者: IamI    时间: 2011-4-22 17:33
F12必挂……另外减速其实就是多开几次update嘛 - -b
另外没改frame_count、画面没有实质刷新,本质上等于跳帧- -b
作者: 一箭烂YiJL    时间: 2011-4-22 17:45
本帖最后由 一箭烂YiJL 于 2011-4-22 17:52 编辑

回复 IamI 的帖子

class<<和alias真是麻烦...有办法解决F12么?

减速的方法早已留意到,但是随意的倍数(浮点数倍数)需要sleep了。
(毕竟这个是提高速度...)

事实上是跳帧的原理,同样的加快frame_count是给逻辑运算和PlayTime用的,
方便测试游戏时间和逻辑运算的准确性。
重申速度不等于效率= =

最莫名其妙的是如果另外开一个实例变量来储存真的Graphics.frame_count,
用于修正Graphics.frame_count,这样虽然可以兼容了非"平滑模式",
但是却在倍数为2的时候出现上调至40帧频率的问题。
作者: 忧雪の伤    时间: 2011-4-22 18:29

  1. class << Graphics
  2.   @speed_Lv = 2
  3.   alias :speed_update :update unless method_defined?("speed_update")
  4.   def update
  5.     @timer = 0 if @timer.nil?
  6.     @timer += 1
  7.     @timer %= @speed_Lv
  8.     if @timer >= (@speed_Lv - 1)
  9.       speed_update            
  10.       Graphics.frame_count -= 1
  11.     end
  12.     Graphics.frame_count += 1
  13.   end
  14. end
复制代码
F12神马的……顺便改了下全局变量……
可以不用全局还是不用吧?……
作者: 一箭烂YiJL    时间: 2011-4-22 18:53
回复 忧雪の伤 的帖子

@speed_Lv还不算被定义了,所以会出错。
用全局变量可以在任何地方随时改变加速倍数。(而且不会没定义)

以前还不知道F12干啥的。现在知道了,也不知道F12这么快重载的原理。
总之,谢谢提出F12解决办法。
作者: 剑兰的马甲    时间: 2011-4-22 21:32
回复 忧雪の伤 的帖子

更新了,虽然没有用你提供办法,但是F12依然已经解决,
而且不用class的形式编写了,而是用了本身的module。

之前所说的@speed_Lv还没定义,是因为并非以module的形式编写,
导致不能将@speed_Lv赋值。(除非函数触动的方式)
作者: 苏小脉    时间: 2011-4-23 09:33
一箭烂YiJL 发表于 2011-4-22 17:45
回复 IamI 的帖子

class

解决 F12:
http://szsu.wordpress.com/2010/09/07/continuation/
作者: 一箭烂YiJL    时间: 2011-4-23 10:46
回复 苏小脉 的帖子

试过了,的确能够解决F12的函数问题(包括module的method)。
原理是将整个架构保存一次,然后再F12重载的时候将架构复原,是吗?

但是我发现这样有点问题,当如这样所说,插入了以后,
在中间写下:p true,F12不会执行,又比如在一个新工程画白色背景:
  1. back = Sprite.new
  2. back.z = 1
  3. back.bitmap = Bitmap.new(640, 480)
  4. back.bitmap.fill_rect(0, 0, 640, 480, Color.new(255,255,255))
复制代码
第一次的时候,白背景将标题背景遮住了。F12,白背景不见了。
就算(module的)实例变量也有相同的问题,苏可以在沉影的(dll)鼠标系统里试试,
会发生disposed sprite的问题。

也不知道这真是问题还是我搞错呢......
作者: 苏小脉    时间: 2011-4-23 10:57
一箭烂YiJL 发表于 2011-4-23 10:46
回复 苏小脉 的帖子

试过了,的确能够解决F12的函数问题(包括module的method)。

原理是记录 Main 脚本之前的堆栈环境,F12 回到开头的时候直接全局跳转到记录点。中间写的东西 F12 之后不会执行第二次,所以希望 F12 后重新执行的内容得放在 callcc 的调用下面。
作者: 后知后觉    时间: 2011-4-23 11:18
本帖最后由 后知后觉 于 2011-4-23 11:19 编辑

回复 一箭烂YiJL 的帖子

主要就要看 谁来适应谁 了.
作者: 一箭烂YiJL    时间: 2011-4-23 17:49
回复 苏小脉 的帖子

也就是要在函数中赋值。 alias放上,原版更上?但原版是函数外赋值的话,就麻烦了。
如果能对method、alias、alias_method......下做method_defined?、unless...的话能解决?
作者: 苏小脉    时间: 2011-4-24 01:53
一箭烂YiJL 发表于 2011-4-23 17:49
回复 苏小脉 的帖子

也就是要在函数中赋值。 alias放上,原版更上?但原版是函数外赋值的话,就麻烦了。

什么“函数中赋值”?不解。

我在那篇文章中写道把 callcc 放在 Main 脚本开头是因为考虑到 Main 脚本之前都有可能发生 alias 的问题,如果你确信某段脚本没有 alias 的问题,然后希望 F12 后重新执行,就把 callcc 的调用提前到该脚本执行前就行了。如果有不连贯的情况,比如前一段需要重新执行,而后一段又会有 alias 的问题,那可以连续设两个 Continuation 跳转点。

判断 method_defined? 可以解决问题,但不是所有写脚本的人都有这个习惯,要是需要去兼容没有这个判断的,同时又使用了大量 alias 的脚本,就要大费周章了。
作者: 一箭烂YiJL    时间: 2011-4-24 10:56
回复 苏小脉 的帖子

“函数中赋值”意思是要在函数中定义变量的值:
  1. @a = 50 if @a.nil?
  2. @b = Sprite.new if @b.nil? or @b.disposed?
复制代码
但是在常用的update中会耗用逻辑运算时间。
(尤其在没有initialize的模块类,除非另外开一个函数定义变量。)

还要自设跳转点啊...那么alias那些就要跟函数外定义变量的模块都要拆开?

我指的"下手"是在method、alias、alias_method......这些函数内部下手,
让method_defined?为false的时候才工作。(但是这似乎是不可能的)
作者: 苏小脉    时间: 2011-4-24 11:49
回复 一箭烂YiJL 的帖子
“函数中赋值”意思是要在函数中定义变量的值
抱歉,我还是没跟上,这个和我们之前讨论的有什么联系?

还要自设跳转点啊...那么alias那些就要跟函数外定义变量的模块都要拆开?

不用啊,为什么?那篇文章里面给的例子就是在 Main 的开头设立了一个跳转点,我的意思是需要的话可以在不同的地方设立多个,这样可以控制 F12 之后哪段执行,哪段跳过。

我指的"下手"是在method、alias、alias_method......这些函数内部下手,
让method_defined?为false的时候才工作。(但是这似乎是不可能的)

只要是 Ruby 的方法就可以钩住,但是语法糖 alias 不行,因为它直接调用底层的 alias 实现了。当然,可以扩展 Ruby。
作者: eve592370698    时间: 2011-4-24 13:49
标题: 那个分辨率扩展卡屏不简单
本帖最后由 eve592370698 于 2011-4-24 20:24 编辑

是吗?http://rpg.blue/thread-162509-1-1.html这个是用分辨率扩展会卡屏的缺陷能解决吗?
图片是一方面,还有就是事件超过30个会卡屏,如果设置了远景图和雾,事件超过50个,那FPS就是个位数了。

ZTBS战旗系统86.rar

1.16 MB, 下载次数: 60


作者: ★PIG★    时间: 2011-4-24 14:08
哦?并行变量运行太多能有帮助么……研究研究
作者: 一箭烂YiJL    时间: 2011-4-24 21:45
回复 苏小脉 的帖子
抱歉,我还是没跟上,这个和我们之前讨论的有什么联系?

之前不是说过用您的办法后函数外给变量定义会出错么?(沉影dll鼠标会出现Sprite disposed)
但是函数内给变量定义且没问题。看一下两个例子:
  1. # 函数外赋值(F12杯具)
  2. $__f12_no_reeval.call if $__f12_no_reeval
  3. module AAA
  4.   @a = Sprite.new
  5.   def self.a
  6.     @a.x = 100
  7.     p @a.x
  8.   end
  9. end
  10. callcc { |$__f12_no_reeval| }
  11. AAA.a     # 代表Scene_Base的update
复制代码

如果是函数内赋值:
  1. # 函数内赋值(F12无问题, 但耗费逻辑时间)
  2. $__f12_no_reeval.call if $__f12_no_reeval
  3. module AAA
  4.   def self.a
  5.     @a = Sprite.new if @a.nil? or @a.disposed?
  6.     @a.x = 100
  7.     p @a.x
  8.   end
  9. end
  10. callcc { |$__f12_no_reeval| }
  11. AAA.a     # 代表Scene_Base的update
复制代码

不用啊,为什么?那篇文章里面给的例子就是在 Main 的开头设立了一个跳转点,我的意思是需要的话可以在不同的地方设立多个,这样可以控制 F12 之后哪段执行,哪段跳过。

如果跳一次的话,就要将alias和函数外定义变量分开= =但是跳来跳去也挺乱的。
但是这样(即有alias和函数外定义变量):
  1. #~ $__f12_no_reeval.call if $__f12_no_reeval
  2. module Graphics
  3.   @speed_update = method("update")
  4.   @speed_lv = Sprite.new
  5.   @speed_lv.x = 50
  6.   def self.update
  7.     a = @speed_lv.x
  8.     @speed_update.call
  9.   end
  10. end
  11. #~ callcc { |$__f12_no_reeval| }
  12. Graphics.update      # 代表后置的场景操作
  13. # 用callcc的时候会发生Sprite disposed
  14. # 不用的时候会发生stack level too deep
复制代码

而我说的将两者分开的做法是这样:
  1. $__f12_no_reeval.call if $__f12_no_reeval
  2. # alias/函数 堆
  3. module Graphics
  4.   @speed_update = method("update")
  5.   def self.update
  6.     a = @speed_lv.x
  7.     @speed_update.call
  8.   end
  9. end

  10. callcc { |$__f12_no_reeval| }  # callcc

  11. # 函数外赋值 堆
  12. module Graphics
  13.   @speed_lv = Sprite.new
  14.   @speed_lv.x = 50
  15. end

  16. Graphics.update      # 代表后置的场景操作
复制代码

我想您说的办法应该是这样:

  1. $__f12_no_reeval.call if $__f12_no_reeval
  2. module Graphics
  3.   @speed_update = method("update")
  4.   callcc { |$__f12_no_reeval| }    # callcc
  5.   @speed_lv = Sprite.new
  6.   @speed_lv.x = 50
  7.   def self.update
  8.     a = @speed_lv.x
  9.     @speed_update.call
  10.   end
  11. end
  12. Graphics.update      # 代表后置的场景操作
复制代码

嗯~相信您会清楚我在说啥...

作者: 苏小脉    时间: 2011-4-25 02:50
一箭烂YiJL 发表于 2011-4-24 21:45
回复 苏小脉 的帖子

哈,劣兄愚钝,压根没想到。一箭老弟果然思绪缜密~
作者: 中华素面    时间: 2011-4-25 11:22
我要范例啊!!!!!!!




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