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

Project1

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

[原创发布] 【14.7.5第二版更新】RGSS1脚本入门参考

[复制链接]

Lv4.逐梦者 (版主)

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

开拓者贵宾剧作品鉴家

跳转到指定楼层
1
发表于 2013-10-12 22:24:57 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式

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

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

x
本帖最后由 RyanBern 于 2015-8-24 12:15 编辑

[box=RoyalBlue]
目录
[/box]

第0章节:预备知识1L(主楼)
第1章节:类7L
        √热心朋友的相关补充23L
第2章节:解密RGSS系统11L
第3章节:改动游戏对象14L
第4章节:窗口的使用19L
第5章节:场景的使用(一)20L
第6章节:场景的使用(二)21L
第7章节:尾声22L


写在前面
       一位论坛的朋友和我说,他看过很多RMXP脚本的教程,但是感觉没得到什么帮助,脚本也总写不好。我想这也是很多论坛朋友的共同问题吧,想自己弄个脚本,却无从下手;想看教程,却一头雾水(尤其是游戏里面的F1,感觉要有一定的基础才能理解最主要的部分)。这些天在论坛里面逛了逛,有不少尝试着自制脚本的朋友,但写出的脚本却总也通不过。我也看到了一些朋友写的代码,不得不说,代码中很多错误都是源于对教程的误解和对范例脚本(也就是游戏默认的脚本)的错误移植,游戏默认内置脚本其实是个很好的参考,但是如果不加分析胡乱利用一通,当然是不行的。于是我想到写下这个帖子,帮助那些渴望写出自己脚本的朋友们,成为一个真正的“脚本党”。我其实也算是个写脚本的业余爱好者,同时也在不断挖掘RGSS1更深层次的东西,本贴介绍的,仅仅是RGSS1的冰山一角,但却是我们编写脚本最常用的知识和基础。发出这个东西,不敢说能让大家都成为脚本高手,至少能让大家对RGSS1有个更清楚的认识。以下教程中,大家可能对Ruby和RGSS1有所混淆,Ruby是一门程序设计的语言;而RGSS1是基于Ruby编写的脚本系统,有很多特定的功能。

       这里写的是我对写脚本的一些理解,希望各位高手能积极提出意见,有哪里写得不对的地方,还请大家帮忙批评指正。另外大家如果遇到什么相关的问题,可以随时在帖子中询问,只要我有时间,我会立即为大家解答的。(当然求脚本之类的提问我在这里就不处理了,请移步RMXP 提问区)

配套脚本教学视频:https://rpg.blue/thread-381015-1-2.html

【第二版序】
       半年前这个教程杀青了,半年后再翻出来,感觉不是很满意,有些地方都没有说清楚。而且后面脚本解读那里,根本就是在利用“抄脚本——写分析”的模式,让人很难有欲望看下去。因此第二版会有一些改动。这半年来又接触了不少编程的技术,对一些问题的看法也和从前大大不同了,因此都写在这里,大家好好探讨一番。这次的改动,注重细节的解说,再加上理论与实践结合的部分(虽然还没有做,大家不要来BS我),想必能比第一版更好吧。


[box=RoyalBlue]
第0章节:预备知识
[/box]

       很多人觉得计算机很聪明,实际上,它是十分天真的。我们现在所看到它实现的强大功能,其实就是通过有限次的计算来实现的。我们说计算机很傻,是因为我们告诉它什么,它就做什么,因此,我们必须要好好和它沟通,它才能更好地为我们服务。
0.1  几个重要的概念
0.1.1  数字计算&运算符&表达式
       这个我相信大家都明白,数字计算是计算机最基本的功能,游戏里面的F1已经说得很详细了,在这里我只想说一些大家容易忽略的。
