查看: 4973|回复: 7

[原创发布] 【原创】改良存读档系统优化版 Ver 1.2

[复制链接]
梦石
0
星屑
9557
在线时间
5074 小时
注册时间
2013-6-21
回帖
3459

开拓者贵宾剧作品鉴家

发表于 2013-6-21 19:57:18 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 RyanBern 于 2016-3-12 09:45 编辑

不知道有没有人发过类似的东西,不过好歹是原创,拿出来跟大家分享一下。
本脚本适用于RMXP。由于是借助RMXP预置脚本改的,所以应该不会有什么冲突,除非原有的系统被改得面目全非。


这是我刚入住6R时献上的第一个技术贴,不过没什么人气,现在拿出来返工一下。简单优化了一下脚本。
代码如下,有什么BUG欢迎报告:
[pre lang="Ruby"]#=============================================================================
# 改良存读档优化版 Ver 1.21
#-----------------------------------------------------------------------------
# By : RyanBern
#-----------------------------------------------------------------------------
# 功能说明:
#     在原始的存读档系统上做了一些加强,提供了一些扩展内容,界面比较简单,可以
#     试着在游戏中使用。
#     1.屏蔽了 Window_SaveFile,而选择了可以滚动的 Window_Selectable,存档数量
#       想存多少就存多少。
#     2.自动存档功能,这个是为一些没有存档意识的玩家写的系统,有了它系统就可以
#       按照一定规律自动保存进度,再也不用担心进度丢失了。存档的时机为主角切换
#       到另一个地图之后,可以通过更改下面的常量来控制。
#     3.存档覆盖提示功能,这个也是为一些粗心玩家设定的系统,当存储的位置已经有
#       了文件时,再存档会跳出覆盖提示,避免误操作。
#-----------------------------------------------------------------------------
# 另外里面的 Window_Selectable 是我扩展的内容,可以单独拿出来使用,扩展的功能
# 是可以指定每一行的行高,这样 Window_Selectable 滚动内容的行高就可以不必限制
# 为 32 了。
#-----------------------------------------------------------------------------
# 更新记录:
#     2014.12.25  精简代码,修复多了 end 的 BUG
#     2016.03.12  缓解 F12 冲突的问题
#=============================================================================
module RB
  # 存档数最大值
  SAVES_MAX = 20
  
  # 如果打开12号开关,将不会自动存档
  NO_AUTOSAVE = 12
  
  # 禁止自动存档的地图ID数组,如果主角移动前的地图的ID在数组中
  # 那么切换地图后将不会自动存档
  NO_AUTOSAVE_MAPS = []
end

#=============================================================================
# ■ Window_Selectable
#-----------------------------------------------------------------------------
#  拥有光标的移动以及滚动功能的窗口类。
#   RB 加强版,可以设定一行的高度
#   指定某一行的高度可以这样 Window_Selectable.new(0, 0, 120, 120, 54)
#   表示该窗口一行高度为 54,如果不写,默认为 32(原始默认高度)
#=============================================================================

class Window_Selectable < Window_Base
  #--------------------------------------------------------------------------
  # ● 定义实例变量
  #--------------------------------------------------------------------------
  attr_reader   :index                    # 光标位置
  attr_reader   :help_window              # 帮助窗口
  attr_accessor :row_height               # 行高
  #--------------------------------------------------------------------------
  # ● 初始画对像
  #     x      : 窗口的 X 坐标
  #     y      : 窗口的 Y 坐标
  #     width  : 窗口的宽
  #     height : 窗口的高
  #--------------------------------------------------------------------------
  def initialize(x, y, width, height, row_height=32)
    super(x, y, width, height)
    @item_max = 1
    @column_max = 1
    @index = -1
    @row_height = row_height
  end
  #--------------------------------------------------------------------------
  # ● 获取开头行
  #--------------------------------------------------------------------------
  def top_row
    # 将窗口内容的传送源 Y 坐标、1 行的高 @row_height 等分
    return self.oy / @row_height
  end
  #--------------------------------------------------------------------------
  # ● 设置开头行
  #     row : 显示开头的行
  #--------------------------------------------------------------------------
  def top_row=(row)
    # row 未满 0 的场合更正为 0
    if row < 0
      row = 0
    end
    # row 超过 row_max - 1 的情况下更正为 row_max - 1
    if row > row_max - 1
      row = row_max - 1
    end
    # row 1 行高的 @row_height 倍、窗口内容的传送源 Y 坐标
    self.oy = row * @row_height
  end
  #--------------------------------------------------------------------------
  # ● 获取 1 页可以显示的行数
  #--------------------------------------------------------------------------
  def page_row_max
    # 窗口的高度,设置画面的高度减去 32 ,除以 1 行的高度 @row_height
    return (self.height - 32) / @row_height
  end
  #--------------------------------------------------------------------------
  # ● 更新光标矩形
  #--------------------------------------------------------------------------
  def update_cursor_rect
    # 光标位置不满 0 的情况下
    if @index < 0
      self.cursor_rect.empty
      return
    end
    # 获取当前的行
    row = @index / @column_max
    # 当前行被显示开头行前面的情况下
    if row < self.top_row
      # 从当前行向开头行滚动
      self.top_row = row
    end
    # 当前行被显示末尾行之后的情况下
    if row > self.top_row + (self.page_row_max - 1)
      # 从当前行向末尾滚动
      self.top_row = row - (self.page_row_max - 1)
    end
    # 计算光标的宽
    cursor_width = self.width / @column_max - 32
    # 计算光标坐标
    x = @index % @column_max * (cursor_width + 32)
    y = @index / @column_max * @row_height - self.oy
    # 更新光标矩形
    self.cursor_rect.set(x, y, cursor_width, @row_height)
  end
