Project1

标题: [简单脚本]声望窗口 [打印本页]

作者: timiesea    时间: 2014-1-1 15:30
标题: [简单脚本]声望窗口
  呵呵!一开始接触脚本就停不下脚步了,该说什么好呢?
  不得不说Ruby的语法实在太奇怪了。写法很自由,当然这样子的优点就是可以节省时间,提高效率,不过我觉得缺点就是可读性差。
  以上是我这两天入门脚本的一些心得。

  昨天实践了Ruby的基本语法,今天我们来看看跟Ruby语法不相干的内容。


  这个脚本所实现的功能如下:


  在菜单界面显示一个窗口,用来显示声望以及数值。
  声望数值在本例中用第15号变量表示:$game_variables[15]

  我就把实现这个功能的过程中,我脑袋所想的告诉大家。

1.我要实现一个窗口用来显示声望值。这个窗口非常简单,不要求任何的功能。凭空写一个的话对于新手来说是比较困难的,我们不妨参照默认脚本中已经存在的脚本进行修改,于是我看到了Window_Gold类。这个类是用来显示金钱的,也没有任何功能,拿来修改是再好不过了。

2.在main前面插入一个空的脚本,将Window_Gold类全部复制过来并且改名字。在本例中,声望窗口的名字为Window_Prestige。然后我们看看已经存在的方法,有哪些是有用的,有哪些是没用的,又有哪些是需要修改的:
    initialize:这个是窗口类的初始化方法。这个方法至关重要,所以不能删除,在本例中也没有进行修改。
    window_width:获取该窗口宽度的方法。由于声望窗口和金钱窗口的宽度是一致的,所以不用修改。
    refresh:刷新方法。这个方法至关重要,不能删除,但是可以修改。如果没有刷新方法,则即使数值改变,界面也不会体现,甚至不会有内容被绘制。
    value:获取金钱数目的方法。这个方法也很重要,稍作修改后可以实现获取声望的效果,不建议删除。
    currency_unit:获取金钱单位的方法。这个方法不重要,在本例中删除了。如果你的游戏中声望是有单位的,我建议在value方法里面进行实现。
    open:打开窗口方法。这个方法至关重要,不能删除,在当前状态下最好也别修改。

3.确定了Window_Gold类每个方法的功能后就可以开始进行修改了。从第一个方法开始:
@initialize
默认脚本如下:
RUBY 代码复制
  1. def initialize
  2.     super(0, 0, window_width, fitting_height(1))
  3.     refresh
  4. end

super:调用父类中的initialize方法并且传入一些参数。在父类(Window_Base)中,该方法的参数列表如下:(x, y, width, height)。传入的参数的含义如下:(x坐标,y坐标,该窗口宽度,当文字只有一行时该窗口的高度)。
refresh:调用这个类的refresh方法。
  可以看出这个initialize方法是不需要做任何修改的,因为该窗口的文字也是只有一行,所以高度和Window_Gold是一样的,而x坐标,y坐标,和窗口宽度也是和Window_Gold一样的。至于x坐标,y坐标是以哪个坐标系为参照物,我目前的理解如下,可能和实际有一些误差:窗口有一个载体,就好比是一个正方形箱子,我们把窗口看成正方形的木块什么的,故x坐标和y坐标就表示我们要将这个木块放置在这个箱子的位置,当然默认是放置在箱子的左上角以免造成空间浪费。而width和height就表示这个木块的大小。

@window_width
默认脚本如下:
RUBY 代码复制
  1. def window_width
  2.     return 160
  3.   end

  return 160表示这个窗口的宽度是160,这个160包括可以看到的声望窗口的全部内容的宽度,包括白色边框。
  由于声望窗口的宽度和Window_Gold是一样的,所以这个方法也不用修改。

