Project1

标题: 脚本学习~提问教程贴~~(更新:2月11日) [打印本页]

作者: 「旅」    时间: 2011-2-8 01:40
标题: 脚本学习~提问教程贴~~(更新:2月11日)
本帖最后由 「旅」 于 2011-2-11 10:25 编辑

【提问区域】
喵最近比较有空~~所以开了这个帖子~~大家可以到这里提基础脚本的问题,或者实用脚本的写法~~~
p.s小旅对理论的东西知道得比较少,不过如果你是来制作游戏的话,理论不重要,关键是怎么运用哦~~
p.s.2千万不要在这个帖子里索要什么脚本哦,这里只负责给大家学习的~~
  1. 范例如下,都是我以前搞不懂的问题,各位需要的话可以提出来~~
  2. Q1:脚本里的def [](id)~end是怎么回事呢?怎么运用?
  3. Q2:怎么可以描绘图型啦、血条啦之类的呢?
  4. Q3:如果我要看默认脚本的话,应该从哪里看起合适?
  5. Q4:能不能介绍一下默认脚本中各类脚本的用途和特征呢?
  6. Q5:什么return然后返回并中断的,可以说明一下到底是怎么回事吗?
  7. Q6:self或super之类的到底是怎么用的?
复制代码
[line]2[/line]
【教程区域】
喵另外顺便写一些教程好了~~~嗯最近对脚本的写法有研究,试试看写出大家都能很容易理解的教程~~~
p.s教程将先讲解整体脚本的格式,随后渐渐会有一些实用脚本、必须了解的脚本等内容献上~~希望认真学习的同学要多点来捧场哦~~~
作者: 春日结乃    时间: 2011-2-8 01:42
本帖最后由 「旅」 于 2011-2-11 10:24 编辑

【提问解答】

提问1
如何设置菜单为半透明并背景显示地图?
提问者
凯蒂洛斯
链接
7楼的正文

提问2
怎么储存变量?以及数据类的重要用途~~
提问者
okasssss
链接
14楼的正文


【脚本教程】

教程1
基础:变量、实例、类之间的关系
链接
7楼的附加内容

教程2
类的属性,及写入与读取的方法~~
链接
20楼正文~~

教程3
教程2的补充~~神奇的仿真变量~~
链接
21楼正文~~~


作者: DeathKing    时间: 2011-2-8 02:16
欢迎整理,然后投稿给RDeveloper。
作者: 凯蒂洛斯    时间: 2011-2-8 20:41
如何将菜单底板设置为半透明并且背景显示为原地图?
谢谢~
作者: IamI    时间: 2011-2-8 20:52
本帖最后由 IamI 于 2011-2-8 20:54 编辑
凯蒂洛斯 发表于 2011-2-8 20:41
如何将菜单底板设置为半透明并且背景显示为原地图?
谢谢~


对于任意Scene
在Main方法内
在Graphics.freeze前加入
  1. @XXXXXXXX.opacity = 某数值
  2. @XXXXXXXX.opacity = 某数值
  3. ......
  4. (所有Sprite、Window都要进行)
  5. @_sp_ = Spriteset_Map.new
复制代码
在main方法最后
  1. @_sp_.dispose
复制代码
以上是大略过程。具体还要靠自己摸索……
作者: 凯蒂洛斯    时间: 2011-2-8 22:18
回复 IamI 的帖子

还是不怎么懂......
作者: 「旅」    时间: 2011-2-9 01:01
本帖最后由 「旅」 于 2011-2-11 09:17 编辑

回复 凯蒂洛斯 的帖子

首先我们要修改窗口Window的"属性"-不透明度opacity~~打开脚本里的Scene_Menu,我们可以找到@command_window、@playtime_window、@steps_window、@gold_window、@status_window这些变量~~他们是储存窗口类实例的变量,
我们可以直接写上@command_window.opacity = 120,这样就可以更改"属性"opacity了。
(p.s不透明度是0~255,所以半透明差不多就是120)
(p.s.2要注意必须在窗口生成后才可更改"属性",也就是@playtime_window = Window_PlayTime.new,不然会有错误。但也必须在Graphics.transition前写好,因为那之前是专门负责初始化的地方,这是标准格式哦~~)

然后我们可以添加地图了,这个也很容易,因为RM默认脚本已经把地图的东西全都写好了,
我们只需要生成下面这个类即可~~~这段放在先前说的初始化的地方~~
@spriteset = Spriteset_Map.new
之后我们不要忘记把这个实例释放掉,也就是让他从内存里消失~~~
@spriteset.dispose
(p.s这个则就不是放在初始化的地方了哟~~因为它是释放,也就是结束时的步骤,要把它放在Graphics.freeze之后)
(p.s.2注意Graphics.transition、和Graphics.freeze是两种不同的东西哦~~~你可以打开"F1帮助文件-RGSS 参考-游戏库-RGSS 内部模块-Graphics"这里参看,至于为什么需要呢,你可以试着删掉脚本每一个Scene_Xxxxx和Main里的这两样东西,之后就会发现没有这些会很奇怪的了~~)

[line]2[/line]
附加内容:
话说上面有提到变量、实例、类3样东西~~~这里解释他们之间暧昧不清的关系喵~~~

其实很简单,类其实就是一段代码~而我们说生成类,就像将设计图(类)里的车制作为实物~制作出的车就是实例~~
因为类其实就只是一个定义的作用~~然后我们需要把它生成,生成的就是实例~~~
而变量嘛是一个指定的作用,因为实例被存在了内存之中,所以通过变量的指定我们就可以很轻易地找到实例了~~~

[line]2[/line]
喵然后就OK了~~有什么问题可以继续提问哦~~~


作者: 凯蒂洛斯    时间: 2011-2-9 17:57
又来麻烦你了……有没有办法使用脚本直接呼出队伍中X号人物的状态栏和装备栏?
作者: 「旅」    时间: 2011-2-9 18:11
回复 凯蒂洛斯 的帖子

这个不难哟~~~脚本里已经定义好了Scene_Status和Scene_Equip这两个类。

只需要$scene = Scene_Status.new(角色ID)或$scene = Scene_Equip.new(角色ID)就行了~~

p.s而为什么是$scene呢~~~你可以打开脚本Main看看~~里面有一个:
  1.   # $scene 为有效的情况下调用 main 过程
  2.   while $scene != nil
  3.     $scene.main
  4.   end
复制代码
这个东西的意思就是只要$scene不为nil(为nil时就是退出游戏了),就会使用Scene_Xxxx类的main方法~~所以以后Scene(场景类)直接生成在$scene里就行,它会自动调用main方法的~~
作者: okasssss    时间: 2011-2-9 18:38
我想问一下,如果我写了一个脚本里面有一个记录人物认识时间的变量@time_m那么游戏结束是这个变量是不是会自动保存到存档数据里面呢?还是下次再运行游戏时这个变量又是空的了?
作者: Wind2010    时间: 2011-2-9 18:48
回复 okasssss 的帖子

清空,因为在Scene_Save和Scene_Load都没有存储/读取该变量的脚本
作者: okasssss    时间: 2011-2-9 18:58
回复 Wind2010 的帖子

谢谢,我还要认真学习.........
作者: 逸豫    时间: 2011-2-9 20:33
回复 okasssss 的帖子

想要不清空有两个方法
1、将其变成Game_System等类的实例变量
2、将其的读取与保存写入Scene_Load与Scene_Save
作者: 「旅」    时间: 2011-2-10 08:58
本帖最后由 「旅」 于 2011-2-10 09:08 编辑

回复 okasssss 的帖子

