010 Fake
这期教程,我们来讲解写特性时的思考逻辑,即写特性时到底该如何思考。
那么首先,最基本的就是抄,抄相似的代码,这个之前也已经是说过了。
但是,如果你不知道Ruby的一些基础的话,你可能抄都会抄错,但是,如何抄代码和Ruby基础并不是这期教程的主要内容。
这期教程我们要讲的是如何理顺你的代码。
那么怎么做呢?
可以使用坊间流传的伪代码方法。
就我个人来说,我并不推荐使用伪代码,但是,伪代码毕竟也有它的一定价值,特别是对于初学者来说。
那么什么是伪代码呢?
伪代码就是使用中文代替真正的代码方法来写成的代码。
你可能会有一点晕,没关系,你很快就会理解的,我们来看这个特性——
![1721304430369.png 1721304430369.png](https://bbs.pokefans.cn/data/attachments/2/2416-5ab0422c159b2b8736e6f7b96a88a607.jpg)
这是青草制造者的代码。
那假如说不存在青草制造者这么一个特性,接着你新建了一个特性,这个特性就叫做青草制造者,而这个特性的效果就是在出场时开出青草场地。
那么你会如何思考?
如果是我的话,我会这样——
首先,找到对应的Handler,把基本结构弄好,接着再使用伪代码进行填充——
那么,这样就好了吗?
还并不是,为了代码的严谨性,其实还需要检查一下现在是否已经是青草场地了,如果已经是青草场地了,那就没有必要发动这个特性了,对不对?
所以修改之后应该是这样的——
把伪代码完成之后,接着就是把伪代码转化为真正的代码。
那么我们就一点点来——
关于特性条的这两行代码,基本没什么好说的,随便抄一下就有了,不过这里还是再次强调,注意参数。
现在还有两行伪代码需要转化,我们就先转化第一行,第一行我们要判断当前场地是否已经是青草场地了,想一下可以抄哪里?
可以抄草之毛皮——
![1721304514646.png 1721304514646.png](https://bbs.pokefans.cn/data/attachments/2/2417-ac81ad513c36780c0a61c959a86f96e0.jpg)
所以——
这里你有没有发现一个神奇的地方?
在草之毛皮里,并没有battle参数,所以它先对user调用了battle以调出battle。
但是,在我们的代码里,本来就有battle了,所以并不需要这样额外多调用一步,直接就可以用battle。
那有同学可能就会想了,那这里我写battler.battle.field.terrain == :Grassy这样行不行呢?
当然行,但是没有必要,为什么,因为我们这里已经有battle,你并不需要这样多此一举,直接用battle就行了。
那么我们继续,还有最后一行伪代码需要转化,说实话,最后这一行其实挺难呢,为什么呢?
因为“开出青草场地”,这显然是一个动作,你需要一个方法来执行这个动作,如果本来就已经有这个方法了,那你直接调用方法就好;
但是,如果本来没有这个方法的话,那你就要自己新写一个方法。
新写方法并不是我们这期教程的主要内容,所以到这里就足够了。
这个时候,可能有同学会说,既然前面可以直接检查battle.field.terrain == :Grassy,那么这里是否可以直接写battle.field.terrain = :Grassy呢?
这里可能会有同学看不懂了,这里的区别是,一个是两个等号,一个只有一个等号。
两个等号是比较,就是比较一下battle.field.terrain是不是:Grassy;
而一个等号是赋值,就是让左边的等于右边的。
你可能会看到有一些教程说这个不是等于,说什么等于是等于,赋值是赋值,是不一样的,但我想说的是,这个就是等于,逞口舌之快是没有任何意义的,并不会因为你怎么叫这个东西而改变你怎么使用这个东西。
别人怎么说是别人的事情,你怎么认为是你的事情,但至少在我的这系列教程中赋值 == 等于。
这个跟数学里面的是一样的,我们设x = 1,或者说这样写了,那是不是x就是等于1?是不是x就是1?
你用赋值来理解的话就是,你把等号右边的值,赋予给了等号左边的这个东西,或者说等号左边的这个东西,目前存储了一个值,这个值和等号右边的这个值是一样的,我们在之前的教程中也提到过,“我们需要一个变量,或者说一个东西,来额外存储这个特性是否已经发动过了。”
要说和数学里的有什么不一样的话,那就是数学里面如果你写了x = 1,那么x就是1了,它就不会变了,也就是说此时x是一个常量了,它不会变,不能变。
但是在我们写代码时,如果写了x = 1,那么仅仅只是某一段时间x是1,如何理解这个某一段时间呢?
这个某一段时间,其实指的是x被赋值,直到x再被赋值的这段时间,也就是说,x是会变的,或者你说x在不同时间所存储的东西是不一样的,这也是为什么我们说x是一个变量,因为它会变,可以变。
我们来看这段代码——
这里,我先让x等于1,然后再让x等于2,并且我在让x等于多少之后,立刻puts了x。
这里的puts,意思是打印,就是在控制台中显示出x是什么。
那么我们就进游戏看一下吧——
![1721304566378.png 1721304566378.png](https://bbs.pokefans.cn/data/attachments/2/2418-04eff14e28fca2ed9f36be5dbd12be37.jpg)
![1721304573342.png 1721304573342.png](https://bbs.pokefans.cn/data/attachments/2/2419-acb07536efe9aa028436c8a9b4de0a86.jpg)
![1721304580575.png 1721304580575.png](https://bbs.pokefans.cn/data/attachments/2/2420-559360340385ee64805410441f191d07.jpg)
![1721304588511.png 1721304588511.png](https://bbs.pokefans.cn/data/attachments/2/2421-61d525c45cbd33bcde875ef38291d707.jpg)
![1721304596983.png 1721304596983.png](https://bbs.pokefans.cn/data/attachments/2/2422-757eeae7a5bc3100a27c371c4b24e663.jpg)
我们可以看到,控制台里打印出了1和2。
所以,当每一次x被=时,x就变了。
这边也顺便说一下,我额外安装了Deluxe Battle Kit(DBK)和Enhanced Battle UI(EBUI)这两个插件,不要在意。
并且,我用的DBK和EBUI就是如图所示的版本,在这套教程中,即使插件出了新的版本,如果我没有特别说明过的话,就代表我没有更新插件到新版本。
最后,我们再强调一下——
=,等于,或者说赋值;
==,比较。
在你自己实际写代码的时候不要手快了,检查代码的时候也不要看快了!
那么怎么记呢?
不需要记,多写就会了,你真要记的话,也就只需要记一下两个=是比较就行了,因为一个=跟你在学校里学到的已有的认知没有什么区别。
这边还是需要额外提一下,不管你是说等于还是说赋值,实际上在针对数组的时候,也并不是真的等于或者赋值,如果我们这样写——
aa = [1, 2, 3] # aa现在是一个数组
bb = aa # bb现在也是一个数组,并且和aa一模一样
aa[0] = 4 # 让aa的第一个元素变成4
那么请问,这个时候如果我们打印bb,会输出什么,是[1, 2, 3],还是[4, 2, 3]?
我们就把这一段代码复制到我们的伪代码里——
进游戏测试——
![1721304632448.png 1721304632448.png](https://bbs.pokefans.cn/data/attachments/2/2423-13a4aa4b1ee9861851e0093ac5dcb753.jpg)
![1721304639613.png 1721304639613.png](https://bbs.pokefans.cn/data/attachments/2/2424-f7a541e1b9cee505bce2a372d1c619ac.jpg)
我们可以看到,输入的结果应该是[4, 2, 3]。
你说这样你看不出来?
那我们可以再稍微修改一下代码——
接着进游戏测试——
![1721304672359.png 1721304672359.png](https://bbs.pokefans.cn/data/attachments/2/2425-08f9680189b183b59f455c58ce70c90e.jpg)
现在我们可以非常清楚的看到了,我们也得到了之前的问题的答案,如果我们打印bb,会输出[4, 2, 3]。
所以,在针对数组的时候,并不会使某个变量等于或者被赋值那一个数组,实际上这个变量只是引用了原始的数组,当原始数组被改变的时候,这个变量也会跟着变,即使没有对这个变量本身做=处理。
现在,回到我们之前的这个问题“既然前面可以直接检查battle.field.terrain == :Grassy,那么这里是否可以直接写battle.field.terrain = :Grassy呢?”
我的严谨的答案是,我不知道,你其实需要自己去实践尝试才能知道是否可以直接赋值来达到目标。
但是,说是这么说,其实我是不建议你直接赋值的,因为当场地改变的时候,会发生很多事情,比如说出现一行字提示,出现场地的动画,新开启的场地要持续几回合,触发其他精灵的特性,触发物品的效果,等等。
所以你最好还是额外写个方法来做。
事实上,ESS原本的代码也的确是写了一个方法——
![1721304686760.png 1721304686760.png](https://bbs.pokefans.cn/data/attachments/2/2426-2a0a69a44ac44a1c13102b32553f8547.jpg)
![1721304693121.png 1721304693121.png](https://bbs.pokefans.cn/data/attachments/2/2427-6724a7406dc911b64a38f8f3c9a59672.jpg)
![1721304700490.png 1721304700490.png](https://bbs.pokefans.cn/data/attachments/2/2428-6810bb1209e68fd9f2449eea1ce373c3.jpg)
这个就是ESS原本的用来开启新的场地的方法。
这个方法其实是有缺陷的,因为它不能自由控制开启的新场地的回合数,现在就算了,以后有机会的话我们再来优化这个方法。
那么这期教程就到此为止,下期教程我们将会讲解PBEffects。
感谢阅读。
这期教程,我们来讲解写特性时的思考逻辑,即写特性时到底该如何思考。
那么首先,最基本的就是抄,抄相似的代码,这个之前也已经是说过了。
但是,如果你不知道Ruby的一些基础的话,你可能抄都会抄错,但是,如何抄代码和Ruby基础并不是这期教程的主要内容。
这期教程我们要讲的是如何理顺你的代码。
那么怎么做呢?
可以使用坊间流传的伪代码方法。
就我个人来说,我并不推荐使用伪代码,但是,伪代码毕竟也有它的一定价值,特别是对于初学者来说。
那么什么是伪代码呢?
伪代码就是使用中文代替真正的代码方法来写成的代码。
你可能会有一点晕,没关系,你很快就会理解的,我们来看这个特性——
![1721304430369.png 1721304430369.png](https://bbs.pokefans.cn/data/attachments/2/2416-5ab0422c159b2b8736e6f7b96a88a607.jpg)
这是青草制造者的代码。
那假如说不存在青草制造者这么一个特性,接着你新建了一个特性,这个特性就叫做青草制造者,而这个特性的效果就是在出场时开出青草场地。
那么你会如何思考?
如果是我的话,我会这样——
Ruby:
Battle::AbilityEffects::OnSwitchIn.add(:GRASSYSURGE,
proc { |ability, battler, battle, switch_in|
}
)
Ruby:
Battle::AbilityEffects::OnSwitchIn.add(:GRASSYSURGE,
proc { |ability, battler, battle, switch_in|
特性条出现
开出青草场地
特性条消失
}
)
还并不是,为了代码的严谨性,其实还需要检查一下现在是否已经是青草场地了,如果已经是青草场地了,那就没有必要发动这个特性了,对不对?
所以修改之后应该是这样的——
Ruby:
Battle::AbilityEffects::OnSwitchIn.add(:GRASSYSURGE,
proc { |ability, battler, battle, switch_in|
next if 青草场地
特性条出现
开出青草场地
特性条消失
}
)
把伪代码完成之后,接着就是把伪代码转化为真正的代码。
那么我们就一点点来——
Ruby:
Battle::AbilityEffects::OnSwitchIn.add(:GRASSYSURGE,
proc { |ability, battler, battle, switch_in|
next if 青草场地
battle.pbShowAbilitySplash(battler) # 特性条出现
开出青草场地
battle.pbHideAbilitySplash(battler) # 特性条消失
}
)
现在还有两行伪代码需要转化,我们就先转化第一行,第一行我们要判断当前场地是否已经是青草场地了,想一下可以抄哪里?
可以抄草之毛皮——
![1721304514646.png 1721304514646.png](https://bbs.pokefans.cn/data/attachments/2/2417-ac81ad513c36780c0a61c959a86f96e0.jpg)
所以——
Ruby:
Battle::AbilityEffects::OnSwitchIn.add(:GRASSYSURGE,
proc { |ability, battler, battle, switch_in|
next if battle.field.terrain == :Grassy
battle.pbShowAbilitySplash(battler) # 特性条出现
开出青草场地
battle.pbHideAbilitySplash(battler) # 特性条消失
}
)
在草之毛皮里,并没有battle参数,所以它先对user调用了battle以调出battle。
但是,在我们的代码里,本来就有battle了,所以并不需要这样额外多调用一步,直接就可以用battle。
那有同学可能就会想了,那这里我写battler.battle.field.terrain == :Grassy这样行不行呢?
当然行,但是没有必要,为什么,因为我们这里已经有battle,你并不需要这样多此一举,直接用battle就行了。
那么我们继续,还有最后一行伪代码需要转化,说实话,最后这一行其实挺难呢,为什么呢?
因为“开出青草场地”,这显然是一个动作,你需要一个方法来执行这个动作,如果本来就已经有这个方法了,那你直接调用方法就好;
但是,如果本来没有这个方法的话,那你就要自己新写一个方法。
新写方法并不是我们这期教程的主要内容,所以到这里就足够了。
这个时候,可能有同学会说,既然前面可以直接检查battle.field.terrain == :Grassy,那么这里是否可以直接写battle.field.terrain = :Grassy呢?
这里可能会有同学看不懂了,这里的区别是,一个是两个等号,一个只有一个等号。
两个等号是比较,就是比较一下battle.field.terrain是不是:Grassy;
而一个等号是赋值,就是让左边的等于右边的。
你可能会看到有一些教程说这个不是等于,说什么等于是等于,赋值是赋值,是不一样的,但我想说的是,这个就是等于,逞口舌之快是没有任何意义的,并不会因为你怎么叫这个东西而改变你怎么使用这个东西。
别人怎么说是别人的事情,你怎么认为是你的事情,但至少在我的这系列教程中赋值 == 等于。
这个跟数学里面的是一样的,我们设x = 1,或者说这样写了,那是不是x就是等于1?是不是x就是1?
你用赋值来理解的话就是,你把等号右边的值,赋予给了等号左边的这个东西,或者说等号左边的这个东西,目前存储了一个值,这个值和等号右边的这个值是一样的,我们在之前的教程中也提到过,“我们需要一个变量,或者说一个东西,来额外存储这个特性是否已经发动过了。”
要说和数学里的有什么不一样的话,那就是数学里面如果你写了x = 1,那么x就是1了,它就不会变了,也就是说此时x是一个常量了,它不会变,不能变。
但是在我们写代码时,如果写了x = 1,那么仅仅只是某一段时间x是1,如何理解这个某一段时间呢?
这个某一段时间,其实指的是x被赋值,直到x再被赋值的这段时间,也就是说,x是会变的,或者你说x在不同时间所存储的东西是不一样的,这也是为什么我们说x是一个变量,因为它会变,可以变。
我们来看这段代码——
Ruby:
Battle::AbilityEffects::OnSwitchIn.add(:GRASSYSURGE,
proc { |ability, battler, battle, switch_in|
x = 1
puts x
next if battle.field.terrain == :Grassy
battle.pbShowAbilitySplash(battler) # 特性条出现
# 开出青草场地
x = 2
puts x
battle.pbHideAbilitySplash(battler) # 特性条消失
}
)
这里的puts,意思是打印,就是在控制台中显示出x是什么。
那么我们就进游戏看一下吧——
![1721304566378.png 1721304566378.png](https://bbs.pokefans.cn/data/attachments/2/2418-04eff14e28fca2ed9f36be5dbd12be37.jpg)
![1721304573342.png 1721304573342.png](https://bbs.pokefans.cn/data/attachments/2/2419-acb07536efe9aa028436c8a9b4de0a86.jpg)
![1721304580575.png 1721304580575.png](https://bbs.pokefans.cn/data/attachments/2/2420-559360340385ee64805410441f191d07.jpg)
![1721304588511.png 1721304588511.png](https://bbs.pokefans.cn/data/attachments/2/2421-61d525c45cbd33bcde875ef38291d707.jpg)
![1721304596983.png 1721304596983.png](https://bbs.pokefans.cn/data/attachments/2/2422-757eeae7a5bc3100a27c371c4b24e663.jpg)
我们可以看到,控制台里打印出了1和2。
所以,当每一次x被=时,x就变了。
这边也顺便说一下,我额外安装了Deluxe Battle Kit(DBK)和Enhanced Battle UI(EBUI)这两个插件,不要在意。
并且,我用的DBK和EBUI就是如图所示的版本,在这套教程中,即使插件出了新的版本,如果我没有特别说明过的话,就代表我没有更新插件到新版本。
最后,我们再强调一下——
=,等于,或者说赋值;
==,比较。
在你自己实际写代码的时候不要手快了,检查代码的时候也不要看快了!
那么怎么记呢?
不需要记,多写就会了,你真要记的话,也就只需要记一下两个=是比较就行了,因为一个=跟你在学校里学到的已有的认知没有什么区别。
这边还是需要额外提一下,不管你是说等于还是说赋值,实际上在针对数组的时候,也并不是真的等于或者赋值,如果我们这样写——
aa = [1, 2, 3] # aa现在是一个数组
bb = aa # bb现在也是一个数组,并且和aa一模一样
aa[0] = 4 # 让aa的第一个元素变成4
那么请问,这个时候如果我们打印bb,会输出什么,是[1, 2, 3],还是[4, 2, 3]?
我们就把这一段代码复制到我们的伪代码里——
Ruby:
Battle::AbilityEffects::OnSwitchIn.add(:GRASSYSURGE,
proc { |ability, battler, battle, switch_in|
x = 1
puts x
next if battle.field.terrain == :Grassy
battle.pbShowAbilitySplash(battler) # 特性条出现
# 开出青草场地
x = 2
puts x
battle.pbHideAbilitySplash(battler) # 特性条消失
#------------------------------
aa = [1, 2, 3] # aa现在是一个数组
bb = aa # bb现在也是一个数组,并且和aa一模一样
aa[0] = 4 # 让aa的第一个元素变成4
puts bb
#------------------------------
}
)
![1721304632448.png 1721304632448.png](https://bbs.pokefans.cn/data/attachments/2/2423-13a4aa4b1ee9861851e0093ac5dcb753.jpg)
![1721304639613.png 1721304639613.png](https://bbs.pokefans.cn/data/attachments/2/2424-f7a541e1b9cee505bce2a372d1c619ac.jpg)
我们可以看到,输入的结果应该是[4, 2, 3]。
你说这样你看不出来?
那我们可以再稍微修改一下代码——
Ruby:
Battle::AbilityEffects::OnSwitchIn.add(:GRASSYSURGE,
proc { |ability, battler, battle, switch_in|
x = 1
puts "当x = 1时的输出:" + x.to_s
next if battle.field.terrain == :Grassy
battle.pbShowAbilitySplash(battler) # 特性条出现
# 开出青草场地
x = 2
puts "当x = 2时的输出:" + x.to_s
battle.pbHideAbilitySplash(battler) # 特性条消失
puts "----------分隔符----------"
#------------------------------
aa = [1, 2, 3] # aa现在是一个数组
bb = aa # bb现在也是一个数组,并且和aa一模一样
aa[0] = 4 # 让aa的第一个元素变成4
puts "bb数组的内容是: #{bb.inspect}"
#------------------------------
}
)
![1721304672359.png 1721304672359.png](https://bbs.pokefans.cn/data/attachments/2/2425-08f9680189b183b59f455c58ce70c90e.jpg)
现在我们可以非常清楚的看到了,我们也得到了之前的问题的答案,如果我们打印bb,会输出[4, 2, 3]。
所以,在针对数组的时候,并不会使某个变量等于或者被赋值那一个数组,实际上这个变量只是引用了原始的数组,当原始数组被改变的时候,这个变量也会跟着变,即使没有对这个变量本身做=处理。
现在,回到我们之前的这个问题“既然前面可以直接检查battle.field.terrain == :Grassy,那么这里是否可以直接写battle.field.terrain = :Grassy呢?”
我的严谨的答案是,我不知道,你其实需要自己去实践尝试才能知道是否可以直接赋值来达到目标。
但是,说是这么说,其实我是不建议你直接赋值的,因为当场地改变的时候,会发生很多事情,比如说出现一行字提示,出现场地的动画,新开启的场地要持续几回合,触发其他精灵的特性,触发物品的效果,等等。
所以你最好还是额外写个方法来做。
事实上,ESS原本的代码也的确是写了一个方法——
![1721304686760.png 1721304686760.png](https://bbs.pokefans.cn/data/attachments/2/2426-2a0a69a44ac44a1c13102b32553f8547.jpg)
![1721304693121.png 1721304693121.png](https://bbs.pokefans.cn/data/attachments/2/2427-6724a7406dc911b64a38f8f3c9a59672.jpg)
![1721304700490.png 1721304700490.png](https://bbs.pokefans.cn/data/attachments/2/2428-6810bb1209e68fd9f2449eea1ce373c3.jpg)
这个就是ESS原本的用来开启新的场地的方法。
这个方法其实是有缺陷的,因为它不能自由控制开启的新场地的回合数,现在就算了,以后有机会的话我们再来优化这个方法。
那么这期教程就到此为止,下期教程我们将会讲解PBEffects。
感谢阅读。
最后编辑: