Project1

标题: [囧]跟我从头读脚本[挖坑啦挖坑啦- -U Scene0~2发布] [打印本页]

作者: Benavii    时间: 2007-3-9 07:15
标题: [囧]跟我从头读脚本[挖坑啦挖坑啦- -U Scene0~2发布]
跟我从头读脚本

——写在前面——

阅读本文之前请先确认三件事:
1、你是否已经能够顺利地阅读大部分默认脚本?如果是,那你可以不必花费时间看这篇文章,因为本文恐怕无法提供你所需要的进阶知识。
2、你是否愿意学脚本?如果是,请确定你是“愿意”而不是“想要”,与单纯的求知不同,前者意味着你愿意为之付出,无论只是一点点业余时间还是长时间的刻苦钻研。
3、你是否已经阅读了RMXP自带的F1帮助文档?如果否,建议你打开RMXP,按下F1,将电子书的内容从头到尾读一遍,不管理解了多少。

———————————————————————————————————————

大家早上好 囧/~ 我是小贝。(不是贝克X姆的贝啦。-_\\)
接触RM也有几个月了,一直听到有人在抱怨脚本难学,我不否认这一点-_\\ 但是,看懂默认的脚本并不是一件很难的事情,毕竟么,程序开发出来就是方便人使用的而不是为了刁难人的,何况RMXP还自带了那么人性化的一个帮助文档。理论上说,将F1帮助文档里的内容看懂80%以上,就可以通读大部分的默认脚本了。
然则……理论归理论,实际上看了F1后仍然一头雾水的也大有人在(比如我-_\\)。理论的东西容易流于抽象,不用实践经验将其固定下来的话,仍然是无用的知识。为了尽快将这理论融入实践,接下来的时间里我们将一起学习RMXP自带的最大也是最完善的范例工程——那就是默认工程本身。
Ready?Okay,Let’s go.
作者: Benavii    时间: 2007-3-9 07:15
标题: [囧]跟我从头读脚本[挖坑啦挖坑啦- -U Scene0~2发布]
跟我从头读脚本

——写在前面——

阅读本文之前请先确认三件事:
1、你是否已经能够顺利地阅读大部分默认脚本?如果是,那你可以不必花费时间看这篇文章,因为本文恐怕无法提供你所需要的进阶知识。
2、你是否愿意学脚本?如果是,请确定你是“愿意”而不是“想要”,与单纯的求知不同,前者意味着你愿意为之付出,无论只是一点点业余时间还是长时间的刻苦钻研。
3、你是否已经阅读了RMXP自带的F1帮助文档?如果否,建议你打开RMXP,按下F1,将电子书的内容从头到尾读一遍,不管理解了多少。

———————————————————————————————————————

大家早上好 囧/~ 我是小贝。(不是贝克X姆的贝啦。-_\\)
接触RM也有几个月了,一直听到有人在抱怨脚本难学,我不否认这一点-_\\ 但是,看懂默认的脚本并不是一件很难的事情,毕竟么,程序开发出来就是方便人使用的而不是为了刁难人的,何况RMXP还自带了那么人性化的一个帮助文档。理论上说,将F1帮助文档里的内容看懂80%以上,就可以通读大部分的默认脚本了。
然则……理论归理论,实际上看了F1后仍然一头雾水的也大有人在(比如我-_\\)。理论的东西容易流于抽象,不用实践经验将其固定下来的话,仍然是无用的知识。为了尽快将这理论融入实践,接下来的时间里我们将一起学习RMXP自带的最大也是最完善的范例工程——那就是默认工程本身。
Ready?Okay,Let’s go.
作者: Benavii    时间: 2007-3-9 07:16
Scene 0:一些基本概念

Ruby是面向对象的语言,拥有类和方法是面向对象语言的一个典型特征。那么什么是类和方法呢?
打个比方。比如你要在庭院里的(x,y)位置种一棵树,那么种树的全过程如下:

你走到了(x,y)
你掘了一铲子土
你又掘了一铲子土
你又掘了一铲子土
你把树苗竖在坑里
你添上一铲子土
你又添上一铲子土
你又添上一铲子土
你给树苗浇了水
种完了
聪明人很快就发现这种记录方式比较傻,所以我们定义一个叫做“挖坑”的方法:

def 挖坑
你掘了一铲子土
你又掘了一铲子土
你又掘了一铲子土
完毕

这样,写一个“挖坑”就代表掘了三铲子土。同理可以写一个“培土”的方法来代表往坑里添上三铲子土。这样种树的过程简化如下:

你走到了(x,y)
挖坑
你把树苗竖在坑里
培土
你给树苗浇了水
种完了

这样看起来就比较像人话了(喂),而且简化了书写,避免了重复劳动,这里“挖坑”“培土”就是我们新定义的方法。
类其实本质上跟方法差不多,可以看作是包含了一组方法的大方法。比如你想要让一个人专门在庭院里种树,可以定义如下的一个方法:
class 种树工
def initialize(x,y)
   走到(x,y)
   挖坑
   把树苗竖在坑里
培土
给树苗浇水
end
def 挖坑
掘了一铲子土
又掘了一铲子土
又掘了一铲子土
end
def 培土
  添上一铲子土
又添上一铲子土
又添上一铲子土
end
end
这样,@老王 = 种树工.new(x,y)就代表老王是一个种树工。这里的x和y被叫做参数,它可以代入范围内的任何数值。
如果没有写“挖坑”的定义部分,就会出现NoMethodError,找不到“挖坑”方法。这也是制作过程中最常见的报错。当程序调用了一个方法,但这个方法并不在该类中时,就会报这个错误。也就是说,即使将“挖坑”这个方法放在其他类中,程序也还是一样找不到,因为调用的是“种树工”这个类,所以它只会在“种树工”这个class中找方法。
类是可以继承的,在class 类名后面加上“<”和另一个类名就可以让前者继承后者中的方法,这样前者就可以使用在后者中定义的方法了。比如定义一个新类叫做“劳动者”,“劳动者”中定义了一个新方法“真·挖坑”,然后把class 种树工改成class 种树工 < 劳动者,这样就可以在“种树者”这个类中调用“劳动者”中的方法“真·挖坑”,虽然“真·挖坑”这个方法并没有在“种树者”这个类中被定义过。不过,在摆放脚本的时候,父类要放在子类上面,否则会出现TypeError。(所以说脚本编辑器里各组脚本的摆放顺序也是有学问的。)
可以直接调用类里的方法,格式是“对象.方法(参数)”(若该方法没有参数就不必带参数),对象必须是该类的实例。比如已经写了@老王 = 种树工.new(x,y)的情况下,再写“@老王.挖坑”就是让(种树工)老王在x,y挖一个坑。

以上是对类、方法和参数的简单说明。仍然觉得陌生也没有关系,这回只是初次见面而已,从今以后就要整天跟他们打交道咯。

作者: Benavii    时间: 2007-3-9 07:17
Scene 1:Min or Max?——Main


准备工作做完,下面就是正式来解读脚本了。首先来读最初的一组脚本:Main。
有的人可能会奇怪,Main不是放在RGSS最下面的么,怎么变成最初的脚本了?难道RMXP是从下往上执行的?实际上,RMXP确实是从上往下读入Main及其之前全部脚本的(这也就是都把不用的脚本扔到Main下方的原因),但Main以上的脚本内容全都是在定义类和方法,并没有开始任何实质性操作。
不算注释的话,默认的Main一共是12行脚本,可说是默认脚本中最短的一组;但它的跨度却很大,整个RM游戏的运行自始至终是在这个Main中循环着的,所以也可以说它是所有脚本中最长的一组。下面我们来看它的具体内容:

begin
  Font.default_name = (["黑体"])
  Graphics.freeze
  $scene = Scene_Title.new
  while $scene != nil
    $scene.main
  end
  Graphics.transition(20)
rescue Errno::ENOENT
  filename = $!.message.sub("No such file or directory - ", "")
  print("找不到文件 #{filename}。 ")
end

begin是程序的开始,而下面的rescue Errno::ENOENT则是捕获错误信息。Begin~rescue~end语句可以看作是一个条件分歧,当没有错误时,执行begin下的部分;而当捕获到错误时,执行rescue下面的部分。也就是说,当游戏正常的运行着时,用到过的只有begin和rescue中间的7行。Rescue下面的部分暂时54掉,一个能完整流畅运行的游戏应该是用不着那里才好。

Font.default_name = (["黑体"])是设定游戏默认字体,很多人下了游戏但对话却没有字,那就是电脑中没有这行里设定的字体导致的。除了安装字体外,对于解密游戏还可以用更改这里的字体名的方法,使文字正常显示。(比如范例游戏Alestian Story用的MS细明体一般人电脑里都不会有,其实将这里的字体名改成“Arial”就可以正常显示了) 如果你是游戏制作者,担心玩家因为缺少字体无法正常看对话,可以将这行改成这样:
Font.default_name = (["黑体",”隶书”,”宋体”])
当玩家电脑上找不到黑体时,会用隶书;没有隶书时,用宋体显示。
(注意字体名一定要填完整,比如“楷体”的全名是“楷体_GB2312”,光打一个“楷体”是无法识别的。)
    另外,在这行下面可以添加一句Font.default_size = 20,这句的意思是“设定游戏默认文字大小为20”(默认大小貌似是32,至于这个20是20磅还是20象素我就不知道了-_\\)。在用事件“显示文字”的时候,往往会出现文字超出文字框的状况,有人以为RMXP的显示文字不会自动换行……实际上文本框仍然是自动换行的,将文字调小就可以全部显示了。

    Graphics.freeze是冻结画面,相当于事件中的准备渐变,常用这个指令的人都知道是怎么回事。如果不熟悉也没关系,以后还有很多的机会见到它。

$scene = Scene_Title.new,设定全局变量$scene的初始值。形如$scene的变量(即是以$开头的变量)是全局变量,一经赋值即可在脚本的任何地方调用。“scene”是这个全局变量的名称。Scene_Title是一个类(class)的名称,而new方法则是Class类(默认类,不在脚本编辑器中)生成对象的一个实例,在这里是生成Scene_Title的一个实例。说“实例”有点难以理解的话,可以认为是“生成了一个Scene_Title”。
Scene是英文“场景”的意思,一个RM游戏可以认为是一幕幕的Scene组成的。

  while $scene != nil
    $scene.main
  end
    这三行是一个while~end语句,意思是“当满足条件的时候则执行while和end之间的部分”,而条件就是写在while右边的语句。Nil意为“无”,一切未经赋值的变量初始值都为nil(并不是0),$scene != nil的意思则是当$scene已经被赋值时(即$scene不为“无”时,这种判断变量是否被赋值的方法经常会用到)。$scene.main是调用$scene的main方法。$scene本质上不过是一个变量,但$scene = Scene_Title.new已经给它赋了值,它现在就是新生成的那个Scene_Title,所以调用它其中的方法就是在调用写在了Scene_Title里的main方法。

  Graphics.transition(20)这句相当于事件中的“执行渐变”,参数20表示在渐变时长为20帧(差不多是1秒),也可以是Graphics.transition(20,”路径”)这种书写格式,这样写的时候会用路径指定的蒙版来渐变,相当于事件中设定渐变图形。


    最后简单地说一下程序的运行流程。程序从begin开始,一直到$scene.main这句之前都是执行Main中写好的内容,从$scene.main这句开始调用每个Scene的main方法。(所以每个Scene中直接运行的部分也只有main方法里的内容而已。) 当一个Scene结束,由于没有其他内容可执行又回到了$scene.main这里,这时$scene已经变为新的值,$scene.main便继续调用新scene的main方法,如此一直循环下去。

    Main是默认脚本中最小也是最大的一组脚本,是整个程序的核心部分,但需要改动的地方并不是很多。之所以把它放在第一个来读,除了简短之外,还有熟悉Ruby语境和初步掌握RGSS结构的设想。如果对于某些方法的作用理解困难,不必担心,后面还有的是他们的戏份。

作者: 絮儿    时间: 2007-3-9 07:18
真•挖坑
{/fd}

贝贝师傅好棒哒~~支持~= ={/tp}
作者: Benavii    时间: 2007-3-9 07:19
Scene 2 最初的Scene——Scene_Title

    下面要读的是整个游戏的第一个场景:Scene_Title。
    默认的SceneTitle有217行,在默认脚本中算比较长的了。它可以被分成两部分,一是执行时用到的main方法,一是main方法中调用的各种方法的定义。先来看main方法。

    Scene_Title的Main方法从11行开始,到87行结束,忽略掉开头的战斗测试判定,它可以被分为标准的三部分。18~66行是第一部分(生成对象),68~79是第二部分(刷新循环),81~86是第三部分(释放对象)。
    首先来看第一部分。
   
    1-1,18~30行,载入数据库。
$data_actors        = load_data("Data/Actors.rxdata") #——载入角色数据
    $data_classes       = load_data("Data/Classes.rxdata") #——载入职业数据
    $data_skills        = load_data("Data/Skills.rxdata") #——载入技能数据
    $data_items         = load_data("Data/Items.rxdata") #——载入道具数据
    $data_weapons       = load_data("Data/Weapons.rxdata") #——载入武器数据
    $data_armors        = load_data("Data/Armors.rxdata") #——载入防具数据
    $data_enemies       = load_data("Data/Enemies.rxdata") #——载入敌人数据
    $data_troops        = load_data("Data/Troops.rxdata") #——载入队伍数据
    $data_states        = load_data("Data/States.rxdata") #——载入状态数据
    $data_animations    = load_data("Data/Animations.rxdata") #——载入动画数据
    $data_tilesets      = load_data("Data/Tilesets.rxdata") #——载入图块数据
    $data_common_events = load_data("Data/CommonEvents.rxdata") #——载入公共事件数据
    $data_system        = load_data("Data/System.rxdata") #——载入系统数据
    在数据库中设定好的各类数据,被保存在Data文件夹下对应的文件中。load_data(”路径”)则是从指定文件中读取数据的方法。整句$data_actors = load_data("Data/Actors.rxdata")的完整含义是从Actors.rxdata文件中读取数据并赋给左边的变量$data_actors。(实际上这些$data_xxxx都是一些数组……)
    $game_system = Game_System.new,生成一个新的Game_System实例。Game_System中存着一些系统附属数据,比如BGM等声音的控制,事件解释器,计时器等等。$game_system的状态是会被存进存档文件的,所以增加一种数据的话,写进Game_System也是一个不错的选择。
   