恩这个提问很赞哦~~~问得很好,是学习脚本必须知道的一个重要内容哟~~~
喵那个,在RGSS里其实是有两种方式可以存储、读取数据的~~~我们先来认识较简单的一种吧~~~
  1. @time_m = load_data(filename)
  2. save_data(@time_m, filename)
复制代码
如上~第一行是"读取"了filename的数据后赋值到@time_m变量里,而第二行则是将@time_m的数据"写入"到filename里面~

filename是一个字符串哦~~~它的内容是某个文件的路径~~~例如:
  1. @time_m = load_data("Data/Actors.rxdata")
  2. p @time_m
复制代码
这时你测试时弹出的内容其实就是"Data/Actors.rxdata"这个文件的数据了(角色的数据库)~~~
  1. save_data("你好吗?", "RMXP.rxdata")
复制代码
还有储存操作~~~如果在路径上没有那个文件的话,他就会自己生成一个哦~现在你可以看看游戏目录下多出什么了~~


好的,接下来讲第二种储存和读取的方法~~~你可以打开Scene_Save和Scene_Load的73~82行看看~~~
  1.     # 储存
  2.     Marshal.dump($game_system, file)
  3.     Marshal.dump($game_switches, file)
  4.     Marshal.dump($game_variables, file)
  5.     Marshal.dump($game_self_switches, file)
  6.     Marshal.dump($game_screen, file)
  7.     Marshal.dump($game_actors, file)
  8.     Marshal.dump($game_party, file)
  9.     Marshal.dump($game_troop, file)
  10.     Marshal.dump($game_map, file)
  11.     Marshal.dump($game_player, file)
复制代码

  1.     # 读取
  2.     $game_system = Marshal.load(file)
  3.     $game_switches = Marshal.load(file)
  4.     $game_variables = Marshal.load(file)
  5.     $game_self_switches = Marshal.load(file)
  6.     $game_screen = Marshal.load(file)
  7.     $game_actors = Marshal.load(file)
  8.     $game_party = Marshal.load(file)
  9.     $game_troop = Marshal.load(file)
  10.     $game_map = Marshal.load(file)
  11.     $game_player = Marshal.load(file)
复制代码
如上~~~知道为什么这个东西和之前讲的那种有区别吗?应该很容易就可以判断出来哟~~~
恩没错,这个东西的特点在于它是多个数据的~~~它可以一次性把很多的数据放在同一个文件哦~~~

但是为什么把它放在新建页面测试时出现错误了呢?嘿嘿大家可以搜索一下write_save_data和read_save_data哟~~~
搜索的第二个结果就是我们上面的那些内容~~~而第一个内容,如下:
  1.     file = File.open(filename, "rb")
  2.     read_save_data(file)
  3.     file.close
复制代码
  1.     file = File.open(filename, "wb")
  2.     write_save_data(file)
  3.     file.close
复制代码
这个就是原因了~~~固定格式之一哦~~~必须在首尾写上那两个东西~~~
另外读取的话,File.open的第2个参数是"rb"。写入则是"wb"~~是和write和read对应的~~~

可能同学们就会奇怪了,为什么需要这么麻烦呢……喵我来告诉大家~~
因为这个是多个数据写入或读取于一个文件,为了确保不会出现意外就要这样哦~(如果重新使用等,就会很乱了)

另外要注意的是,我们存入什么数据的顺序,和读取的顺序一定要一定哦~~~写入第一个是$game_system的话,那么读取第一个也要是$game_system~~不然数据就会全都乱套了~~~

最后呢,继续解答okasssss酱的疑问~~~喵那个@time_m的话,最好就是放在一个数据类里哦~~~不然如果每个变量都需要保存、读取的话,那样代码会很长,而且效率会很低的~~~
那么什么是数据类呢?其实就是脚本最前端的Game_Temp、Game_System、Game_Xxxx这些类……
他们的好处在于,保存或读取时可以一次性把类里的实变量都一同保存、读取~~~很方便的~~~~
p.s他们实例的变量是$game_temp、$game_system、$game_xxx。