赋值运算符“=”:
       虽然很不起眼,但是,我们要注意的是,一定要把它和数学上的等号'='区分开,在这里赋值运算符的作用是把它右边的值赋给左边,左边通常是一个变量(它的概念我们即将会讲到)。不能给常量或者伪变量再次赋值。例如不能写3=2这样的式子。另外,赋值运算符的优先级是最低的一个,因此一般把所有表达式都计算完毕后再进行赋值。
除法'/',取余数'%':
       这两个运算符的用处十分广泛。大家一定要弄清整数的除法。在绝大多数编程语言中,整数的除法不会发生除不尽的问题,得到的结果,其实是两个数的商值。例如7/2应该得到3,我们可以把它理解成7 = 2 * 3 + 1因此结果是3,而不是3.5。取余数也就是7%3=1。我们要注意,余数的正负除数的相同(或者0),绝对值比除数小,因此,(-7)/3=-3,(-7)%3=2。这要提醒大家注意的是,不要随便交换乘除法的顺序,否则会造成一些不可预料的错误。
       例如,1/3*3和1*3/3最后算出的结果是不一样的,如果到这里你没有发现它们之间的不同,请回顾一下除法的意义。
       另外,如果想得到小数形式的商,就要用7.0 / 2,这样得到的是浮点数类型的3.5。注意,在计算机中,所有的浮点数都是不准确的,也就是说会有浮点误差,这是计算机精度有限造成的,因此,不能比较两个浮点数是否相等,因为通常你得到的都是“伪值”(即二者不相等)。所以,大家一定要充分利用整数,除非无法避免,尽量不要使用浮点数。
条件表达式'? :':
       具体的使用方法是:表达式1 ? 表达式2 : 表达式3
       意思就是系统先算表达式1,如果表达式1成立,则计算表达式2,否则计算表达式3。并且整个条件表达式的值就是表达式2或表达式3的值(取决于表达式1是否成立)。
这个语句因为比if语句简单,所以用途十分广泛,大家一定要熟练掌握。
       例如,max = x > y ? x : y,这里的意思就是先比较x和y的大小,如果x比y大,则再计算表达式2(也就是x),否则计算表达式3(也就是y),再把计算后的表达式赋值给变量max。
       注:条件表达式有短路原则,如果表达式1成立,那么计算表达式2,而不去考虑表达式3(此时如果计算表达式3甚至可能发生错误)。同理,如果表达式1不成立,那么计算机也不会考虑表达式2的值。
0.1.2  变量
       其实在第一部分已经用到了变量的概念,不过我相信大家对变量或多或少都有个了解,因此就没有再次引入变量的概念。但是,近期在论坛发现有一位朋友在讨论区提出了自己对变量的新看法,我跑去看了看,觉得还是比较深刻的,因此我在这里还要把它拿出来。
       首先,变量是什么?一种很粗浅的理解就是,变量就是随着程序进行而有能力发生改变的量。它改变与否当然是服从编程者的意愿。但是,这个理解在我看来,并不是很深刻,因为很多人会把类似于a,b,这样的东西叫做变量,甚至有些人根据变量名称的汉语意思,来默认这个变量的作用。其实不然,类似a,b,x,level等等,我们应该把它看作一个符号,看作我们和计算机沟通的语言,而不是变量本身,而变量本身,则是存储在计算机内存中的一块数据。而就像我看的那篇帖子中说的,变量名其实就是告诉你,在内存的某处,存储这一堆数据,而这些数据代表的值是什么。因此,x = 3的意思就是,内存中存储着一段表示整数3的数据,而x,就是所谓的“标签”,我把它换成小猫小狗什么的完全可以。
       学过C语言的朋友可能会发现,Ruby里面是没有指针的,这个机制其实为写程序的人提供了很大的方便。Ruby并不是真的没有指针,而是在使用的时候,指针和变量的区别变得模糊起来。下面我们来重点说说Ruby的变量机制。
       Ruby中,任意的符号都可以看作一个变量,并且不加声明就可以直接引用,未经过初始化的全局变量和实变量的值为nil。这个nil到底是何方神圣?其实nil是个伪变量,表示的是“无”,属于Ruby的一种抽象数据实例。程序运行前,在内存的某处的一堆数据来表示nil,所有没有被初始化的全局变量和实变量,都代表它。从这个角度来讲,Ruby中的变量和指针似乎是等价的。但是有时候会发生很多费解的事情,我们来看看下面的两个例子。