@sprite = Sprite.new
    @sprite.bitmap = RPG::Cache.title($data_system.title_name)
    这两句是在生成标题图片。形如@sprite的变量是实例变量(以@开头),它的作用范围限于类的内部,也就是说只在Scene_Title这个类里有用,并且只要是在这个类里,任何一个方法都可以调用它。第一句是生成一个新的Sprite对象(就是图片对象),第二句则是指定这个Sprite的bitmap(位图,就是具体要显示哪张图片)。RPG::Cache.title(“XX”)是将Graphics\title文件夹下名为“XX”的图片读入缓存,可以简单地理解为指定@sprite为这张图片。$data_system就是载入数据库时载入的系统数据,里面记录了数据库“系统”选项卡上的内容,而title_name这个方法则是获得在数据库“系统”选项卡里设定好的标题图片文件名。

    s1 = "新游戏"
    s2 = "继续"
    s3 = "退出"
    @command_window = Window_Command.new(192, [s1, s2, s3])
    @command_window.back_opacity = 160
    @command_window.x = 320 - @command_window.width / 2
    @command_window.y = 288
    37~43,生成一个选项窗口。
    形如s1的变量是局部变量(小写字母或下划线开头,不能是保留字),它的作用范围限于方法的内部。在这里前四行可以合写为@command_window = Window_Command.new(192, [“新游戏”, “继续”, “退出”])。在选项比较少的情况下,分开写并没有什么太大的意义;但当选项多起来的时候,用变量使之简捷美观就变得很有必要了(比如Scene_Menu中的选项窗口)。