@refresh
默认脚本如下:
RUBY 代码复制
  1. def refresh
  2.     contents.clear
  3.     draw_currency_value(value, currency_unit, 4, 0, contents.width - 8)
  4.   end

  contents.clear:清除前一刻绘制的内容。这个contents在F1里面描述如下:引用作为窗口内容的位图。我的理解是:窗口本身。在刚才,我们把窗口看成是一个木块。很显然,要显示的东西(金钱,声望)就相当于用笔写在这一个木块上。所以大家还可以把contents理解为一个画板,一个和木块同样的画板。clear方法就是清除画板上的所有内容。如果不清除的话,新画上去的东西会和原来的进行重叠。
  draw_currency_value:这个方法在父类(Window_Base)中,意思是绘制当前的金钱数目和金钱单位。参数列表是:(value, unit, x, y, width),实际传入的参数如下:(金钱数目,金钱单位,绘制x坐标,绘制y坐标,绘制的宽度)。
  由默认脚本可知,这个refresh方法是用来绘制的,也就是说每一次调用refresh就会绘制一遍(事先清除)。由于《RMVA》的帧数太高了,所以我们感觉好像一直都显示在屏幕上,如果帧数低一点大家可以发现这个窗口是一闪一闪的。
  好!那么明白refresh方法的用途后我们就明白了,很显然默认脚本的内容不是我们想要的。开始修改吧。

第一:把draw_currency_value(value, currency_unit, 4, 0, contents.width - 8)这一行注释。因为我们不需要它。

第二:绘制“声望”二字。
  在本例中,声望二字的颜色采用的是系统颜色(蓝色),所以我们在绘制前应该先把颜色设置一下。在Window_Base找到draw_currency_value方法我们就很容易发现设置颜色的语句:change_color(system_color)。
  然后开始绘制“声望”二字,同样是在Window_Base找到draw_currency_value方法,我们发现有一个draw_text的方法。这个方法在Window_Base里的内容如下:
RUBY 代码复制
  1. def draw_text(*args)
  2.     contents.draw_text(*args)
  3. end

  好,contents到底是什么东西?我们还得通过F1来获取答案。经过一番搜索,我发现contents在RGSS参考手册-游戏函数库-RGSS内建内-Window 窗口类中,是一个属性(描述:引用作为窗口内容的位图(Bitmap 位图类 ))。而draw_text正是这个属性的方法,位于同一个路径下的Bitmap 位图类。该方法的参数列表如下:(x, y, width, height, str[, align]) 分别代表如下含义(绘制的x坐标,绘制的y坐标,绘制的宽度,绘制的高度,绘制的内容,对齐方式(可以省略))。对于这个方法,我是这么理解的:箱子里有一个木块,木块上要写字,而写之前得先确定范围。当然,我们平时写字的时候在潜意识中已经确定好了范围,所以会出现一行写不下故意写得很挤的情况。计算机同理的,它也需要知道这个字要在木块的哪一个区域里写。如果内容太多当然就写不下。而对齐方式主要有以下几种情况:1:居中对齐;2:右对齐;默认:左对齐。如果省略这个参数则采用左对齐。
  理解了draw_text的用法后我们就开始绘制“声望”吧:draw_text(0, 0, contents.width - 8, line_height, "声望");这里我省略了对齐方式,所以默认是左对齐。那么这个脚本的意思如下:在窗口的(0,0)坐标上,绘制“声望”二字。这两个字的最大宽度不得超过窗口宽度的-8像素,最大高度不得超过一行文字的高度。我这么说大家可理解?

第三:绘制声望数值。
  在绘制之前要注意,在刚才已经把绘制的颜色变成system_color了,如果不再一次改变颜色的话,声望数值的颜色就会和“声望”文字的颜色一致,显得不美观。所以我们还需要改变一次颜色:change_color(normal_color)。
  改变好颜色后我们再来绘制:draw_text(0,0,contents.width - 8,line_height,value,2)。这条语句的含义和绘制声望文字的含义是一样的,只是多加了一个参数,表示右对齐。如果不加,则声望数值会覆盖在声望文字上。因为两个绘制区域是重叠的,而对齐方式也是一样的,所以就会重叠在一起。
  经过漫长的探索,已经绘制好了内容,但远远不够。我们继续。

