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

Project1

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

[原创发布] 【教程】【不定期更新】实用型XP脚本编写小技巧#13

[复制链接]

Lv4.逐梦者 (版主)

梦石
0
星屑
9532
在线时间
5073 小时
注册时间
2013-6-21
帖子
3580

开拓者贵宾剧作品鉴家

跳转到指定楼层
发表于 2015-1-17 12:55:15 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式

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

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

x
本帖最后由 RyanBern 于 2017-1-5 20:45 编辑

这个帖子记录了我在编写RMXP脚本时候学会的若干技巧,在编写脚本的时候我会把一些有价值的想法记录在这个帖子中,此帖会不定期更新。
此帖涉及到的技巧多实用性,没有特别高深的技术,应该很容易就能学会。不过,具体问题具体分析,这个教程里面的脚本一般不能直接拿过来实用,也只是提供了一个处理该类问题的思路,所以请不要问“这脚本怎么不能实现XX效果”这样的问题。
另外请大家多多提出批评意见。


技巧1:数据库内容扩展
【更新】2015.01.17
【摘要】默认的数据库提供的功能大概不能满足一些人的需要,如果你想要给一个特技定义“冷却时间”的属性,但是数据库并没有相应的设置区域,这时候该如何处理?是打开脚本编辑器直接设置固定值,还是使用外部文件存储这一设定?原则上说,这个本来是数据库的设定,只是数据库的功能不够而已,因此我们希望还可以在数据库中设置自己的自定义属性,而不是把数据编辑转移到脚本编辑器中。以下这个方法经过测试,稳定性较好,并且能满足多数需求。
【正文】



技巧2:额外信息的存储
【更新】2015.01.17
【摘要】在编写一些XP的脚本系统中,不可避免要涉及到数据的存储问题,特别是用户存档数据的存储。这类问题如果处理不好,那么写出来的脚本的兼容性会很差,而且修改也十分麻烦。这个方法利用默认脚本的一些结构,可以被用作比较简单的额外信息存储,并且实现起来也不是非常麻烦。
【正文】



技巧3:让Sprite和Window动起来
【更新】2015.01.17
【摘要】在各种场景中,我们希望我们界面中的元素运动起来,而不是静止地呆在原地。例如在菜单场景中,我们希望命令窗口从屏幕外飞入到场景中,要一个动态的效果。我们自然会想到可以通过更改坐标让它动起来。再比如我们需要一个图片淡出画面,而不是一下子从画面上消失,我们就会想通过更改不透明度来实现这个效果。原理是很简单的,但是怎么样处理才比较妥当呢?下面这个技巧通过定义了一些额外的接口,能够让Sprite和Window随心所欲地移动。
【正文】



技巧4:装备附带技能——简洁到了极致
【更新】2015.01.23
【摘要】装备附带技能是一个很久远的问题,要解决它也不是很困难。但是,实现装备附带技能的方法却非常重要。这个技巧实际上没有什么新鲜的东西,在上文中也不断提及。其核心就是“永远不要更改原始数据”。注意到了这一点,我们就能用很短的篇幅来完成装备附带技能的脚本。
【正文】



技巧5:事件和脚本结合——给地图事件做个计时器
【更新】2015.01.24
【摘要】相信一定有人想利用RMXP做一个类似于农场的游戏,希望达到的最基本效果是让地图上的某些事件随着游戏时间的变化而变化。例如,玩家在某一时刻种下一颗种子,然后游戏时间经过15分钟后,终于长出了果实,这就是一个简易的农场事件。由于这个效果涉及到了地图上的事件,因此在实现的过程中,必须要考虑地图事件的刷新机制。如果完全通过事件实现,制作起来比较麻烦,而且会带来一些效率上的问题。下面这个技巧,将事件和脚本配合使用,利用脚本制作核心的计时器功能,利用事件完成地图上的刷新,比较有参考价值。
【正文】



技巧6:二周目制作
【更新】2015.02.18
【摘要】二周目的设计在RPG游戏中是个很不错的设定,它增加了游戏的可玩性,适度延长游戏的时间。但是,RMXP默认的系统中不具有二周目/多周目的设定,因此我们要想办法在玩家一周目通关之后,选择“新游戏”进入游戏,就会进入二周目的剧情。一般来说,二周目的信息不会保存在存档中,因此需要借助其他文件来存储这个信息。这个技巧利用游戏原有数据库文件,巧妙地将二周目信息隐藏在其中。为我们制作游戏提供了新的思路。
【正文】