Window_Command.new是生成一个新的Window_Command对象(对于生成对象已经很熟了吧?),Window_Command是指令窗口的类,除了继承Window_Selectable中光标相关的各种方法之外,还有诸如disable_item等专为指令窗口设计的方便方法。
back_opacity是设定窗口背景透明度的方法(最小为0——全透明,最大为255——不透明),注意这个方法只有设定窗口背景的透明度,即默认skin的蓝色区域,周围白色的边框和内部的文字都是不透明的。(opacity是连边框一起的透明度,而contents.opacity则是窗口内容的透明度)
x是指定窗口左上角x坐标的方法,y是指定左上角y坐标的方法,width是指定窗口宽的方法,height则是指定窗口高度的方法。这四个值决定了窗口的形状和位置,可以在窗口的类的initialize方法中更改他们,也可以在调用该窗口的Scene中像上面这样更改他们。

    @continue_enabled = false #——设置读档标志为不可用
    for i in 0..3 #——0到3的for循环
      if FileTest.exist?("Save#{i+1}.rxdata") #——若游戏文件夹下存在名为Save#{i+1}.rxdata的文件
        @continue_enabled = true #——设置读档标志为可用
      end #——if判定的end
    end #——for循环的end
    if @continue_enabled #——如果读档可用
      @command_window.index = 1 #——设置命令窗口的索引为1
    else #——否则
      @command_window.disable_item(1) #——设置命令窗口选项为不可用
    end #——if判定的end
    47~59行是在做一个效果,就是如果存在存档文件,标题画面的“读取”选项可用,反之则呈灰色显示。其中@continue_enabled是个普通的实例变量,叫什么都可以,这里只是用它做一个标记方便下面的判断。
    FileTest.exist?("路径/文件名")是判定指定路径下是否存在某文件的方法,其中文件名要打全名(png格式的图片在此也不能省略扩展名)。
    如果一个变量只有真假值时,可以简略的用if @变量名代替if @变量名 == true,用if !@变量名代替if @变量名 == false。
    Index和disable_item(index)都是Window_Command里面的方法(index是用attr_reader而不是def定义的),这个后面会说到。

    接下来的四行比较简单:
    $game_system.bgm_play($data_system.title_bgm) #——开始播放bgm
    Audio.me_stop #——停止播放ME
    Audio.bgs_stop #——停止播放BGS
    Graphics.transition #——执行渐变
    到Graphics.transition为止,整个生成对象部分就完结了。在生成对象部分中,生成了本Scene需要调用到的各种对象,包括窗口,精灵等。同时,一些想要在图像变化之前(随图像一起)开始播放的音乐之类也在此处设定。
    注意,第一部分的内容也仅仅是“设定”,除了设定初始值之外,并不会直接运行。

    接下来是第二部分,刷新循环。这部分比第一部分短很多,且在每个Scene中基本是一样的:
    loop do #——循环
      Graphics.update #——刷新画面
      Input.update #——刷新输入信息
      update #——调用update方法
      if $scene != self #——当场景变换时
        break #——中止循环
      end #——if语句结束
    end #——循环结束
    Graphics.update是刷新画面的指令,让画面前进1帧,无论画面上是否有在活动的东西它都会刷新,可说是游戏中执行次数最多的一条指令。两次执行这条指令的间隔如果超过十秒,就会被程序认为是卡死从而强制关闭,弹出一个“脚本已经被备分”的对话框。如果出现这种情况时,请重启电脑或整理内存,关闭不必要的应用程序然后再测试,如果还出现,那就是程序里有死循环了。标准情况下,未开启平滑模式时,一秒钟会刷新20次画面,开启后一秒钟刷新40次。
    Input.update是刷新输入信息,当某个Scene需要接受按键处理时,就要在loop do循环里加上这么一句,否则Scene是不会管你有没有在按键的。刷新输入信息跟刷新画面一样,也是一秒钟20次或40次。(据说世界上按键最快的人每秒能按键18次?……反正够用的了。=v=)
    If $scene != self,是判定场景是否有变更的语句。Self是个伪变量,它指的是“当前方法的执行对象本身”,听起来有点绕口,实际上可以简单地理解为它就是指SceneTitle,而SceneMap中的self指SceneMap,WindowItem中的self指WindowItem。
    当要变换场景时,使用$scene = Scene_XX.new,然后在这循环里由于$scene的值已变而self值未变,满足了$scene != self,于是执行了break(中断循环),程序往下进行来到第三部分:释放对象。

    释放对象的内容也很短,一共四行:
     Graphics.freeze
    @command_window.dispose
    @sprite.bitmap.dispose
    @sprite.dispose
    dispose方法是将对象释放的方法,将用过的窗口或其他对象用此方法释放掉以节约资源。如果没有将第一部分生成的对象全部释放,每次进入这个场景时都会再生成一次对象,长此以往就会大幅拖慢运行速度,严重时还会卡死。所以当游戏帧数掉的很厉害时,就要仔细检查一下每个Scene是否有把生成的对象全释放掉了。在第一部分生成了三个对象:选项窗口,精灵的图片和精灵本身,这里把他们全释放掉。注意sprite类对象要释放两次,一次是释放掉它的位图,一次是释放它本身。
    Graphics.freeze前面已经说了,是冻结画面的指令,到下次Graphics.transition之前,画面上的一切变化都不会变更。把画面冻结住之后,我们即使释放掉了窗口或图片,它仍然会留在画面上,直到执行下一个Graphics.transition。同理,如果我们在这段期间显示了窗口或图片,它也不会立即在画面上显示出来,直到Graphics.transition之后才会显示。

    这样main方法就结束了。不同的Scene有不同的main方法,但大致上都是可以分为这三段的,且后两段的格式基本都是通用的(特别是菜单类的Scene),虽然长,但并不复杂。

    接下来是Scene_Title中调用的一些方法。首先是不可或缺的update方法,它负责窗口内容的变换和按键处理。Scene_Title的刷新方法还是比较简单的:
  def update
    @command_window.update
    if Input.trigger?(Input::C)
      case @command_window.index
      when 0  # 新游戏
        command_new_game
      when 1  # 继续
        command_continue
      when 2  # 退出
        command_shutdown
      end
    end
  end
    这里@command_window.update这句是调用Window_Command自带的update方法,先不去管它。下面if Input.trigger?(Input::C)是“当按键C被按下时”,这里的“按键C”并不是指键盘上的C键,而是指空格/回车键(其实C键也行-_-),具体的按键与键盘键位对应表可以在帮助文档中“游戏的操作方法”一节查看。接下来是一个case~when~end分歧语句,@command_window.index是取得光标位置的索引值(索引值为0~[选项个数-1]之间的整数)。Case语句跟上面的if语句合起来就是“按键按下时光标停在某选项上时”,而when下面则调用与该选项相对应的方法。

    110~143,定义了开始新游戏的command_new_game方法。
    $game_system.se_play($data_system.decision_se) #——播放系统“决定”的音效。
    Audio.bgm_stop #——停止播放BGM
    Graphics.frame_count = 0 #——重置画面计数器。这个是数帧数用的,游戏时间就是用帧数/速度算出来的。
    $game_temp          = Game_Temp.new #——生成新的临时对象
    $game_system        = Game_System.new #——生成新的系统附属数据对象
    $game_switches      = Game_Switches.new #——生成新的开关。所以直到选择新游戏那一刻,SceneTitle是无法调用事件里的开关或变量的,因为根本就没生成。
    $game_variables     = Game_Variables.new #——生成新的变量
    $game_self_switches = Game_SelfSwitches.new #——生成新的独立开关
    $game_screen        = Game_Screen.new #——生成新的画面对象
    $game_actors        = Game_Actors.new #——生成新的人物对象。这个是数据库里的全部人物而非队中人物。
    $game_party         = Game_Party.new #——生成新的队伍,这回是队中人物了。
    $game_troop         = Game_Troop.new #——生成新的敌人队列。
    $game_map           = Game_Map.new #——生成新的地图对象。
    $game_player        = Game_Player.new #——生成新的主角,这个主要是处理事件启动判定等。
    $game_party.setup_starting_members #——设置初期同伴,就是设定初期队伍中有哪些人。也就是在数据库——系统选项卡里左上角那里设置的人物。
    $game_map.setup($data_system.start_map_id) #——设置人物初期位置,就是把人物放在标着S的白色小方块的那张地图上。所以当没有设置初期人物位置的时候会报错“找不到MAP000.rxdata”。
    $game_player.moveto($data_system.start_x, $data_system.start_y) #——将主角放置在初期位置,就是放在“S”那格。
    $game_player.refresh #——刷新主角
    $game_map.autoplay #——切换地图的BGM与BGS
    $game_map.update #——刷新地图,执行地图上的并行事件
    $scene = Scene_Map.new #——切换到SceneMap。$scene值在这里改变后,本Scene的循环就会因$scene != self而中断。

    147~158,定义的是读档的command_continue方法。

    unless @continue_enabled #——除非读档标记为真。还记得前面用到的@continue_enabled么?作为实例变量,它可以在main之外的方法被调用。另外就是注意unless和if的区别……(我自己总搞混-_\\)
      $game_system.se_play($data_system.buzzer_se) #——播放“冻结”的系统音效
      return #——结束方法。Return之后,方法会直接结束,不去理会下面的指令。
    end
    $game_system.se_play($data_system.decision_se) #——播放“确定”的系统音效。
    $scene = Scene_Load.new #——切换到读档画面
  这个方法很简单,不过return除了结束方法之外还有别的用途,以后再讲。

    162~171,定义了结束游戏的command_shutdown方法。
    $game_system.se_play($data_system.decision_se) #——播放决定音效
    Audio.bgm_fade(800) #——BGM淡出。参数“800”的单位是毫秒。
    Audio.bgs_fade(800) #——BGS淡出
    Audio.me_fade(800) #——ME淡出
    $scene = nil #——场景转换为无。这样当SceneTitle的执行结束,再次回到Main方法时,由于没有Scene可显示,会直接结束。

    最后一部分的battle_test是战斗测试时用的(所以战斗测试并不装载地图,仅由SceneTitle和SceneBattle组成),平时用不到,也没有太大的阅读价值,故不予解读。(实际上无非是装载数据库,设定几个值和场景转换而已,有兴趣也可以看看)

    这样关于Scene_Title的解说就结束了。Scene_Title是游戏最初的场景,在了解了它的构造和功能之后,我们可以着手对其进行各种各样的蹂躏……呃,是改造。比如添加标题画面的选项,改用图片标题菜单,设置标题画面的各种特效(滚动,流星雨,etc.),或者干脆删除不必要的部分直接使用事件做标题画面,都是通过改造这个Scene_Title来完成的。
