Project1
标题:
这段脚本有没有对游戏速度影响最小的写法
[打印本页]
作者:
typhon_524
时间:
2009-12-2 15:04
标题:
这段脚本有没有对游戏速度影响最小的写法
本帖最后由 typhon_524 于 2009-12-2 15:12 编辑
下面这段脚本是加在 Scene_Map 里的,在地图上会用事件随时调用 $scene.defence ,但是写得很长,对游戏速度有一些影响,求教有没有提高游戏速度的脚本写法
def defence
$game_variables[41] = 0 # 抗火属性归零
$game_variables[42] = 0 # 抗冰属性归零
$game_variables[43] = 0 # 抗雷属性归零
$game_variables[44] = 0 # 抗水属性归零
$game_variables[45] = 0 # 抗土属性归零
$game_variables[46] = 0 # 抗风属性归零
$game_variables[47] = 0 # 抗光属性归零
$game_variables[48] = 0 # 抗暗属性归零
for i in [32,36,40]
$game_variables[41] += 4 if $game_party.actors[0].armor1_id != 0 and $data_armors[$game_party.actors[0].armor1_id].guard_element_set.include?(i)
$game_variables[41] += 4 if $game_party.actors[0].armor2_id != 0 and $data_armors[$game_party.actors[0].armor2_id].guard_element_set.include?(i)
$game_variables[41] += 4 if $game_party.actors[0].armor3_id != 0 and $data_armors[$game_party.actors[0].armor3_id].guard_element_set.include?(i)
end
for i in [33,37,41]
$game_variables[41] += 6 if $game_party.actors[0].armor1_id != 0 and $data_armors[$game_party.actors[0].armor1_id].guard_element_set.include?(i)
$game_variables[41] += 6 if $game_party.actors[0].armor2_id != 0 and $data_armors[$game_party.actors[0].armor2_id].guard_element_set.include?(i)
$game_variables[41] += 6 if $game_party.actors[0].armor3_id != 0 and $data_armors[$game_party.actors[0].armor3_id].guard_element_set.include?(i)
end
for i in [34,38,42]
$game_variables[41] += 8 if $game_party.actors[0].armor1_id != 0 and $data_armors[$game_party.actors[0].armor1_id].guard_element_set.include?(i)
$game_variables[41] += 8 if $game_party.actors[0].armor2_id != 0 and $data_armors[$game_party.actors[0].armor2_id].guard_element_set.include?(i)
$game_variables[41] += 8 if $game_party.actors[0].armor3_id != 0 and $data_armors[$game_party.actors[0].armor3_id].guard_element_set.include?(i)
end
$game_variables[42] += 10 if $game_party.actors[0].armor1_id != 0 and $data_armors[$game_party.actors[0].armor1_id].guard_element_set.include?(2)
$game_variables[42] += 10 if $game_party.actors[0].armor2_id != 0 and $data_armors[$game_party.actors[0].armor2_id].guard_element_set.include?(2)
$game_variables[42] += 10 if $game_party.actors[0].armor3_id != 0 and $data_armors[$game_party.actors[0].armor3_id].guard_element_set.include?(2)
$game_variables[42] += 10 if $game_party.actors[0].armor4_id != 0 and $data_armors[$game_party.actors[0].armor4_id].guard_element_set.include?(2)
$game_variables[42] += 10 if $game_party.actors[0].armor5_id != 0 and $data_armors[$game_party.actors[0].armor5_id].guard_element_set.include?(2)
$game_variables[42] += 10 if $game_party.actors[0].armor6_id != 0 and $data_armors[$game_party.actors[0].armor6_id].guard_element_set.include?(2)
for i in [43,47,51]
$game_variables[42] += 2 if $game_party.actors[0].armor1_id != 0 and $data_armors[$game_party.actors[0].armor1_id].guard_element_set.include?(i)
$game_variables[42] += 2 if $game_party.actors[0].armor2_id != 0 and $data_armors[$game_party.actors[0].armor2_id].guard_element_set.include?(i)
$game_variables[42] += 2 if $game_party.actors[0].armor3_id != 0 and $data_armors[$game_party.actors[0].armor3_id].guard_element_set.include?(i)
end
for i in [44,48,52]
$game_variables[42] += 4 if $game_party.actors[0].armor1_id != 0 and $data_armors[$game_party.actors[0].armor1_id].guard_element_set.include?(i)
$game_variables[42] += 4 if $game_party.actors[0].armor2_id != 0 and $data_armors[$game_party.actors[0].armor2_id].guard_element_set.include?(i)
$game_variables[42] += 4 if $game_party.actors[0].armor3_id != 0 and $data_armors[$game_party.actors[0].armor3_id].guard_element_set.include?(i)
.............................
....................................
.................
............................
............
.............................
复制代码
作者:
紫苏
时间:
2009-12-2 18:49
本帖最后由 紫苏 于 2009-12-2 19:12 编辑
要 Ruby 最快的写法,可以从减少函数的调用上着手,命令式编程语言中,自然是函数调用越少效率越高~在你这段代码中,有很多“常量”,直到在这个函数结束前都不会改变,而每次你都调用一个函数去获取该“常量”,这个函数调用的步骤多次重复,效率就从中丢失了
比如:$game_party.actors[0]——每调用一次 $game_party.actors[0],实际上就是调用了一次 Game_Party#actors 方法获取了队员数组,并再通过这个数组调用了 Array#[] 方法去获取索引为 0 的数组元素。然而从这段代码中不难看出,变量的运算仅仅是针对队伍中的第一个队员,即 $game_party.actors[0],那完全可以用一个变量保存这个队员对象,这样之后仅仅是引用这个对象,而不会再次重复 $game_party.actors[0] 的调用了
总地来说,就是重复了很多次的相同代码,尽量把它返回的结果保存在另一个局部变量中,这样其实是用空间换取了时间~
以前两个循环为例,我们分别把优化后的代码和未经优化的代码放到两个函数中:
def defence1
$game_variables[41] = 0 # 抗火属性归零
$game_variables[42] = 0 # 抗冰属性归零
$game_variables[43] = 0 # 抗雷属性归零
$game_variables[44] = 0 # 抗水属性归零
$game_variables[45] = 0 # 抗土属性归零
$game_variables[46] = 0 # 抗风属性归零
$game_variables[47] = 0 # 抗光属性归零
$game_variables[48] = 0 # 抗暗属性归零
actor = $game_party.actors[0]
armor1_id = actor.armor1_id
armor2_id = actor.armor2_id
armor3_id = actor.armor3_id
armed1 = armor1_id != 0
armed2 = armor2_id != 0
armed3 = armor3_id != 0
armor1 = $data_armors[armor1_id]
armor2 = $data_armors[armor2_id]
armor3 = $data_armors[armor3_id]
ges1 = armor1.guard_element_set
ges2 = armor2.guard_element_set
ges3 = armor3.guard_element_set
for i in [32,36,40]
$game_variables[41] += 4 if armed1 and ges1.include?(i)
$game_variables[41] += 4 if armed2 and ges2.include?(i)
$game_variables[41] += 4 if armed3 and ges3.include?(i)
end
for i in [33,37,41]
$game_variables[41] += 6 if armed1 and ges1.include?(i)
$game_variables[41] += 6 if armed2 and ges2.include?(i)
$game_variables[41] += 6 if armed3 and ges3.include?(i)
end
# ...
end
def defence2
$game_variables[41] = 0 # 抗火属性归零
$game_variables[42] = 0 # 抗冰属性归零
$game_variables[43] = 0 # 抗雷属性归零
$game_variables[44] = 0 # 抗水属性归零
$game_variables[45] = 0 # 抗土属性归零
$game_variables[46] = 0 # 抗风属性归零
$game_variables[47] = 0 # 抗光属性归零
$game_variables[48] = 0 # 抗暗属性归零
for i in [32,36,40]
$game_variables[41] += 4 if $game_party.actors[0].armor1_id != 0 and $data_armors[$game_party.actors[0].armor1_id].guard_element_set.include?(i)
$game_variables[41] += 4 if $game_party.actors[0].armor2_id != 0 and $data_armors[$game_party.actors[0].armor2_id].guard_element_set.include?(i)
$game_variables[41] += 4 if $game_party.actors[0].armor3_id != 0 and $data_armors[$game_party.actors[0].armor3_id].guard_element_set.include?(i)
end
for i in [33,37,41]
$game_variables[41] += 6 if $game_party.actors[0].armor1_id != 0 and $data_armors[$game_party.actors[0].armor1_id].guard_element_set.include?(i)
$game_variables[41] += 6 if $game_party.actors[0].armor2_id != 0 and $data_armors[$game_party.actors[0].armor2_id].guard_element_set.include?(i)
$game_variables[41] += 6 if $game_party.actors[0].armor3_id != 0 and $data_armors[$game_party.actors[0].armor3_id].guard_element_set.include?(i)
end
end
复制代码
然后再在事件中测试运行时间:
t = Time.now
for i in 0..100000
defence1
end
p Time.now - t
t = Time.now
for i in 0..100000
defence2
end
p Time.now - t
复制代码
未经优化的 defence2 执行的时间约略是优化后的 defence1 的两倍有余,所以在 defence 经常反复调用时,速度的差距也就明显了
另外一个着手点是 include? 方法——一般的 Array 是乱序线性数组,include? 自然也就只能是线性搜索,而这厮在数组很长时是一个骨灰级的效率杀手——在最坏的场合,include? 会一直从数组开头搜索到数组结尾。你的函数中,由于 guard_element_set 本身默认就是顺序数组(除非你用了什么脚本改变了从数据库中读取的防具属性防御)的这个特殊性,include? 完全可以被优化为一个一次性的遍历(即从头到尾检查整个 guard_element_set 数组一遍),每次枚举其中的一个元素,按照自然顺序检查元素(即属性的 ID)是否为某值,若是此值如何如何,如是彼值怎样怎样……也就是说,本来的这数个 for 循环,都会变成三个 for 循环(不管你有多少个属性需要判断),每个循环分别检查 armor1、armor2 和 armor3 的三个不同的 guard_element_set。这样下来,一共只会有三次数组的遍历,最坏的场合也不过是循环中的 if 或 case 语句判断到最后一个而已
另外,在循环外,你有很长一段代码重复调用 guard_element_set.include?(2),由于参数总是 2,且 guard_element_set 也并未改变,这些 include? 都会返回相同的结果。因此,将 include? 的结果保存在变量中引用也会提高效率~
作者:
typhon_524
时间:
2009-12-3 09:07
本帖最后由 typhon_524 于 2009-12-3 09:08 编辑
非常感谢,如果我还有一个$game_party.actors[1]要添加,最好的办法是不是就直接加在后面了?这游戏最多就两个角色
def defence1
$game_variables[41] = 0 # 抗火属性归零
$game_variables[42] = 0 # 抗冰属性归零
$game_variables[43] = 0 # 抗雷属性归零
$game_variables[44] = 0 # 抗水属性归零
$game_variables[45] = 0 # 抗土属性归零
$game_variables[46] = 0 # 抗风属性归零
$game_variables[47] = 0 # 抗光属性归零
$game_variables[48] = 0 # 抗暗属性归零
actor = $game_party.actors[0]
armor1_id = actor.armor1_id
armor2_id = actor.armor2_id
armor3_id = actor.armor3_id
armed1 = armor1_id != 0
armed2 = armor2_id != 0
armed3 = armor3_id != 0
armor1 = $data_armors[armor1_id]
armor2 = $data_armors[armor2_id]
armor3 = $data_armors[armor3_id]
ges1 = armor1.guard_element_set
ges2 = armor2.guard_element_set
ges3 = armor3.guard_element_set
for i in [32,36,40]
$game_variables[41] += 4 if armed1 and ges1.include?(i)
$game_variables[41] += 4 if armed2 and ges2.include?(i)
$game_variables[41] += 4 if armed3 and ges3.include?(i)
end
for i in [33,37,41]
$game_variables[41] += 6 if armed1 and ges1.include?(i)
$game_variables[41] += 6 if armed2 and ges2.include?(i)
$game_variables[41] += 6 if armed3 and ges3.include?(i)
end
# ...
end
def petdefence
$game_variables[41] = 0 # 抗火属性归零
$game_variables[42] = 0 # 抗冰属性归零
$game_variables[43] = 0 # 抗雷属性归零
$game_variables[44] = 0 # 抗水属性归零
$game_variables[45] = 0 # 抗土属性归零
$game_variables[46] = 0 # 抗风属性归零
$game_variables[47] = 0 # 抗光属性归零
$game_variables[48] = 0 # 抗暗属性归零
actor = $game_party.actors[1]
armor1_id = actor.armor1_id
armor2_id = actor.armor2_id
armor3_id = actor.armor3_id
armed1 = armor1_id != 0
armed2 = armor2_id != 0
armed3 = armor3_id != 0
armor1 = $data_armors[armor1_id]
armor2 = $data_armors[armor2_id]
armor3 = $data_armors[armor3_id]
ges1 = armor1.guard_element_set
ges2 = armor2.guard_element_set
ges3 = armor3.guard_element_set
for i in [32,36,40]
$game_variables[41] += 4 if armed1 and ges1.include?(i)
$game_variables[41] += 4 if armed2 and ges2.include?(i)
$game_variables[41] += 4 if armed3 and ges3.include?(i)
end
for i in [33,37,41]
$game_variables[41] += 6 if armed1 and ges1.include?(i)
$game_variables[41] += 6 if armed2 and ges2.include?(i)
$game_variables[41] += 6 if armed3 and ges3.include?(i)
end
# ...
end
复制代码
欢迎光临 Project1 (https://rpg.blue/)
Powered by Discuz! X3.1