喵示范一下~~~首先把@time_m放入Game_System(我个人建议这个数据类)的initialize里初始化。

  1. @time_m = 0
复制代码
p.s如果不初始化的话,很容易发生错误的~~~

然后模仿上面的attr_accessor :xxxx...写一个吧~~~(如果不知道这个的话,可以看我上篇解答的附加内容2)

  1. attr_accessor :time_m
复制代码
恩就这样,然后就没有了~~~(啥居然没有了!?)恩对的哦~~~

接下来我们进入游戏测试吧~~~
p.s因为要新建游戏或读取游戏后Game_System才有在$game_system生成,所以我们到游戏地图上的事件里测试~~~
  1. p $game_system.time_m
  2. $game_system.time_m += 100
  3. p $game_system.time_m
复制代码
喵最后测试成功~~~

好了终于废话完了~~语言表达不是很好的说,各位看的时候辛苦了><
作者: Wind2010    时间: 2011-2-10 09:05
回复 「旅」 的帖子

学习了,原来还可以这样储存...我都是直接在Scene_Load和Scene_Save加入存储内容的0 0
作者: clannad    时间: 2011-2-10 12:40
大家好像都是问一些很难得问题啊- -
我问一个很菜的问题,如何判断角色的攻击命中了敌人呢?
if self.is_a?(Game_Actor) and self.damage>0
我只会写上面那个自己被命中的
作者: 「旅」    时间: 2011-2-10 18:04
本帖最后由 「旅」 于 2011-2-10 18:05 编辑

回复 clannad 的帖子

这个问题嘛,根据情况不同有很多种选择的说~~~
  1.     $game_party.actors[队伍角色顺序].damage_pop
  2.     $game_troop.enemies[队伍敌人顺序].damage_pop
  3.     $game_actors[角色id].damage_pop
复制代码
以上是我找到的几种最简单的~~~
p.s第3个其实和第1个一样,不过他们的编号不同,一个是队伍里的编号,一个是数据库里的编号~~具体为什么是这样嘛,等我明天有空再讲哦~~~
作者: clannad    时间: 2011-2-10 18:24
回复 「旅」 的帖子

。。。。。.damage.pop是什么意思啊?
作者: Wind2010    时间: 2011-2-10 18:32
回复 clannad 的帖子

显示伤害的开关,设置了damage后再把damage.pop打开就可以显示伤害

PS:如果没有命中damage是"Miss" 注意是字符串
作者: 「旅」    时间: 2011-2-11 09:18
本帖最后由 「旅」 于 2011-2-11 09:28 编辑

也许大家接触过@command_window.opacity = 120这个东西~~给新人讲解一下好了~~~
喵告诉大家哦~~其实.opacity这个东西并非真正的变量哟~~注意他有一个点~~而这个格式就是操作方法的~~
所以其实它是一个方法来着~~
(p.s其实这个内容在脚本入门里有,不过他讲得很模糊呢~~)

[line]2[/line]
  1. class Person
  2.   def name
  3.     return @name
  4.   end
  5.   def name=(name)
  6.     @name = name
  7.   end
  8. end
复制代码
这个代码就是脚本入门里的~~~首先是return的用法~~~return可以将一个数值运送到调用它的地方~~
例如——
a = Person.new
p a.name
这时就会出现一个nil的提醒~~~因为@name根本没有初始化~~所以是nil(空)哦~~~
(那么我们试试初始化吧~~~有些同学也许注意到了,在默认脚本里类的开头常可以看到initialize(中文就是初始化)~~那个东西其实在a = Person.new时就会调用到哦~~也就是说只要.new就会调用initialize。p.s这个情况是唯一的哟~~)

各位加上这句~~~
  1.   def initialize
  2.     @name = "阿尔南瓜"
  3.   end