作者: Benavii    时间: 2007-3-9 07:24
试着照版务区某位同志的设想来写的东西……汗。
1万2千字只是开场白orz (这样下去会死人的……-_\\)

还是那句话,懒得看的人通常更懒得看这种长文,而勤快点的人基本上都用不着这么初级的东西了-_-

先扔个三节看看,如果还有人愿意看就接着填{/gg}

才疏学浅兼之闭门造车,谬误难免,错漏之处还请方家斧正。
作者: 9987788    时间: 2007-3-9 14:25
严重支持……
HOHO!{/cy}
8过以上教程最好按楼主说的 不管怎么 先把F1 看个N遍再来看 否则很多东西 都会很糊涂的
如果实在懒的完全看F1 建议不管怎么 也先把第一个RPGMAKERXP和脚本入门里的解读篇看完 那里有很多有用的东西……

作者: 魔剑美神    时间: 2007-3-9 22:17
真是很赞,脚本盲的某人飘过~~{/hx}
作者: zhong    时间: 2007-3-11 08:20
受教了~~~很详细啊~~记得你曾帮我解决过Scene_Title的问题~~感激ing~~~这个希望能继续下去,很想看看关于Scene_Battle的剖析~~~~除了场景类还会讲解其他类吗?
作者: Benavii    时间: 2007-3-11 08:29
以下引用zhong于2007-3-11 0:20:01的发言:

受教了~~~很详细啊~~记得你曾帮我解决过Scene_Title的问题~~感激ing~~~这个希望能继续下去,很想看看关于Scene_Battle的剖析~~~~除了场景类还会讲解其他类吗?

我最不熟的就是Scene_Battle,击沉……{/lh}

设想中是以Scene类为主线通读其他的各组,理论上都会说到……(毫无信心地望天)


唔这坑啊……貌似还是有人跳的?那么接下来是Scene_Menu类以及其附属的一大串Scene和Window类,嗯>_<
作者: 颠倒的彩虹    时间: 2007-3-11 08:39
这是给小白看的吗?好象挺对口的..收下了.感激…{/pz}
作者: 美兽    时间: 2007-3-11 15:36
LZ慢慢挖吧,默认脚本有些地方还是相对复杂的,大略扫了一遍

这就不较真了.
拥有类和方法是面向对象语言的一个典型特征


@command_window与@sprite的dispose是不同的.
   @command_window.dispose
   @sprite.dispose


这两句都有些问题
形如@sprite的变量是实例变量(以@开头),它的作用范围限于类的内部,
形如s1的变量是局部变量(小写字母或下划线开头,不能是保留字),它的作用范围限于方法的内部。


这句混淆了true,false与真伪值的概念.
如果一个变量只有真假值时,可以简略的用if @变量名代替if @变量名 == true,用if !@变量名代替if @变量名 == false。


这句话LZ应该找机会再验证下.
一切未经赋值的变量初始值都为nil(并不是0),


作者: 暴风の龙    时间: 2007-3-11 17:58
支持啊,看得我都入迷了
作者: 贺仔    时间: 2007-3-11 18:52
强~!~
比那个F1好多了。。。。。。。
那个都不举这么好的例子。。
挖坑{/gg}
作者: 亿万星辰    时间: 2007-3-11 19:14
如果一个变量只有真假值时,可以简略的用if @变量名代替if @变量名 == true,用if !@变量名代替if @变量名 == false。

这句单从使用方面来说应该没错,我也是一直是这么用的.
作者: 神思    时间: 2007-3-11 19:18
如果一个变量只有真假值时,可以简略的用if @变量名代替if @变量名 == true,用if !@变量名代替if @变量名 == false。


{/gg}
整个结构大概是这样
if(xxx)
如果xxx部分的返回为真则运行if~end部分`````

所以
if(true)
p 'true'
end
if(false)
p 'false'
end
if(true == true)
p 'true'
end
if(false == false)
p 'true'
end

-____-`||所以.......................
作者: 美兽    时间: 2007-3-11 19:42
这就是为什么我说混淆了true,false与真伪值概念的原因

    if @a
       p 'a'
    end
    if !@a
       p 'b'
    end     
    @a = '派阿基亚'
    if @a
       p 'c'
    end

作者: 美兽    时间: 2007-3-11 19:57
实例变量直接有外部访问的方法.
局部变量可以通过闭包在其她地方访问.

大多有标记的变量未声明前初始值为nil,如果声明但没明确初始化RUBY会根据数据类型动态初始化,局部变量不声明或初始化前被当作无参数方法调用.

@command_window的dispose是调用祖父类同名方法将bitmap对象一同释放,而@sprite的dispose的释放仅是精灵,bitmap对象根据情况有可能垃圾回收,这是RUBY语言特有机制,但一般不建议被动的利用垃圾回收,一般生成对象时是很消耗资源,在做STG时用数组当做格纳库,bitmap对象一概不释放,反复重复利用,FPS消耗极低,这就是RM默认高速缓存存在的价值,以及菜单类把dispose放在退出的最后的原因。

作者: 亿万星辰    时间: 2007-3-11 20:27
如果一个变量只有真假值时,可以简略的用if @变量名代替if @变量名 == true,用if !@变量名代替if @变量名 == false。

他是说了是特指一个数字量时......{/fd}
虽然说法不是那么合适.....
作者: 美兽    时间: 2007-3-11 20:38
屏蔽
作者: 亿万星辰    时间: 2007-3-11 20:41
{/hx}这个也不要太要求了,很显然他的意思是
a_switch = true
你就可以通过
if a_switch
  do_something
end
这样的句子来操作
作者: 美兽    时间: 2007-3-11 20:47
以下引用亿万星辰于2007-3-11 12:41:58的发言:

这个也不要太要求了,很显然他的意思是
a_switch = true
你就可以通过
if a_switch
do_something
end
这样的句子来操作