技巧7:多项选择
【更新】2015.03.19
【摘要】大家都知道,RMXP的事件指令的第二条就是“显示选择项”,当主角和NPC对话之后,NPC会让主角做个选择。但是这个事件指令的不好的地方就是它只能设置四个选择项,当选择多于这个数目时,就要想各种办法了。例如,通过反复使用“显示选择项”事件指令,牺牲2个选项槽,把这个选项改为“上一页”和“下一页”,然后再考虑多个选项之间的衔接问题。这样做不是很方便,也使得选项过于臃肿。如果单纯利用脚本,那么如何设置选择之后的分歧,也是一个问题。这个技巧运用了脚本事件相结合的办法,能够制作出使用起来比较方便的多项选择系统。
【正文】



技巧8:椭圆形状的blt
【更新】2015.06.28
【摘要】众所周知,Bitmap类的#blt方法有类似于截图传送的功能,它可以把一张bitmap的部分复制到另一个bitmap当中。这个方法很方便,但是它也有很多的拓展空间。比如说,blt方法只能截取矩形区域,而不能截取其他形状的区域。如果我们对区域有所要求的话,原始的blt就不能满足了。这个技巧为Bitmap类新定义了一个#ellipse_blt方法,它可以将传送源位图的一个椭圆区域截取到目标bitmap上。
【正文】



技巧9:地图事件数据的扩展
【更新】2015.06.29
【摘要】技巧9实际是对技巧1的进一步补充,在技巧1中,我们对数据库的功能进行了扩展。但是地图上的事件某种意义上讲也是游戏数据的一部分,那么如何在地图事件上附加额外信息呢?下面就要介绍两种附加信息的方法:利用事件的名字和事件当中的注释。
【正文】



技巧10:记录事件位置
【更新】2015.07.01
【摘要】RGSS1中,切换地图之后,重新进入该地图会导致事件的位置重置。究其原因,是因为游戏并没有储存各个地图的信息,而是在每次进入地图的时候,重新载入原始的地图数据,这导致事件归位。所以,我们必须要在主角移动之前将地图上的事件位置储存起来,这需要利用我们技巧2。当然,并不是所有事件都需要记录位置,我们利用技巧9来对特殊的事件进行设置,让RGSS系统知道哪些事件需要记住位置,哪些事件不需要。
【正文】

技巧11:另类的alias实现
【更新】2015.09.15
【摘要】在自己编写脚本中使用alias关键字,能够节省插件脚本的篇幅,还有减少脚本冲突的可能性的效果。在这个技巧里面,我则要介绍另一种alias的实现方式,利用这个方法,起到的效果和alias差不多,但是完全不用使用alias关键字,而且也不必想方设法给新方法起不同的名字了(从而达到防止Stack Level Too Deep的错误)。 注:本技巧参考了这里的帖子。
【正文】

技巧12:简单的数据库破限
【更新】2016.07.14
【摘要】众所周知 RMXP 对数据库元素的数量基本上都有 999 的上限,那么总有这个数量不够的情况。遇到这种情况我们该怎么办呢?你可能想到 DKRM,但是 DKRM 的资源不是那么好找,你也可能想到用脚本将多余的数据补上去,但是总觉得写起来很麻烦。这里介绍了一种在不改动编辑器的条件下轻松突破这个限制的一种办法,可能以前有人已经做过,不过我还是在这里更新一下吧。
【正文】


技巧13:简易召唤系统——我们当中出现了一个叛徒
【更新】2017.01.05
【摘要】这个技巧巧妙利用了敌人出现/隐身的设定,制作了一个简易的召唤系统。并且需要极少量的脚本代码,非常适合事件党学习(以及出成考场题目)。
【正文】

点评

接收更新通知。  发表于 2015-9-15 08:03
接收更新提示  发表于 2015-7-18 11:57
显示选项的一个不自然的思路可以见我的事件转译器-_-#  发表于 2015-3-19 12:50
更新时求自顶啊= = 点评接收更新通知  发表于 2015-2-8 21:10

评分

参与人数 8星屑 +525 +2 收起 理由
七夜弦 + 1 精品文章
SixRC + 1 看完了 r7漏洞+1
gonglinyuan + 20 精品文章
余烬之中 + 200
7408 + 15 精品文章
你最珍贵 + 60
kuerlulu + 30 精品文章
taroxd + 200 永远不要更改原始数据+1

查看全部评分

Lv2.观梦者

梦石
0
星屑
665
在线时间
50 小时
注册时间
2018-6-27
帖子
49
20
发表于 2018-7-16 09:16:29 | 只看该作者
  1. class Window_Choice < Window_Selectable
  2.   def initialize
  3.     x = 2
  4.     super(0, 0, x, 248)
复制代码

那个,新人问一下,多个选项脚本里这么写为啥出错啊
回复 支持 反对