end
class Window_File < Window_Selectable
  #--------------------------------------------------------------------------
  # ● 初始化目标
  #--------------------------------------------------------------------------
  def initialize
    super(0, 64, 640, 416 ,96)
    @column_max = 1
    case $scene
    when Scene_Save
      @item_max = RB::SAVES_MAX
    when Scene_Load
      @item_max = RB::SAVES_MAX + 1
    end
    refresh
    self.index = 0
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    if @item_max == 0
      return
    end
    self.contents = Bitmap.new(width - 32, @item_max * 96)
    self.contents.clear
    for j in 0...@item_max
      x = 64
      y = j * 96
      self.contents.font.color = normal_color
      case $scene
      when Scene_Save
      name = "文件 #{j + 1}"
      self.contents.draw_text(4, y, 600, 32, name)
      @filename = "Save#{j + 1}.rxdata"
      @name_width = contents.text_size(name).width
      @time_stamp = Time.at(0)
      @file_exist = FileTest.exist?(@filename)
      when Scene_Load
        if j == 0
          name = "自动存档"
        else
          name = "文件 #{j}"
        end
        self.contents.draw_text(4, y, 600, 32, name)
      @filename = "Save#{j}.rxdata"
      @name_width = contents.text_size(name).width
      @time_stamp = Time.at(0)
      @file_exist = FileTest.exist?(@filename)
      end
      if @file_exist
        file = File.open(@filename, "r")
        @time_stamp = file.mtime
        @characters = Marshal.load(file)
        @frame_count = Marshal.load(file)
        @game_system = Marshal.load(file)
        @game_switches = Marshal.load(file)
        @game_variables = Marshal.load(file)
        @total_sec = @frame_count / Graphics.frame_rate
        file.close
      end
      # 存档文件存在的情况下
      if @file_exist
        # 描绘角色
        for i in 0...@characters.size
          bitmap = RPG::Cache.character(@characters[0], @characters[1])
          cw = bitmap.rect.width / 4
          ch = bitmap.rect.height / 4
          src_rect = Rect.new(0, 0, cw, ch)
          x = 300 - @characters.size * 32 + i * 64 - cw / 2
          self.contents.blt(x, 68 - ch + y, bitmap, src_rect)
        end
        # 描绘游戏时间
        hour = @total_sec / 60 / 60
        min = @total_sec / 60 % 60
        sec = @total_sec % 60
        time_string = sprintf("%02d:%02d:%02d", hour, min, sec)
        self.contents.font.color = normal_color
        self.contents.draw_text(4, 8 + y, 600, 32, time_string, 2)
        # 描绘时间标记
        self.contents.font.color = normal_color
        time_string = @time_stamp.strftime("%Y/%m/%d %H:%M")
        self.contents.draw_text(4, 40 + y, 600, 32, time_string, 2)
      end
    end
  end
end
#==============================================================================
# ■ Window_ReplaceConfirm
#------------------------------------------------------------------------------
#  确认是否覆盖原始存档的窗口
#==============================================================================