@value
默认脚本如下:
RUBY 代码复制
  1. def value
  2.     $game_party.gold
  3. end

  $game_party是一个实例(全局变量),存储的是队伍的各种信息,可以在默认脚本的Game_Party类中找到其定义。当然,这部分内容不在本帖的讨论范围内。gold是一个变量,存储队伍的金钱数目。
  那么很显然,这个方法的内容不是我们想要的,把$game_party.gold注释。然后,在本例中,声望的数值是用第15号变量来保存的,所以应该写:return $game_variables[15]。也可以省略return。
  如果你的游戏中声望是有单位的,例如单位是:个。那么这么写:return $game_variables[15].to_s + "个";由于“个”是个字符串,而$game_variables[15]是一个数字。我们必须先将数字转化为字符串,然后再跟“个”进行相加,就可以得到比如以下效果:15个,否则运行会出错。至于to_s,可以在F1的RGSS参考手册-Ruby语法-标准函数库-内建类-Numeric 数字类-Integer 整数类中找到,是一个方法。

@currency_unit
默认脚本如下:
RUBY 代码复制
  1. def currency_unit
  2.     Vocab::currency_unit
  3. end

  Vocab就在默认脚本中,就是第一个,是一个模块。而currency_unit则表示Vocab中的方法。用来获取数据库设定的金钱的单位。
  那么对于无单位的声望,这个方法就可以完全注释不用了。有单位的声望也不用这个。

@open
默认脚本如下:
RUBY 代码复制
  1. def open
  2.     refresh
  3.     super
  4. end

  refresh:调用该类的refresh方法。这个方法刚才我们已经修改了,用来绘制声望文字和声望数字。所以这条语句不可变更。
  super:调用父类(Window_Base)的同名方法(open),是用来打开窗口的。跟update有关,不在本文的讨论范围内,可以保留也可以删除。

4.直到目前为止,总算把Window_Gold类的所有方法都按照我们的意愿修改完毕了,但是还远远不够。我们只是定义了这么一个窗口类,还没有对它进行实例化,没有对它进行显示什么的。那么开始吧。先是实例化。以Window_Gold类为例。找到其实例化的地方,位于Scene_Menu类的create_gold_window方法,然后Scene_Menu的start方法调用create_gold_window来实现实例化。我们依葫芦画瓢,在Scene_Menu类中新建一个方法:create_prestige_window。里面需要定义以下信息:实例化,x坐标,y坐标。
create_gold_window方法默认脚本如下:
RUBY 代码复制
  1. def create_gold_window
  2.     @gold_window = Window_Gold.new
  3.     @gold_window.x = 0
  4.     @gold_window.y = Graphics.height - @gold_window.height
  5. end

  @gold_window是一个成员变量,我们的声望窗口也需要一个,就命名为@prestige_window。
  @gold_window = Window_Gold.new:进行金钱窗口的实例化。仿照这条语句的写法,声望窗口的实例化就为:@prestige_window = Window_Prestige.new。当进行实例化时,就会调用Window_Prestige类的initialize方法。
  @gold_window.x = 0:金钱窗口x坐标。声望窗口也是0,所以:@prestige_window.x = 0。0表示紧挨着游戏窗口的左侧。
  @gold_window.y = Graphics.height - @gold_window.height:金钱窗口的y坐标。由于金钱窗口紧挨着游戏窗口的下方,所以其计算的方法就是窗体高度减去金钱窗口的高度。而声望窗口又是紧挨着金钱窗口,所以我们还要减去声望窗口的高度:@prestige_window.y = Graphics.height - @gold_window.height - @prestige_window.height。Graphics的定义可以在F1中找到。height是一个方法,用来获取游戏窗口的高度,一般而言是416。

5.实例化的方法写好后,我们就在Scene_Menu的start方法加一句:create_prestige_window。
start经过修改的脚本如下:
RUBY 代码复制
  1. def start
  2.     super
  3.     create_command_window
  4.     create_gold_window
  5.     create_status_window
  6.     create_prestige_window#新加的
  7. end