复制代码
然后再使用p a.name~~我们发现真的把@name给运送来了~~撒花~~
(p.s大家要注意运送的功劳都是return的哦~~def name这个name可以改成别的,因为他只是一个方法名~~但如果我们改为"return @other"的话,就不会显示"阿尔南瓜"了~~~)
所以return的好处在于,一般情况下,我们是不能读取类里的实变量的~可是有了这个后我们可以突破界限了~

然后还有def name=(name)这个~~也就是我们最开始用到的~~他附带了一个参数~~
这样的话,我们就可以从外界写入一个数值,然后改变类里面的实变量了~~~这两样可以简单理解为"读取"和"写入"~~~
(p.s大家要记住这两样东西~~真正写起脚本的话,这个是无处不在的哟~~~)

最后介绍一下attr_reader、attr_writer、attr_accessor~~~
其实更简单哟~~~他就是等于简化了代码~~~例如我们写入attr_accessor :name
就等于自动完成了下面这两句~~~

  1.   def name
  2.     return @name
  3.   end
  4.   def name=(name)
  5.     @name = name
  6.   end
复制代码
而attr_reader(读取)就是只有前一句~~attr_writer(写入)是只有后一句~~~
喵现在大家应该大致可以了解默认脚本里Game_Xxxxx那些东西了吧~~~
作者: 「旅」    时间: 2011-2-11 09:22
话说上楼讲了@command_window.opacity = 120的奥秘~~但是其实呢不单是写入和读取,只要你定义了如下格式的:

  1.    def name
  2.     return @name
  3.   end
  4.   def name=(name)
  5.     @name = name
  6.   end
复制代码
那么就会附送一个功能哦~~~就是@command_window.opacity += 120或@command_window.opacity -= 120啦~~~
是不是很奇怪呢,其实这个东西是RGSS自动给的~~~具体怎么操作的我们没必要知道,反正只用知道如上代码那样定义的话,我们就可以仿真的制作出一个变量了。

p.s不过如果你不把实变量(例如上面的@name)初始化,那么是不能用+=或-=的~~因为那时@name是nil,而nil是没有这些操作的~~~必须把它初始化为整型,也就是整数哦(例如0或999之类)~~
作者: fux2    时间: 2011-2-11 09:33
本帖最后由 fux2 于 2011-2-11 09:52 编辑

回复 「旅」 的帖子

内啥,这里错了,于是编辑掉了。
作者: 「旅」    时间: 2011-2-11 09:50
回复 fux2 的帖子

唔喵不过好像不是的说~~如果是整型的话,返回值是整型的clone值~~所以返回后操作不会影响原本的数值的说~~还有那两个方法是缺一不可的说,喵很奇怪的说><
作者: fux2    时间: 2011-2-11 09:52
本帖最后由 fux2 于 2011-2-11 10:02 编辑

回复 「旅」 的帖子

果断删除错误言论,事实是
    ! 叹号结尾说明此方法很危险,有副作用 传入参数会被修改
    ? 问号结尾说明这是一个查询方法, 通常是返回布尔值的方法
    = 等号结尾说明此方法用于赋值

这才是RGSS的巨大黑手……



作者: 认真的学    时间: 2011-2-11 10:47
本帖最后由 认真的学 于 2011-2-11 10:47 编辑

嗯......讲解一下clone吧......具体的问题是:
1、原值和原值clone之后有什么区别?
2、clone和dup的区别......
另外什么是【整型(数?)的clone值】,整数不是没有clone方法么?
作者: 六祈    时间: 2011-2-11 12:35
回复 认真的学 的帖子

clone是一种浅复制,只有被复制的对象本身会产生一个全新的拷贝,可以任意操作clone对象而对本对象无影响,但是注意:对象内部关联的对象仅仅是复制了引用
举例如下:
a=[1,2]
b=[a]
c=b.clone
b[0][1]=3   #这时a=[1,3]
p c            #[[1,3]]

clone可以复制单例类而dup不可以




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