(1)
RUBY 代码复制
  1. a = 2
  2. b = a
  3. a = 3
  4. print b #print 是系统内部的输出函数

(2)
RUBY 代码复制
  1. a = [1,2,3]
  2. b = a
  3. a[2] = 4 #这是给数组第2号单元赋值为4
  4. print b

       在第一个例子里面,屏幕上将会打印2,在第二个例子里面,屏幕上会打印124。
       细心的朋友会发现,在(1)中改变了a的值,但是b的值没变;但是在(2)中就不同了,对a进行的某种操作也会在b那里反映出来。但是,无论是哪种情况,在执行b=a之后,a和b表示的是同一块数据(指向内存中的同一片区域,即地址),而不是相同数据的不同拷贝,或者说,b是a的一个别名,你要找这片内存区域,说a也行,说b也行。
       那么,我们应该如何去理解“变量”?在这里我们应该把“变量”都理解成“引用”,它们代表的并不是该数据内容的本身,而是该数据所在的内存地址。把变量的重新赋值理解为指针的指向改变,而数据内容的本身是没有变化的。(这点对Integer之类的东西貌似也是对的,因此你不能说把某一片用于表示“1”的内存区域修改,使其表示“2”,你只能把变量指针的指向从“指向表示'1'的内存区域”改变成“指向表示'2'的内存区域”)
       在后面定义函数的时候,也会发生类似的现象。写过程序的朋友知道,函数上面的参数(我们叫做形式参数,简称形参)和实际的变量(我们叫实际参数,简称实参)没有什么关系,对形参的改变丝毫不影响实参的变化。举个例子来说,假如有下面的程序:
RUBY 代码复制
  1. def swap(a,b)
  2.   t = a
  3.   a = b
  4.   b = t
  5. end

函数的作用是交换a和b两个变量的值,但是如果运行下面的程序:
RUBY 代码复制
  1. a = 3
  2. b = 4
  3. swap(a,b)
  4. p a,b

       我们会发现a和b的值并没有发生交换,原因就是计算机只是把实际参数的值拷贝给了形式参数,之后函数内部对形式参数进行的操作与实际参数无关。
       但是,我们刚才说过,变量实际表示的就是地址,而我们知道,相同的地址必定指向相同的内存空间,对同一块内存空间进行操作,变量的值当然会发生改变。例如:
RUBY 代码复制
  1. def f(a)
  2.   a[1] = 3
  3. end
  4. a = [2,2,3]
  5. f(a)
  6. print a

       得到输出的结果应该是233,这就意味着函数真正地对a进行了操作。因此,我们得出结论,传递到方法中的参数(实际是地址)会被复制一份,不会对实际的参数发生改变,而可以按照这个地址参数对其他区域进行操作,总之,实际参数的地址是不会变的。总之,一句话,这里函数参数的传值方式为“值传递(Pass By Value)”,记住这点也就不难理解上面的现象了。

最后我们要说Ruby中最常见的三种变量,这三种变量起作用的时机不同,用法不同,因此要分情况进行使用。
(1)全局变量
       在Ruby中,全局变量以$开头,例如$t,$game_party,等等。它们是在程序的任何地方都有效的变量,也就是说,如果变量名字相同,那么必定就是同一个全局变量。因此,只有我们要创建共享范围比较大(在程序的不同地方都要用)的变量时,才能用到它,否则一般不用全局变量。最常见的例子,就是跨类进行全局变量调用,如果你定义了一个类,使用的过程中需要调用别的类的内容,就要用全局变量来帮忙。例如在Window_Item类中就调用了Game_Party类的实例$game_party,试想,如果$game_party不是全局变量,在Window_Item中,计算机不认识Game_Party中的符号,那么当然会发生访问错误。这个地方,到了我说类(class)的时候,大家会有更加清楚的认识。