class Window_ReplaceConfirm < Window_Selectable
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    super(160, 176, 320, 128)
    self.contents = Bitmap.new(width - 32, height - 32)
    @item_max = 2
    @column_max = 2
    @commands = ["是的",  "不要"]
    refresh
    self.index = 0
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    self.contents.clear
    self.contents.font.color = system_color
    self.contents.draw_text(4, 0, 328, 32, "当前位置已经存在存档文件")
    self.contents.draw_text(4, 32, 328, 32, "确认要覆盖当前存档文件吗?")
    self.contents.font.color = normal_color
    for i in 0...@item_max
      draw_item(i)
    end
  end
  #--------------------------------------------------------------------------
  # ● 描绘项目
  #     index : 项目编号
  #--------------------------------------------------------------------------
  def draw_item(index)
    x = 4 + index * 144
    self.contents.draw_text(x, 64, 128, 32, @commands[index])
  end
  def update_cursor_rect
    if @index < 0
      self.cursor_rect.empty
    else
      self.cursor_rect.set(@index * 144, 64, (self.width - 32) / 2, 32)
    end
  end
end
#==============================================================================
# ■ Scene_File
#------------------------------------------------------------------------------
#  存档画面及读档画面的超级类。
#==============================================================================

class Scene_File
  #--------------------------------------------------------------------------
  # ● 主处理
  #--------------------------------------------------------------------------
  def main
    # 生成帮助窗口
    @help_window = Window_Help.new
    @help_window.set_text(@help_text)
    @file_window = Window_File.new
    @file_window.index = $game_temp.last_file_index
    @file_window.active = true
    @confirm_window = Window_ReplaceConfirm.new
    @confirm_window.active = false
    @confirm_window.visible = false
    @confirm_window.z = @file_window.z + 10
    # 执行过渡
    Graphics.transition
    # 主循环
    loop do
      # 刷新游戏画面
      Graphics.update
      # 刷新输入信息
      Input.update
      # 刷新画面
      update
      # 如果画面被切换的话就中断循环
      if $scene != self
        break
      end
    end
    # 准备过渡
    Graphics.freeze
    # 释放窗口
    @help_window.dispose
    @file_window.dispose
    @confirm_window.dispose
  end
  #--------------------------------------------------------------------------
  # ● 刷新画面
  #--------------------------------------------------------------------------
  def update
    # 刷新窗口
    @help_window.update
    @file_window.update
    @confirm_window.update
    case $scene
    when Scene_Save
      if @file_window.active
        update_file
        return
      end
      if @confirm_window.active
        update_confirm
        return
      end
    when Scene_Load
      # 按下 C 键的情况下
      if Input.trigger?(Input::C)
        # 调用过程 on_decision (定义继承目标)
        on_decision(make_filename_load(@file_window.index))
        $game_temp.last_file_index = @file_window.index
        return
      end
      # 按下 B 键的情况下
      if Input.trigger?(Input::B)
        # 调用过程 on_cancel (定义继承目标)
        on_cancel
        return
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● 生成文件名
  #     file_index : 文件名的索引 (0~3)
  #--------------------------------------------------------------------------
  def make_filename(file_index)
    return "Save#{file_index + 1}.rxdata"
  end
  def make_filename_load(file_index)
    return "Save#{file_index}.rxdata"
  end
end


class Scene_Save < Scene_File
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    super("要储存到哪个文件?")
  end
  def update_file
    filename = make_filename(@file_window.index)
    if Input.trigger?(Input::C)
      $game_system.se_play($data_system.decision_se)
      if FileTest.exist?(filename)
        @file_window.active = false
        @confirm_window.active = true
        @confirm_window.visible = true
      else
        # 演奏存档 SE
        $game_system.se_play($data_system.save_se)
        # 写入存档数据
        file = File.open(filename, "wb")
        write_save_data(file)
        file.close
        # 如果被事件调用
        if $game_temp.save_calling
          # 清除存档调用标志
          $game_temp.save_calling = false
          # 切换到地图画面
          $scene = Scene_Map.new
          return
        end
        # 切换到菜单画面
        $scene = Scene_Menu.new(4)
      end
    end
    if Input.trigger?(Input::B)
      # 演奏取消 SE
      $game_system.se_play($data_system.cancel_se)
      # 如果被事件调用
      if $game_temp.save_calling
        # 清除存档调用标志
        $game_temp.save_calling = false
        # 切换到地图画面
        $scene = Scene_Map.new
        return
      end
      # 切换到菜单画面
      $scene = Scene_Menu.new(4)
    end
  end
  def update_confirm
    filename = make_filename(@file_window.index)
    if Input.trigger?(Input::C)
      case @confirm_window.index
      when 0
        # 演奏存档 SE
        $game_system.se_play($data_system.save_se)
        # 写入存档数据
        file = File.open(filename, "wb")
        write_save_data(file)
        file.close
        # 如果被事件调用
        if $game_temp.save_calling
          # 清除存档调用标志
          $game_temp.save_calling = false
          # 切换到地图画面
          $scene = Scene_Map.new
          return
        end
        # 切换到菜单画面
        $scene = Scene_Menu.new(4)
      when 1
        $game_system.se_play($data_system.cancel_se)
        @file_window.active = true
        @confirm_window.active = false
        @confirm_window.visible = false
      end
    end
    if Input.trigger?(Input::B)
      $game_system.se_play($data_system.cancel_se)
      @file_window.active = true
      @confirm_window.active = false
      @confirm_window.visible = false
    end
  end
  def autosave
    filename = "Save0.rxdata"
    file = File.open(filename, "wb")
    write_save_data(file)
    file.close
  end