6.好!到目前为止,已经全部完成了。赶紧进游戏看看效果吧。

以下是脚本:
RUBY 代码复制
  1. #这是一个在主菜单显示声望的窗口类
  2. #encoding:utf-8
  3. #==============================================================================
  4. # ■ Window_Prestige
  5. #------------------------------------------------------------------------------
  6. #  显示声望的窗口
  7. #==============================================================================
  8.  
  9. class Window_Prestige < Window_Base
  10.   #--------------------------------------------------------------------------
  11.   # ● 初始化对象
  12.   #--------------------------------------------------------------------------
  13.   def initialize
  14.     super(0, 0, window_width, fitting_height(1))
  15.     refresh
  16.   end
  17.   #--------------------------------------------------------------------------
  18.   # ● 获取窗口的宽度
  19.   #--------------------------------------------------------------------------
  20.   def window_width
  21.     return 160
  22.   end
  23.   #--------------------------------------------------------------------------
  24.   # ● 刷新(在这里绘制内容)
  25.   #--------------------------------------------------------------------------
  26.   def refresh
  27.     contents.clear#清除刚刚绘制的内容,以免造成内容重叠
  28.     change_color(system_color)#改变绘制颜色为system_color(蓝色)
  29.     #开始绘制“声望”二字,参数(x,y,w,h,v)
  30.     #含义:
  31.     #x:绘制内容的x坐标,相对于这个窗体
  32.     #y:绘制内容的y坐标,相对于这个窗体
  33.     #w:绘制内容的宽度,过短会显示不全
  34.     #h:绘制内容的高度,同上
  35.     #v:绘制的内容
  36.     #int:对齐方式,1:居中;2:右对齐。省略:左对齐。
  37.     draw_text(0, 0, contents.width - 8, line_height, "声望");
  38.     change_color(normal_color);#改变绘制颜色为普通白色
  39.     #开始绘制声望数值
  40.     #line_height:位于父类中,表示一行文字占用的高度
  41.     draw_text(0,0,contents.width - 8,line_height,value,2);
  42.   end
  43.   #--------------------------------------------------------------------------
  44.   # ● 获取声望
  45.   #--------------------------------------------------------------------------
  46.   def value
  47.     return $game_variables[15];
  48.   end
  49.   #--------------------------------------------------------------------------
  50.   # ● 打开窗口
  51.   #--------------------------------------------------------------------------
  52.   def open
  53.     refresh
  54.     super
  55.   end
  56. end


RUBY 代码复制
  1. class Scene_Menu < Scene_MenuBase
  2.   #--------------------------------------------------------------------------
  3.   # ● 开始处理
  4.   #--------------------------------------------------------------------------
  5.   alias start_old start;
  6.   def start
  7.     super
  8.     create_command_window
  9.     create_gold_window
  10.     create_status_window
  11.     create_prestige_window
  12.   end
  13.   #--------------------------------------------------------------------------
  14.   # ● 生成声望窗口
  15.   #--------------------------------------------------------------------------
  16.   def create_prestige_window
  17.     @prestige_window = Window_Prestige.new
  18.     @prestige_window.x = 0
  19.     @prestige_window.y = Graphics.height - @gold_window.height - @prestige_window.height
  20.   end
  21. end


将以上2段脚本分别插入到main前面就可以实现功能了。效果在帖子的上方。

注:alias start_old start:表示将一个旧方法重新命名。格式如下:alias 新方法名称 旧方法名称。这样做的好处是避免脚本冲突。

呼!终于写完了。我自己都觉得很啰嗦。不过既然是类似于教程心得之类的东西,当然不能只贴脚本了事。详细的说明和思路还是很有必要的。因为我还是新人,所以也欢迎各位提出建议或者意见。
作者: 三月青梅    时间: 2014-1-9 14:54

作者: 上贺茂润    时间: 2014-1-9 15:25
有VX的吗?还有,LS存图片作死




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