(2)实变量
       在Ruby中,实变量以@开头,通常是跟具体对象关联的。
例如:
RUBY 代码复制
  1. class Person
  2.   def initialize
  3.     @name = "XX"
  4.   end
  5.   def pr_name
  6.     print @name
  7.   end
  8. end
  9. print @name

       在这里,@name进入到了函数pr_name的内部,对@name进行访问时,访问的应当是“这个对象的@name”。但是如果在这个类之外写print @name,那么你一定看到的是nil,因为这时@name已经不是Person中的@name。
(3)局部变量
       在Ruby中,局部变量就是没有前缀的变量,比如level,x,等等。这一类的作用范围更窄,只是在定义函数内部有效,作为块参数的局部变量只在当前块内有效。在函数外面则是无效的。因此,我们在函数临时需要一个变量,函数结束后完全不需要的时候,就应该用这种变量。另外,函数的形式参数也要用局部变量表示。在这里面说明的一点就是,这种类型的变量是没有默认值的。例如:
RUBY 代码复制
  1. def fun
  2.   a = 2
  3.   return 2 * a
  4. end
  5. def fun2
  6.   b = a + 1
  7.   return b
  8. end

       在这里fun中的a和fun2中的a一毛钱关系都没有,它们是两个符号。所以我们明显看到,fun2中,对a进行的操作时非法的,因为此时a没有初始化,所以系统不能把它看做一个变量,在后面我们要说到,函数名字(方法)也是采用这种无前缀符号形式表示,系统会寻找与之同名的方法,如果还找不到方法,那么运行的时候,系统会提示错误信息No method error。
       但是,自动变量的好处就是用完能及时回收,保证内存空间,但是对于全局变量,如果创建出来,在写程序的人没有下达命令的时候,系统是不敢轻易回收它的。试想如果程序里面的变量都是全局的,那么用不了多长时间,内存就塞满了,这对运行程序来说是非常致命的。因此大家务必要清楚什么时候该用什么变量,才能做一个合格的“准脚本党”。
0.1.3  常量和伪变量
       在这里顺便介绍一下常量和伪变量。
   
       常量,顾名思义就是这个量代表一个特定的值,一般不能被改变。Ruby中常量的表示方法是用首字母大写的标识符表示,例如Icon,MAXNUM等等,因此常量必须要赋予初始值。当然,常量也有作用的范围,使用常量时,建议把它们放到命名空间中去,这样能够突出常量的作用域,避免发生混淆。常量的作用是为了编写程序的方便,例如,论坛上有很多这样的脚本,显示一个窗口,但是在40号开关打开的情况下,窗口是不显示的。我们可以在外面利用常量WINDOW = 40来表示控制其是否显示的开关ID,这样如果要改动,只需要改动一处即可。
       伪变量,是一类特殊的变量。Ruby中的伪变量常见的有4个,分别是self,true,false,nil。下面我们分别来说一下。
       self:被处理对象的本身,这个概念在我们讲到类的地方会详细说明,初学者会比较难懂(说实话我在接触Ruby初期就完全不懂得self的含义)
       true/false:表示一种逻辑值,实际是TrueClass/FalseClass的唯一实例。true是恒真,false是恒假,一般作为if的条件判断来使用,之间的运算符合逻辑运算。
       nil:Ruby中的特殊数据类型实例,表示“无”,注意,它并不能代替不同类所谓“空”的概念。在数组类型中,空数组用[]表示,不用nil,在字符串中,空字符串用""表示,也不用nil。nil本身没有多少方法,大家可以认为它也表示一个恒假的值。

       值得一说的是,表示伪的方式有很多,大家一定要记住2种,false,nil,这两个都表示伪,和C语言不同的是,数字0以及其他的值都表示真。[此处感谢无脑之人的宝贵意见]