end


class Scene_Load < Scene_File
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    # 再生成临时对像
    $game_temp = Game_Temp.new
    # 选择存档时间最新的文件
    $game_temp.last_file_index = 0
    latest_time = Time.at(0)
    for i in 0..RB::SAVES_MAX
      filename = make_filename_load(i)
      if FileTest.exist?(filename)
        file = File.open(filename, "r")
        if file.mtime > latest_time
          latest_time = file.mtime
          $game_temp.last_file_index = i
        end
        file.close
      end
    end
    super("要载入哪个文件?")
  end
end

class Scene_Map
  unless method_defined? :rb_transfer_player_20141225
    alias rb_transfer_player_20141225 transfer_player
    def transfer_player
      rb_transfer_player_20141225
      unless RB::NO_AUTOSAVE_MAPS.include?($game_map.map_id) || $game_switches[RB::NO_AUTOSAVE]
        save = Scene_Save.new
        save.autosave
      end
    end
  end
end
[/pre]
附范例一枚:
Project5.rar (190.96 KB, 下载次数: 221)
注意有几个地方,我不知道该怎么标注,大家注意Scene_Save里面返回上一级的命令$scene = Scene_Menu.new(x),不同人的菜单不一样的,如果改过Scene_Menu的同学还请注意一下括号里面的数字。

点评

无图无真相  发表于 2013-7-28 19:59

评分

参与人数 1星屑 +6 收起 理由
龙和许也 + 6 塞糖

查看全部评分

梦石
0
星屑
1556
在线时间
626 小时
注册时间
2010-8-5
回帖
317
发表于 2013-7-28 19:44:54 | 显示全部楼层
这么好的帖子为啥没人呢.~~~占个沙发{:2_287:}
回复

使用道具 举报

梦石
0
星屑
130
在线时间
1 小时
注册时间
2013-7-30
回帖
2
发表于 2013-7-30 15:25:31 | 显示全部楼层
在下新手,受教了。

——新手玩家
回复

使用道具 举报

梦石
0
星屑
50
在线时间
11 小时
注册时间
2013-8-2
回帖
11
发表于 2013-8-2 16:33:30 | 显示全部楼层
好像不错个说,试试看
回复

使用道具 举报

梦石
0
星屑
50
在线时间
169 小时
注册时间
2010-7-7
回帖
38
发表于 2013-8-3 09:51:28 | 显示全部楼层
652行是不是多了一个end啊,有错误啊,删掉后可用
回复

使用道具 举报

梦石
0
星屑
9557
在线时间
5074 小时
注册时间
2013-6-21
回帖
3459

开拓者贵宾剧作品鉴家

 楼主| 发表于 2014-12-25 18:59:10 | 显示全部楼层
1.20版本更新,自顶一下。
主要更新的是修复了一些错误,另外精简了一些代码。
功能还是原来的
回复

使用道具 举报

梦石
0
星屑
9292
在线时间
2504 小时
注册时间
2011-5-20
回帖
14521

开拓者

发表于 2014-12-25 19:21:18 | 显示全部楼层
RyanBern 发表于 2014-12-25 01:59
1.20版本更新,自顶一下。
主要更新的是修复了一些错误,另外精简了一些代码。
功能还是原来的 ...

来个通用版吧(···这是在做什么···)
[img]http://service.t.sina.com.cn/widget/qmd/5339802982/c02e16bd/7.png
回复

使用道具 举报

梦石
0
星屑
287
在线时间
1580 小时
注册时间
2010-6-17
回帖
2818

开拓者贵宾

发表于 2017-2-1 12:27:57 | 显示全部楼层
要是想显示小截图怎么做啊?
快来点我一下,你会豁然开朗的
喵Kano特制
←开发中……

←暂时弃坑 电脑上资源全没
回复

使用道具 举报

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

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部