使用道具 举报

Lv4.逐梦者 (版主)

梦石
0
星屑
9532
在线时间
5073 小时
注册时间
2013-6-21
帖子
3580

开拓者贵宾剧作品鉴家

19
 楼主| 发表于 2017-8-25 23:47:58 | 只看该作者
本帖最后由 RyanBern 于 2017-8-25 23:49 编辑
lcr 发表于 2017-8-25 15:06
关于技巧12:数据突破
是复制在什么地方  是复制在自己新建的地方吗? 不知道怎么用 我是小白 求大神详细 ...


第一步:复制第一段脚本到脚本编辑器的任何地方。
第二步:新建一个事件,在事件指令中选择【脚本】,然后里面命令写入
RUBY 代码复制
  1. set_item_max("CommonEvent", 1200)

即可修改公共事件的最大值为 1200。如果是别的数字请改动第二个参数。
第三步:启动游戏,并执行这个事件(执行的时候没有任何外在的效果,只要确认触发这个事件就行)
第四步:关闭游戏,关闭工程,重新载入工程即可看到效果。
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
51 小时
注册时间
2016-5-31
帖子
59
18
发表于 2017-8-25 15:06:42 | 只看该作者

关于技巧12:数据突破
是复制在什么地方  是复制在自己新建的地方吗? 不知道怎么用 我是小白 求大神详细
回复 支持 0 反对 1

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
106
在线时间
470 小时
注册时间
2015-4-26
帖子
92
17
发表于 2016-8-1 11:46:52 | 只看该作者
关于技巧8:椭圆形状的blt
我还在学习脚本,对此有一些困难
能否发一个范例供学习
谢谢
回复 支持 反对

使用道具 举报

Lv4.逐梦者 (版主)

梦石
0
星屑
9532
在线时间
5073 小时
注册时间
2013-6-21
帖子
3580

开拓者贵宾剧作品鉴家

16
 楼主| 发表于 2016-7-16 13:22:17 | 只看该作者
jiushiainilip19 发表于 2016-7-15 14:07
技巧3 能够做到一个图片原地旋转的效果吗?

当然可以,需要你定义一个rotate_effect,这个旋转效果是指定一个速度然后永远旋转下去,如果想要改成旋转一个固定角度则和前面的move_effect类似。
RUBY 代码复制
  1. def rotate_effect(speed)
  2.   @rotate_speed = speed
  3.   if @rotate_speed == 0
  4.     @rotate_effect = false
  5.     return
  6.   end
  7.   @rotate_effect = true
  8. end
  9. def rotating?
  10.   return @rotate_effect
  11. end

然后你需要自己定义update
RUBY 代码复制
  1. def update
  2.   if self.rotating?
  3.     self.angle += @rotate_speed
  4.   end
  5. end

代码未测试,可能有BUG,遇到笔误等问题请自行修改。

点评

3Q 3Q!  发表于 2016-7-17 07:28
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
596
在线时间
797 小时
注册时间
2014-7-1
帖子
578

开拓者

15
发表于 2016-7-15 14:07:09 | 只看该作者
技巧3 能够做到一个图片原地旋转的效果吗?{:2_249:}
学习使我疲劳,打工使我疲惫,恋爱使我伤身,吸烟伤我肺腑,饮酒损我形象,旅游使我破费,月底不见铜板,只有在论坛里面看看各种大佬才能使我进去
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
80
在线时间
216 小时
注册时间
2011-9-17
帖子
151
14
发表于 2016-5-26 23:48:58 | 只看该作者
求不算挖坟。
技巧5的事件和脚本结合——给地图事件做个计时器解释效果是我想实现的
于是我重新开一个工程,把脚本放到Main之上
再这样做事件,发现没有效果啊

1.png (78.13 KB, 下载次数: 8)

1.png

2.png (82.42 KB, 下载次数: 11)

2.png

3.png (78.6 KB, 下载次数: 7)

3.png
回复 支持 反对

使用道具 举报

Lv3.寻梦者 (版主)

…あたしは天使なんかじゃないわ

梦石
0
星屑
2208
在线时间
4033 小时
注册时间
2010-10-4
帖子
10779

开拓者贵宾

13
发表于 2015-9-15 16:09:10 | 只看该作者
本帖最后由 taroxd 于 2015-9-15 16:29 编辑

在较新版本的 Ruby 中:

RUBY 代码复制
  1. C = Class.new
  2.  
  3. class C < C.clone # 这里是打开 C 而不是覆盖常量 C,而 C.clone 不是原来 C 的父类 Object,因此会报错
  4. end
  5.  
  6. # superclass mismatch for class C (TypeError)