0.2  几个建议
       在本章节的最后,给大家提几个建议。

0.2.1  写任何脚本都要有良好的书写规范,脚本中要注意缩进,要有层次感。变量和运算符之间,最好用空格隔开。例如x = a + b这样。
0.2.2  变量名字要取得适当,尽量取一些有含义的名字,这样能让写程序和看程序的人知道这个变量代表什么。例如表示等级,就用level,而不是用简单的m或者n。循环变量一般都用i,j表示,这点大家养成习惯就好。另外,短下划线“_”看做一个字母,如果要分隔变量之间的单词,请用_,例如icon_size,中间的“_”当然不能换成空格。大家使用标识符时,不要使用中文字符,以免发生错误。
0.2.3  要培养自主纠错能力,不要提示个什么错误就茫然不知所措。系统弹出那个小小的对话框经常会包含重要的错误信息,这样能协助你改正错误。出现的错误,可能是Syntax Error(语法错误,可能是少打end或者是捏造了不存在的写法),可能是No Method Error(未定义方法错误,可能是对nil调用方法或者是类的概念模糊),可能是Name Error(命名错误),一切都要具体情况具体分析。

*0.3  有关变量/指针/地址的重要补充(第二版更新)
       这个是补充的内容,有兴趣的初学者可以看看,当然大神什么的就免了。

       写这里的原因是时隔半年,突然发现自己的教程里面有很多东西没有说清楚。当然半年前还没有学过Java基础课,对有些东西的猜测也不敢随便写上去,现在把它补上。

       在变量机制方面,Ruby和Java非常相似。不同的是,Ruby使用变量前无需声明,因此不必告诉编译器各种变量的类型,Java中使用变量之前还是要声明的。还有一点不同就是Ruby是“万物皆对象”,即所有的数据都是一个对象,而Java除了对象以外,还有类似于int,char等基本数据类型。我们下面说的就是对象这一方面。

       如果想要创建一个对象的实体,就必须对类调用new方法,这样系统会在内存中动态地开辟一块区域,然后用调用构造方法initialize,最后把对象的引用返回给变量。如果不调用new方法,系统不会在内存中开辟区域。
下面是一个例子:
RUBY 代码复制
  1. class A
  2.   attr_accessor :x
  3.   attr_accessor :y
  4.   attr_accessor :z
  5.   def initialize(x,y,z)
  6.     @x = x
  7.     @y = y
  8.     @z = z
  9.   end
  10. end

执行:a = A.new(0,0,0),效果如图

执行:b = A.new(1,1,1),效果如图

注意到变量a和b的地址不同
执行:b = a,效果如图

       执行完毕后,a和b变成了一个地址,指向了同一片内存区域。这就相当于为同一片内存区域建立了两个标签,或者说起了个别名,无论对a还是对b访问都会访问到这个区域。也就是说,a.x = 2和b.x = 2的效果完全相同。

       那么,原来b代表的内存空间去哪了?即上面图的最右的部分,它不被任何指针变量所拥有,也不可能通过其他变量访问到它。像这种不被任何指针变量所拥有的内存区域,就应当被回收,以供别的变量使用。Ruby和Java相同,都有一套GC机制(Garbage Collection),它会定期检查内存空间是否已经不被任何一个指针变量所引用,如果没有任何指针指向它,GC就会把它回收再利用。注意,GC执行不是实时的,否则的话效率会变得很低。

       说这里有什么用呢?是为了解释RGSS1中一处不太好理解的脚本(至少个人认为是这样),要解释这个地方,还需要了解一下Ruby存储对象的机制。