呵呵,只是不清楚LZ是否清楚这个问题,因为这个问题我也是过了很长时间才清楚,不希望别人也走我的弯路,我先屏蔽掉好了。

作者: yinghao2005    时间: 2007-3-11 20:50
我可是脚本盲{/gg},不过看了LZ的讲解觉得心旷神怡,柳暗花明。收藏了
加油!希望能全部讲解一下{/se}
期待!!!

作者: Benavii    时间: 2007-3-12 06:39
以下引用美兽于2007-3-11 7:36:23的发言:

LZ慢慢挖吧,默认脚本有些地方还是相对复杂的,大略扫了一遍


@command_window与@sprite的dispose是不同的.

  @command_window.dispose
  @sprite.dispose
#——这个知道的orz 在此是简单地提醒要释放生成过的对象,还没有想到那么深的地方orz


这两句都有些问题

形如@sprite的变量是实例变量(以@开头),它的作用范围限于类的内部,
形如s1的变量是局部变量(小写字母或下划线开头,不能是保留字),它的作用范围限于方法的内部。

#——谨受教……这个是确实不知道,orz

这句混淆了true,false与真伪值的概念.

如果一个变量只有真假值时,可以简略的用if @变量名代替if @变量名 == true,用if !@变量名代替if @变量名 == false。

#——汗……那句确实没有在说真伪值的问题,偷懒少打了字……
     真伪值的话,false和nil是伪值,其余的都是真值……这样吧{/fd}



这句话LZ应该找机会再验证下.

一切未经赋值的变量初始值都为nil(并不是0),

#——汗,这个确实搞错了,昨天才意识到$game_variables[x]都是0,而$game_swiches[x]初始值都是false。
        然后……额,我那个“初始化”是想表达“声明”的意思orz 术语不过关……

嗯……又学了一些东西,感谢

写这东西的初衷是,让不怎么了解程序的人知道“这个为什么会动,那里怎么会出错,怎样改这东西的位置”这样,达到初步“读懂”的程度,所以很多地方就没想那么深> < (深一些的话更力不从心是事实- -b)  

到头来还是要学一点编程知识才好> <
作者: 六脉神剑    时间: 2007-3-12 19:03
#——汗,这个确实搞错了,昨天才意识到$game_variables[x]都是0,而$game_swiches[x]初始值都是false。

$game_switches和$game_variables在各自的对象类的[]方法中不就被赋值了?{/gg}
作者: 美兽    时间: 2007-3-12 19:40
$game_variables,$game_switches属于重定义的范畴,不算普遍情况。

LZ不必受此影响,我仅是做补充,有些概念实际仅仅是的一句话,我也是花很久才搞清的,只是希望别人不要走我的老路。


作者: 亿万星辰    时间: 2007-3-12 19:46
这个帖子到最后应该会是个能淘到很多东西的地方
作者: 沉默的米饭团    时间: 2007-3-12 22:00
很形象啊
作者: gpra8764    时间: 2007-3-13 02:52
提示: 作者被禁止或删除 内容自动屏蔽
作者: Zeiro    时间: 2007-3-15 02:53
提示: 作者被禁止或删除 内容自动屏蔽
作者: subversion    时间: 2007-3-20 02:31
提示: 作者被禁止或删除 内容自动屏蔽
作者: 叶舞枫    时间: 2007-3-20 03:45
由于制作得非常好,而且很是教程,
贝贝 VIP += 5
{/dy}
作者: 叶舞枫    时间: 2007-3-23 21:17
发布完毕,通知一下。
http://rpg.blue/web/index.htm

贝贝辛苦了~~{/dy}


作者: 精灵使者    时间: 2007-3-24 17:46
原来如此!!谢谢你帮了我改变字体大小的忙!以前的黑体字体太大了看不清楚……多谢!
作者: 猫哥哥    时间: 2007-5-2 09:35
受教了……写得很详细啊……希望LZ能写下去噢{/qiang}
作者: lj6139957    时间: 2007-6-7 03:24
是个好帖子啊....强烈要求LZ多写些这类的帖子啊...不然我们新手都不知道从哪里读起...从哪里学起...谢谢了啊...看懂了
作者: 咖哩猫    时间: 2007-6-12 21:07
非常好的启蒙教材啊,感动~~{/ll}
如果再多写一些就更好了…
作者: libinsf    时间: 2007-6-13 00:14
这样的教程看着让人烦心。不生动。也不活泼。
作者: p7l8k90    时间: 2010-8-27 21:05
回复 Benavii 的帖子

谢谢发言,很多不明白的东西都稍微明白点了,相信一段时间以后坑定能行!
   
作者: zhoubin881224    时间: 2010-8-29 10:42
提示: 作者被禁止或删除 内容自动屏蔽




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