所以,要用这种方式的话,应该是这样的代码
RUBY 代码复制
  1. class C
  2.   def c
  3.     1
  4.   end
  5. end
  6.  
  7. class C < Object.send :remove_const, :C
  8.   def c
  9.     super + 1
  10.   end
  11. end


然而这种方式不仅会让继承链变得很难看,而且很容易导致问题。

RUBY 代码复制
  1. class Game_BattlerBase
  2.   # 默认脚本
  3. end
  4.  
  5. class Game_Battler < Game_BattlerBase
  6.   # 默认脚本
  7. end
  8.  
  9. # 若这一行是
  10. # class Game_BattlerBase < Object.send :remove_const, :Game_BattlerBase
  11. # 也一样会导致问题
  12. class Game_Battler < Object.send :remove_const, :Game_Battler
  13.   # A 的插件脚本
  14. end
  15.  
  16. class Game_Battler < Game_BattlerBase
  17.   # B 的插件脚本
  18. end
  19.  
  20. # superclass mismatch for class Game_Battler (TypeError)


很明显,这个脚本冲突就是 A 的锅

不想发生命名冲突的话,应该是这样的方式比较好

RUBY 代码复制
  1. class C
  2.   def c
  3.     1
  4.   end
  5. end
  6.  
  7. class C
  8.   original_c = instance_method :c
  9.   define_method :c do
  10.     original_c.bind(self).call + 1
  11.   end
  12. end


接着推销一下这个:http://taroxd.github.io/rgss/Tar ... AE%BE%E7%BD%AE.html

当然,还是更高版本 Ruby 中的 prepend 和 refine 最舒服。

RUBY 代码复制
  1. class C
  2.   def c
  3.     1
  4.   end
  5. end
  6.  
  7. module MyPatchToC
  8.   def c
  9.     super + 1
  10.   end
  11. end
  12.  
  13. C.prepend MyPatchToC


RUBY 代码复制
  1. # 在我自己的脚本里,我就直接把 id 猴补到 Fixnum 里面了。
  2. # 为了在某些场合既能传物品(装备、角色等等)id作为参数,也能传入物品的实例作为参数
  3. # 其实我挺希望能这样用 refine 的
  4. module MyPatchToFixnum
  5.   refine Fixnum do
  6.     alias_method :id, :to_int
  7.   end
  8. end
  9.  
  10. class AnotherClass
  11.   using MyPatchToFixnum
  12.  
  13.   def self.show(item_or_item_id)
  14.     puts item_or_item_id.id
  15.   end
  16. end
  17.  
  18. # assume that $data_items exists
  19. AnotherClass.show($data_items[1]) # 1
  20. AnotherClass.show(1)              # 1
  21.  
  22. 1.id # undefined method `id' for 1:Fixnum (NoMethodError)

以及,如果不是做 RM 插件的话,这种技术的实际应用真的很少……
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (暗夜天使)

只有笨蛋才会看到

梦石
1
星屑
21484
在线时间
9389 小时
注册时间
2012-6-19
帖子
7114

开拓者短篇九导演组冠军

12
发表于 2015-9-15 14:02:26 | 只看该作者
技巧11 另类alias 在RMVA的Ruby1.9中能用吗?

点评

不能 superclass mismatch  发表于 2015-9-15 16:08
没有进行测试,仅仅在1.8里面试过。  发表于 2015-9-15 14:11
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
60
在线时间
705 小时
注册时间
2007-12-23
帖子
874
11
发表于 2015-9-15 08:15:13 | 只看该作者
关于技巧10:记录事件位置

我先前没有忘了这个帖子里有这个内容,搜了半天也没有搜到,只好自己写了一个。现在回来看看这个部分,对比了以下各种实现细节,发现这样实现好像还是有点问题的,就是如果一个事件【固定朝向】了之后turn_left、turn_right等方法会失效,导致事件的朝向不能被记录下来。

点评

看看我的新帖吧http://rm.66rpg.com/thread-383466-1-1.html  发表于 2015-9-15 09:12
没想到也会出这这样的一个小BUG。  发表于 2015-9-15 08:30
我以前曾经发过一个比这里的这个简洁一些的脚本,当时那个脚本直接clone了$game_map对象,但是这个脚本我为了省一些资源所以就仅保存了位置  发表于 2015-9-15 08:28
这个问题当时确实没有考虑到,不过刚才稍微想了一下没想到什么比较好的解决办法。  发表于 2015-9-15 08:24
买了正版RMMV的同学进来看一下,谢谢~
https://rpg.blue/thread-393237-1-1.html
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-9-21 14:50

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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