我们先看下这个脚本:
RUBY 代码复制
  1. class Game_Party
  2.   #--------------------------------------------------------------------------
  3.   # ● 同伴成员的还原
  4.   #--------------------------------------------------------------------------
  5.   def refresh
  6.     # 游戏数据载入后角色对像直接从 $game_actors
  7.     # 分离。
  8.     # 回避由于载入造成的角色再设置的问题。
  9.     new_actors = []
  10.     for i in [email]0...@actors.size[/email]
  11.       if $data_actors[@actors[i].id] != nil
  12.         new_actors.push($game_actors[@actors[i].id])
  13.       end
  14.     end
  15.     @actors = new_actors
  16.   end
  17. end

       这个方法出现在Game_Party中,我第一次看这里的时候,注释就没有看懂。什么叫“游戏数据载入后角色对象直接从$game_actors中分离,回避由于载入造成的角色再设置问题”?

       而后全局搜索$game_party.refresh,发现它只出现在一个地方:Scene_Load(101)。可见真的是为了处理载入方面的问题。那么,既然载入了,为什么还要多次一举这样设置一番呢?

       稍微懂点RGSS1的人都知道,$game_actors是存储所有主角角色的变量,编写的时候利用了类Array的外壳。而$game_party.actors是存储当前队伍中所有角色的数组,当然这个集合是所有角色集合的子集。那么,这两个地方都有指向Game_Actor类的引用,它们必须要保持一致。下面的图形能够说明这一问题。

       但是,如果涉及到对象的存储问题,实际就不是这样了。我们在Scene_Save中可以看到,系统对$game_actors和$game_party都做了存储。因为写入文件的是对象,所以不但要把对象本身写入,而且要把对象内部的引用也要写入,如果对象内部的引用还有引用,那么也要写入……说白了,要写入$game_party本身,也要写入$game_party.actors这个数组对象,注意,写入$game_party本身只写入了$game_party.actors数组的引用,数组本身的内容没有写入。由于$game_party.actors是对象数组,因此还要把数组中的每一个Game_Actor对象都写入进去。而刚才我们提到,$game_actors中也含有所有Game_Actor对象,这样一来,同样的数据要写入两遍。读取的时候自然也要读两遍。我们在这里做个测试:
RUBY 代码复制
  1. class Scene_Load
  2.   #--------------------------------------------------------------------------
  3.   # ● 读取存档数据
  4.   #     file : 读取用文件对像 (已经打开)
  5.   #--------------------------------------------------------------------------
  6.   def read_save_data(file)
  7.     # 读取描绘存档文件用的角色数据
  8.     characters = Marshal.load(file)
  9.     # 读取测量游戏时间用画面计数
  10.     Graphics.frame_count = Marshal.load(file)
  11.     # 读取各种游戏对像
  12.     $game_system        = Marshal.load(file)
  13.     $game_switches      = Marshal.load(file)
  14.     $game_variables     = Marshal.load(file)
  15.     $game_self_switches = Marshal.load(file)
  16.     $game_screen        = Marshal.load(file)
  17.     $game_actors        = Marshal.load(file)
  18.     $game_party         = Marshal.load(file)
  19.     $game_troop         = Marshal.load(file)
  20.     $game_map           = Marshal.load(file)
  21.     $game_player        = Marshal.load(file)
  22.     # 加上这个
  23.     p $game_actors[1].to_s,$game_party.actors[0].to_s
  24.     # 魔法编号与保存时有差异的情况下
  25.     # (加入编辑器的编辑过的数据)
  26.     if $game_system.magic_number != $data_system.magic_number
  27.       # 重新装载地图
  28.       $game_map.setup($game_map.map_id)
  29.       $game_player.center($game_player.x, $game_player.y)
  30.     end
  31.     # 刷新同伴成员
  32.     $game_party.refresh
  33.   end
  34. end

