查看: 92|回复: 0

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

[复制链接]
  • TA的每日心情
    开心
    4 天前
  • 签到天数: 37 天

    连续签到: 3 天

    [LV.5]常住居民I

    2028

    主题

    32

    回帖

    7260

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    VIP
    0
    卡币
    5184
    OK点
    16
    积分
    7260
    发表于 同元一千年八月七日(秋) | 显示全部楼层 |阅读模式
    不知道有没有人发过类似的东西,不过好歹是原创,拿出来跟大家分享一下。
    本脚本适用于RMXP。由于是借助RMXP预置脚本改的,所以应该不会有什么冲突,除非原有的系统被改得面目全非。


    这是我刚入住6R时献上的第一个技术贴,不过没什么人气,现在拿出来返工一下。简单优化了一下脚本。
    代码如下,有什么BUG欢迎报告:
    RUBY 代码
    1. #=============================================================================
    2. # 改良存读档优化版 Ver 1.21
    3. #-----------------------------------------------------------------------------
    4. # By : RyanBern
    5. #-----------------------------------------------------------------------------
    6. # 功能说明:
    7. #     在原始的存读档系统上做了一些加强,提供了一些扩展内容,界面比较简单,可以
    8. #     试着在游戏中使用。
    9. #     1.屏蔽了 Window_SaveFile,而选择了可以滚动的 Window_Selectable,存档数量
    10. #       想存多少就存多少。
    11. #     2.自动存档功能,这个是为一些没有存档意识的玩家写的系统,有了它系统就可以
    12. #       按照一定规律自动保存进度,再也不用担心进度丢失了。存档的时机为主角切换
    13. #       到另一个地图之后,可以通过更改下面的常量来控制。
    14. #     3.存档覆盖提示功能,这个也是为一些粗心玩家设定的系统,当存储的位置已经有
    15. #       了文件时,再存档会跳出覆盖提示,避免误操作。
    16. #-----------------------------------------------------------------------------
    17. # 另外里面的 Window_Selectable 是我扩展的内容,可以单独拿出来使用,扩展的功能
    18. # 是可以指定每一行的行高,这样 Window_Selectable 滚动内容的行高就可以不必限制
    19. # 为 32 了。
    20. #-----------------------------------------------------------------------------
    21. # 更新记录:
    22. #     2014.12.25  精简代码,修复多了 end 的 BUG
    23. #     2016.03.12  缓解 F12 冲突的问题
    24. #=============================================================================
    25. module RB
    26.   # 存档数最大值
    27.   SAVES_MAX = 20
    28.   # 如果打开12号开关,将不会自动存档
    29.   NO_AUTOSAVE = 12
    30.   # 禁止自动存档的地图ID数组,如果主角移动前的地图的ID在数组中
    31.   # 那么切换地图后将不会自动存档
    32.   NO_AUTOSAVE_MAPS = []
    33. end
    34. #=============================================================================
    35. # ■ Window_Selectable
    36. #-----------------------------------------------------------------------------
    37. #  拥有光标的移动以及滚动功能的窗口类。
    38. #   RB 加强版,可以设定一行的高度
    39. #   指定某一行的高度可以这样 Window_Selectable.new(0, 0, 120, 120, 54)
    40. #   表示该窗口一行高度为 54,如果不写,默认为 32(原始默认高度)
    41. #=============================================================================
    42. class Window_Selectable < Window_Base
    43.   #--------------------------------------------------------------------------
    44.   # ● 定义实例变量
    45.   #--------------------------------------------------------------------------
    46.   attr_reader   :index                    # 光标位置
    47.   attr_reader   :help_window              # 帮助窗口
    48.   attr_accessor :row_height               # 行高
    49.   #--------------------------------------------------------------------------
    50.   # ● 初始画对像
    51.   #     x      : 窗口的 X 坐标
    52.   #     y      : 窗口的 Y 坐标
    53.   #     width  : 窗口的宽
    54.   #     height : 窗口的高
    55.   #--------------------------------------------------------------------------
    56.   def initialize(x, y, width, height, row_height=32)
    57.     super(x, y, width, height)
    58.     @item_max = 1
    59.     @column_max = 1
    60.     @index = -1
    61.     @row_height = row_height
    62.   end
    63.   #--------------------------------------------------------------------------
    64.   # ● 获取开头行
    65.   #--------------------------------------------------------------------------
    66.   def top_row
    67.     # 将窗口内容的传送源 Y 坐标、1 行的高 @row_height 等分
    68.     returnself.oy / @row_height
    69.   end
    70.   #--------------------------------------------------------------------------
    71.   # ● 设置开头行
    72.   #     row : 显示开头的行
    73.   #--------------------------------------------------------------------------
    74.   def top_row=(row)
    75.     # row 未满 0 的场合更正为 0
    76.     if row < 0
    77.       row = 0
    78.     end
    79.     # row 超过 row_max - 1 的情况下更正为 row_max - 1
    80.     if row > row_max - 1
    81.       row = row_max - 1
    82.     end
    83.     # row 1 行高的 @row_height 倍、窗口内容的传送源 Y 坐标
    84.     self.oy = row * @row_height
    85.   end
    86.   #--------------------------------------------------------------------------
    87.   # ● 获取 1 页可以显示的行数
    88.   #--------------------------------------------------------------------------
    89.   def page_row_max
    90.     # 窗口的高度,设置画面的高度减去 32 ,除以 1 行的高度 @row_height
    91.     return(self.height - 32) / @row_height
    92.   end
    93.   #--------------------------------------------------------------------------
    94.   # ● 更新光标矩形
    95.   #--------------------------------------------------------------------------
    96.   def update_cursor_rect
    97.     # 光标位置不满 0 的情况下
    98.     if@index < 0
    99.       self.cursor_rect.empty
    100.       return
    101.     end
    102.     # 获取当前的行
    103.     row = @index / @column_max
    104.     # 当前行被显示开头行前面的情况下
    105.     if row < self.top_row
    106.       # 从当前行向开头行滚动
    107.       self.top_row = row
    108.     end
    109.     # 当前行被显示末尾行之后的情况下
    110.     if row > self.top_row + (self.page_row_max - 1)
    111.       # 从当前行向末尾滚动
    112.       self.top_row = row - (self.page_row_max - 1)
    113.     end
    114.     # 计算光标的宽
    115.     cursor_width = self.width / @column_max - 32
    116.     # 计算光标坐标
    117.     x = @index % @column_max * (cursor_width + 32)
    118.     y = @index / @column_max * @row_height - self.oy
    119.     # 更新光标矩形
    120.     self.cursor_rect.set(x, y, cursor_width, @row_height)
    121.   end
    122. end
    123. class Window_File < Window_Selectable
    124.   #--------------------------------------------------------------------------
    125.   # ● 初始化目标
    126.   #--------------------------------------------------------------------------
    127.   def initialize
    128.     super(0, 64, 640, 416 ,96)
    129.     @column_max = 1
    130.     case$scene
    131.     when Scene_Save
    132.       @item_max = RB::SAVES_MAX
    133.     when Scene_Load
    134.       @item_max = RB::SAVES_MAX + 1
    135.     end
    136.     refresh
    137.     self.index = 0
    138.   end
    139.   #--------------------------------------------------------------------------
    140.   # ● 刷新
    141.   #--------------------------------------------------------------------------
    142.   def refresh
    143.     if@item_max == 0
    144.       return
    145.     end
    146.     self.contents = Bitmap.new(width - 32, @item_max * 96)
    147.     self.contents.clear
    148.     for j in0...@item_max
    149.       x = 64
    150.       y = j * 96
    151.       self.contents.font.color = normal_color
    152.       case$scene
    153.       when Scene_Save
    154.       name = "文件 #{j + 1}"
    155.       self.contents.draw_text(4, y, 600, 32, name)
    156.       @filename = "Save#{j + 1}.rxdata"
    157.       @name_width = contents.text_size(name).width
    158.       @time_stamp = Time.at(0)
    159.       @file_exist = FileTest.exist?(@filename)
    160.       when Scene_Load
    161.         if j == 0
    162.           name = "自动存档"
    163.         else
    164.           name = "文件 #{j}"
    165.         end
    166.         self.contents.draw_text(4, y, 600, 32, name)
    167.       @filename = "Save#{j}.rxdata"
    168.       @name_width = contents.text_size(name).width
    169.       @time_stamp = Time.at(0)
    170.       @file_exist = FileTest.exist?(@filename)
    171.       end
    172.       if@file_exist
    173.         file = File.open(@filename, "r")
    174.         @time_stamp = file.mtime
    175.         @characters = Marshal.load(file)
    176.         @frame_count = Marshal.load(file)
    177.         @game_system = Marshal.load(file)
    178.         @game_switches = Marshal.load(file)
    179.         @game_variables = Marshal.load(file)
    180.         @total_sec = @frame_count / Graphics.frame_rate
    181.         file.close
    182.       end
    183.       # 存档文件存在的情况下
    184.       if@file_exist
    185.         # 描绘角色
    186.         for i in0...@characters.size
    187.           bitmap = RPG::Cache.character(@characters[i][0], @characters[i][1])
    188.           cw = bitmap.rect.width / 4
    189.           ch = bitmap.rect.height / 4
    190.           src_rect = Rect.new(0, 0, cw, ch)
    191.           x = 300 - @characters.size * 32 + i * 64 - cw / 2
    192.           self.contents.blt(x, 68 - ch + y, bitmap, src_rect)
    193.         end
    194.         # 描绘游戏时间
    195.         hour = @total_sec / 60 / 60
    196.         min = @total_sec / 60 % 60
    197.         sec = @total_sec % 60
    198.         time_string = sprintf("%02d:%02d:%02d", hour, min, sec)
    199.         self.contents.font.color = normal_color
    200.         self.contents.draw_text(4, 8 + y, 600, 32, time_string, 2)
    201.         # 描绘时间标记
    202.         self.contents.font.color = normal_color
    203.         time_string = @time_stamp.strftime("%Y/%m/%d %H:%M")
    204.         self.contents.draw_text(4, 40 + y, 600, 32, time_string, 2)
    205.       end
    206.     end
    207.   end
    208. end
    209. #==============================================================================
    210. # ■ Window_ReplaceConfirm
    211. #------------------------------------------------------------------------------
    212. #  确认是否覆盖原始存档的窗口
    213. #==============================================================================
    214. class Window_ReplaceConfirm < Window_Selectable
    215.   #--------------------------------------------------------------------------
    216.   # ● 初始化对像
    217.   #--------------------------------------------------------------------------
    218.   def initialize
    219.     super(160, 176, 320, 128)
    220.     self.contents = Bitmap.new(width - 32, height - 32)
    221.     @item_max = 2
    222.     @column_max = 2
    223.     @commands = ["是的",  "不要"]
    224.     refresh
    225.     self.index = 0
    226.   end
    227.   #--------------------------------------------------------------------------
    228.   # ● 刷新
    229.   #--------------------------------------------------------------------------
    230.   def refresh
    231.     self.contents.clear
    232.     self.contents.font.color = system_color
    233.     self.contents.draw_text(4, 0, 328, 32, "当前位置已经存在存档文件")
    234.     self.contents.draw_text(4, 32, 328, 32, "确认要覆盖当前存档文件吗?")
    235.     self.contents.font.color = normal_color
    236.     for i in0...@item_max
    237.       draw_item(i)
    238.     end
    239.   end
    240.   #--------------------------------------------------------------------------
    241.   # ● 描绘项目
    242.   #     index : 项目编号
    243.   #--------------------------------------------------------------------------
    244.   def draw_item(index)
    245.     x = 4 + index * 144
    246.     self.contents.draw_text(x, 64, 128, 32, @commands[index])
    247.   end
    248.   def update_cursor_rect
    249.     if@index < 0
    250.       self.cursor_rect.empty
    251.     else
    252.       self.cursor_rect.set(@index * 144, 64, (self.width - 32) / 2, 32)
    253.     end
    254.   end
    255. end
    256. #==============================================================================
    257. # ■ Scene_File
    258. #------------------------------------------------------------------------------
    259. #  存档画面及读档画面的超级类。
    260. #==============================================================================
    261. class Scene_File
    262.   #--------------------------------------------------------------------------
    263.   # ● 主处理
    264.   #--------------------------------------------------------------------------
    265.   def main
    266.     # 生成帮助窗口
    267.     @help_window = Window_Help.new
    268.     @help_window.set_text(@help_text)
    269.     @file_window = Window_File.new
    270.     @file_window.index = $game_temp.last_file_index
    271.     @file_window.active = true
    272.     @confirm_window = Window_ReplaceConfirm.new
    273.     @confirm_window.active = false
    274.     @confirm_window.visible = false
    275.     @confirm_window.z = @file_window.z + 10
    276.     # 执行过渡
    277.     Graphics.transition
    278.     # 主循环
    279.     loopdo
    280.       # 刷新游戏画面
    281.       Graphics.update
    282.       # 刷新输入信息
    283.       Input.update
    284.       # 刷新画面
    285.       update
    286.       # 如果画面被切换的话就中断循环
    287.       if$scene != self
    288.         break
    289.       end
    290.     end
    291.     # 准备过渡
    292.     Graphics.freeze
    293.     # 释放窗口
    294.     @help_window.dispose
    295.     @file_window.dispose
    296.     @confirm_window.dispose
    297.   end
    298.   #--------------------------------------------------------------------------
    299.   # ● 刷新画面
    300.   #--------------------------------------------------------------------------
    301.   def update
    302.     # 刷新窗口
    303.     @help_window.update
    304.     @file_window.update
    305.     @confirm_window.update
    306.     case$scene
    307.     when Scene_Save
    308.       if@file_window.active
    309.         update_file
    310.         return
    311.       end
    312.       if@confirm_window.active
    313.         update_confirm
    314.         return
    315.       end
    316.     when Scene_Load
    317.       # 按下 C 键的情况下
    318.       if Input.trigger?(Input::C)
    319.         # 调用过程 on_decision (定义继承目标)
    320.         on_decision(make_filename_load(@file_window.index))
    321.         $game_temp.last_file_index = @file_window.index
    322.         return
    323.       end
    324.       # 按下 B 键的情况下
    325.       if Input.trigger?(Input::B)
    326.         # 调用过程 on_cancel (定义继承目标)
    327.         on_cancel
    328.         return
    329.       end
    330.     end
    331.   end
    332.   #--------------------------------------------------------------------------
    333.   # ● 生成文件名
    334.   #     file_index : 文件名的索引 (0~3)
    335.   #--------------------------------------------------------------------------
    336.   def make_filename(file_index)
    337.     return"Save#{file_index + 1}.rxdata"
    338.   end
    339.   def make_filename_load(file_index)
    340.     return"Save#{file_index}.rxdata"
    341.   end
    342. end
    343. class Scene_Save < Scene_File
    344.   #--------------------------------------------------------------------------
    345.   # ● 初始化对像
    346.   #--------------------------------------------------------------------------
    347.   def initialize
    348.     super("要储存到哪个文件?")
    349.   end
    350.   def update_file
    351.     filename = make_filename(@file_window.index)
    352.     if Input.trigger?(Input::C)
    353.       $game_system.se_play($data_system.decision_se)
    354.       ifFileTest.exist?(filename)
    355.         @file_window.active = false
    356.         @confirm_window.active = true
    357.         @confirm_window.visible = true
    358.       else
    359.         # 演奏存档 SE
    360.         $game_system.se_play($data_system.save_se)
    361.         # 写入存档数据
    362.         file = File.open(filename, "wb")
    363.         write_save_data(file)
    364.         file.close
    365.         # 如果被事件调用
    366.         if$game_temp.save_calling
    367.           # 清除存档调用标志
    368.           $game_temp.save_calling = false
    369.           # 切换到地图画面
    370.           $scene = Scene_Map.new
    371.           return
    372.         end
    373.         # 切换到菜单画面
    374.         $scene = Scene_Menu.new(4)
    375.       end
    376.     end
    377.     if Input.trigger?(Input::B)
    378.       # 演奏取消 SE
    379.       $game_system.se_play($data_system.cancel_se)
    380.       # 如果被事件调用
    381.       if$game_temp.save_calling
    382.         # 清除存档调用标志
    383.         $game_temp.save_calling = false
    384.         # 切换到地图画面
    385.         $scene = Scene_Map.new
    386.         return
    387.       end
    388.       # 切换到菜单画面
    389.       $scene = Scene_Menu.new(4)
    390.     end
    391.   end
    392.   def update_confirm
    393.     filename = make_filename(@file_window.index)
    394.     if Input.trigger?(Input::C)
    395.       case@confirm_window.index
    396.       when0
    397.         # 演奏存档 SE
    398.         $game_system.se_play($data_system.save_se)
    399.         # 写入存档数据
    400.         file = File.open(filename, "wb")
    401.         write_save_data(file)
    402.         file.close
    403.         # 如果被事件调用
    404.         if$game_temp.save_calling
    405.           # 清除存档调用标志
    406.           $game_temp.save_calling = false
    407.           # 切换到地图画面
    408.           $scene = Scene_Map.new
    409.           return
    410.         end
    411.         # 切换到菜单画面
    412.         $scene = Scene_Menu.new(4)
    413.       when1
    414.         $game_system.se_play($data_system.cancel_se)
    415.         @file_window.active = true
    416.         @confirm_window.active = false
    417.         @confirm_window.visible = false
    418.       end
    419.     end
    420.     if Input.trigger?(Input::B)
    421.       $game_system.se_play($data_system.cancel_se)
    422.       @file_window.active = true
    423.       @confirm_window.active = false
    424.       @confirm_window.visible = false
    425.     end
    426.   end
    427.   def autosave
    428.     filename = "Save0.rxdata"
    429.     file = File.open(filename, "wb")
    430.     write_save_data(file)
    431.     file.close
    432.   end
    433. end
    434. class Scene_Load < Scene_File
    435.   #--------------------------------------------------------------------------
    436.   # ● 初始化对像
    437.   #--------------------------------------------------------------------------
    438.   def initialize
    439.     # 再生成临时对像
    440.     $game_temp = Game_Temp.new
    441.     # 选择存档时间最新的文件
    442.     $game_temp.last_file_index = 0
    443.     latest_time = Time.at(0)
    444.     for i in0..RB::SAVES_MAX
    445.       filename = make_filename_load(i)
    446.       ifFileTest.exist?(filename)
    447.         file = File.open(filename, "r")
    448.         if file.mtime > latest_time
    449.           latest_time = file.mtime
    450.           $game_temp.last_file_index = i
    451.         end
    452.         file.close
    453.       end
    454.     end
    455.     super("要载入哪个文件?")
    456.   end
    457. end
    458. class Scene_Map
    459.   unless method_defined? :rb_transfer_player_20141225
    460.     alias rb_transfer_player_20141225 transfer_player
    461.     def transfer_player
    462.       rb_transfer_player_20141225
    463.       unlessRB::NO_AUTOSAVE_MAPS.include?($game_map.map_id) || $game_switches[RB::NO_AUTOSAVE]
    464.         save = Scene_Save.new
    465.         save.autosave
    466.       end
    467.     end
    468.   end
    469. end
    复制代码

    附范例一枚:

    注意有几个地方,我不知道该怎么标注,大家注意Scene_Save里面返回上一级的命令$scene = Scene_Menu.new(x),不同人的菜单不一样的,如果改过Scene_Menu的同学还请注意一下括号里面的数字。
                 本帖来自P1论坛作者jiahui5592986,因Project1站服务器在国外有时候访问缓慢不方便作者交流学习,经联系P1站长fux2同意署名转载一起分享游戏制作经验,共同为国内独立游戏作者共同创造良好交流环境,原文地址:https://rpg.blue/forum.php?mod=viewthread&tid=316649  若有侵权,发帖作者可联系底部站长QQ在线咨询功能删除,谢谢。

    本帖子中包含更多资源

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

    x
    天天去同能,天天有童年!
    回复 论坛版权

    使用道具 举报

    ahome_bigavatar:guest
    ahome_bigavatar:welcomelogin
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|小黑屋|同能RPG制作大师 ( 沪ICP备12027754号-3 )

    GMT+8, 2024-5-14 00:39 , Processed in 0.049482 second(s), 44 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

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