在读取数据完毕之后,我们来看看这两个对象的地址。注:所有对象都有to_s方法,如果不加重设的话,返回的是引用的地址。

       由于$game_actors实际有意义的数据是从下标[1]开始,因此$game_actors[1]和$game_party.actors[0]是一样的,但是它们的地址却不一样。这就要调用$game_party.refresh,让这两部分引用保持一致性。
       大家可以想想,如果不调用$game_party.refresh,会出现什么后果,而此时的内存地址模型又是怎样的?

       预备知识就说到这里吧,虽然比较繁琐,但是我觉得在帮助上还是看不到的。这个帖子是连载,有时间我会写后面的内容,那些才是重头戏,大家一起期待之后的帖子吧。

点评

编辑帖子时就会有这个提示。说明楼主更新了  发表于 2014-7-5 18:54
每次都看见你在“和我同一个楼层”评论,但是每次我都找不到  发表于 2014-7-5 18:54
短消息的内容我已经放在32L,请务必看一看  发表于 2014-7-2 15:48
请查收短消息  发表于 2014-7-2 15:34
回复:无脑之人 是这样的哈,我下了Ruby的源码,发现是从C上移植过来的,因此也没多想,多谢提醒。  发表于 2013-10-13 20:46

评分

参与人数 8星屑 +238 收起 理由
gonglinyuan + 30 精品文章
zmz6668 + 8 精品文章
季长风 + 10 精品文章
jspython + 10 精品文章
秋寒 + 30 塞糖
wingzeroplus + 20 精品文章
feizhaodan + 120 奖赏条例
无脑之人 + 10 精品文章

查看全部评分

Lv3.寻梦者

梦石
0
星屑
4654
在线时间
431 小时
注册时间
2016-5-11
帖子
140
59
发表于 2023-5-4 12:14:07 | 只看该作者
教程看完了,学会了P函数
开玩笑的,感谢楼主和各位大神,留名支持一下
这不算挖坟吧。

点评

挖出RB10年前的黑历史了  发表于 2023-5-5 20:23
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
287
在线时间
274 小时
注册时间
2010-5-30
帖子
44

开拓者

58
发表于 2018-3-7 16:36:04 | 只看该作者
RyanBern 发表于 2018-3-7 09:11
一个比较方便的做法是将真实商店变成 $game_system 对象里面的一个实变量。因为 $game_system 这个对象是 ...

改完可以存储了=w=谢谢版主大大!看起来$game_system里面可以塞好多东西……
回复 支持 反对

使用道具 举报

Lv4.逐梦者 (版主)

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

开拓者贵宾剧作品鉴家

57
 楼主| 发表于 2018-3-7 09:11:09 | 只看该作者
tsukishinu 发表于 2018-3-6 14:47
版主大大你好,想请教一个问题。我照着这个帖子写完了真实商店,虽然功能基本实现了,但是商店里的数据没法 ...

一个比较方便的做法是将真实商店变成 $game_system 对象里面的一个实变量。因为 $game_system 这个对象是可以自动存储的,所以以它为载体存储额外对象是个重要的技巧。

代码只需要添加:
RUBY 代码复制
  1. class Game_System
  2.   attr_accessor :visualshop
  3. end


而后在生成真实商店的时候使用 $game_system.visualshop = Game_VisualShop.new(args) 即可
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
287
在线时间
274 小时
注册时间
2010-5-30
帖子
44

开拓者

56
发表于 2018-3-6 14:47:33 | 只看该作者
版主大大你好,想请教一个问题。我照着这个帖子写完了真实商店,虽然功能基本实现了,但是商店里的数据没法存档,毕竟真实商店的库存和玩家操作有关。数据写在了$game_visualshop数组里面,如果在Scene_Title里面初始化就没法保存了,不知道改怎么写才能让数据保存下来。
如果版主大大看到了,希望能指点一下(跪),非常感谢版主大大写了这个教程,学到了很多,终于能看懂默认脚本了。

ps:不知道算不算挖坟啊,但是没权限发消息对不起((
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
4474
在线时间
1045 小时
注册时间
2016-5-19
帖子
262
55
发表于 2017-4-20 10:23:07 | 只看该作者
版主大大,请问我看完了第四章节就能把战斗菜单改成新仙剑奇侠传那样了吗?

点评

看完窗口和场景才(有可能)可以。  发表于 2017-4-20 21:19
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
881
在线时间
7 小时
注册时间
2017-1-19
帖子
1
54
发表于 2017-1-21 19:29:50 | 只看该作者
本帖最后由 zwlstc109 于 2017-1-21 19:41 编辑

支持下
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (暗夜天使)

只有笨蛋才会看到

梦石
1
星屑
21599
在线时间
9411 小时
注册时间
2012-6-19
帖子
7117

开拓者短篇九导演组冠军

53
发表于 2016-7-8 22:37:16 | 只看该作者
本帖最后由 喵呜喵5 于 2016-7-8 22:39 编辑
银羽凌云 发表于 2016-7-8 19:03
大神求教
class Person
  attr_accessor:name,:sex,:age


没有任何正常的做法能够实现你所希望的效果,因为 Ruby 是动态类型的,所以和 C 语言等静态类型语言不同下面这段代码执行时不会报错
  1. a = 1
  2. a = "hello"
复制代码

而也正是因为Ruby是动态类型的,赋值操作实际上是传递一个引用,上面这段代码中,a=1时,a是一个指向1的值,a="hello"时,a是一个指向hello的值,a 并不是一个具体的数值,而更像是某一个具体数值的一个“外号”或者“别名”

所以,在下面这段代码中,你会看到一个奇怪但符合这一规则的结果
  1. class Person
  2.   attr_accessor :name,:nickname
  3.   def initialize(name,nickname)
  4.     @name = name
  5.     @nickname = nickname
  6.   end
  7. end
  8. xiaoming = Person.new("小明","xiaoming")
  9. xiaoming2 = xiaoming
  10. xiaoming2.name = "小明明"
  11. print xiaoming.name
复制代码

修改 xiaoming2 的名字时,xiaoming 的名字也跟着发生改变了

不论是 xiaoming 还是 xiaoming2,他们都只是别人给 Person("小明") 起的一个外号,有些外号是你直接起了告诉小明的(@nickname),有些外号是你背地里偷偷起的(xiaoming2 = xiaoming),
直接起的外号小明知道,起外号的你也知道,你提到这个外号便知道说的是小明,你问小明他有什么外号他也会告诉你
背地里偷偷起的外号你自己知道,提到这个外号也知道说的是小明,但是你问小明知不知道这个外号时,小明自然就懵逼了


另外,实际写代码过程中一般不会出现真的需要获取小明外号的情况





评分

参与人数 1星屑 +150 收起 理由
RyanBern + 150 触瞎

查看全部评分

回复 支持 反对

使用道具 举报

Lv4.逐梦者 (版主)

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

开拓者贵宾剧作品鉴家

52
 楼主| 发表于 2016-7-8 22:13:33 | 只看该作者
银羽凌云 发表于 2016-7-8 21:59
大神求教
class Cuboid
  def initialize(number)

001表示一个八进制数,因此不建议你这样给实变量赋值。

一个可行的办法是这样
[pre lang=Ruby]def count
  print sprintf("长方体%03d", @cuboid_number)
end[/pre]

然后调用cuboid_001 = Cuboid.new(1)
利用sprintf可以进行格式化输出。

至于第一个问题,我不会写。你可以考虑使用eval来计算表达式的值。
name='xiaoming'
eval name+'.name = "小红"'
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
16 小时
注册时间
2016-6-11
帖子
3
51
发表于 2016-7-8 21:59:06 | 只看该作者
大神求教
class Cuboid
  def initialize(number)
    @cuboid_number = number
  end
  def shuchu
    number = @cuboid_number
    print "长方体#{number}"
  end
end
cuboid_001 = Cuboid.new(001)
cuboid_001.shuchu
结果:长方体1
怎样才能得到结果:长方体001
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-11-11 13:19

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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