#==============================================================================
# vx新截图存档 by 沉影不器
#------------------------------------------------------------------------------
# ☆ 核心部分是内存位图的输入输出
# (快速存储Bitmap的Marshal 作者: 柳之一) 强大啊
#------------------------------------------------------------------------------
# ▼ 相比rmxp正版截图存档(作者: 柳柳),主要变动如下:
# ① 省去了 screenshot.dll 文件 (因快速存储Bitmap的Marshal的存在)
# ② 无须人工新建存档文件夹,脚本将自建
# ③ 方便地更改最大存档数,只需设置最大值
#==============================================================================
MAX_SAVE_ID = 12 # 最大存档数
SAVE_DIR = "Saves/" # 改变的存档目录(不希望改变目录请删)
#==============================================================================
# (快速存储Bitmap的Marshal 作者: 柳之一) 强大啊
#==============================================================================
class Font
def marshal_dump
end
def marshal_load(obj)
end
end
class Bitmap
# 传送到内存的API函数
RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
RtlMoveMemory_ip = Win32API.new('kernel32', 'RtlMoveMemory', 'ipi', 'i')
def _dump(limit)
data = "rgba" * width * height
RtlMoveMemory_pi.call(data, address, data.length)
[width, height, Zlib::Deflate.deflate(data)].pack("LLa*") # 压缩
end
def self._load(str)
w, h, zdata = str.unpack("LLa*")
b = self.new(w, h)
RtlMoveMemory_ip.call(b.address, Zlib::Inflate.inflate(zdata), w * h * 4)
return b
end
# [[[bitmap.object_id * 2 + 16] + 8] + 16] == 数据的开头
def address
buffer, ad = "rgba", object_id * 2 + 16
RtlMoveMemory_pi.call(buffer, ad, 4)
ad = buffer.unpack("L")[0] + 8
RtlMoveMemory_pi.call(buffer, ad, 4)
ad = buffer.unpack("L")[0] + 16
RtlMoveMemory_pi.call(buffer, ad, 4)
return buffer.unpack("L")[0]
end
end
#==============================================================================
# ■ Game_Temp
#==============================================================================
class Game_Temp
#--------------------------------------------------------------------------
# ● 定义实例变量
#--------------------------------------------------------------------------
attr_accessor :save_bitmap # 存档位图
#--------------------------------------------------------------------------
# ● 初始化对象
#--------------------------------------------------------------------------
alias ini initialize
def initialize
ini
@save_bitmap = Bitmap.new(1, 1)
end
end
#==============================================================================
# ■ Window_SaveFile
#==============================================================================
class Window_SaveFile < Window_Base
#--------------------------------------------------------------------------
# ● 定义实例变量
#--------------------------------------------------------------------------
attr_reader :filename # 文件名
attr_reader :file_exist # 文件存在标志
#--------------------------------------------------------------------------
# ● 初始化对象
# file_index : 存档文件索引 (0~3)
# filename : 文件名
#--------------------------------------------------------------------------
def initialize(file_index, filename)
super(160, 56, 384, 360)
@file_index = file_index
@filename = filename
make_dir(SAVE_DIR) if SAVE_DIR != nil
load_gamedata
refresh(@file_index)
end
#--------------------------------------------------------------------------
# ● 读取部分游戏数据
#--------------------------------------------------------------------------
def load_gamedata
@file_exist = FileTest.exist?(SAVE_DIR + @filename)
if @file_exist
file = File.open(SAVE_DIR + @filename, "r")
begin
@characters = Marshal.load(file)
@frame_count = Marshal.load(file)
@last_bgm = Marshal.load(file)
@last_bgs = Marshal.load(file)
@game_system = Marshal.load(file)
@game_message = Marshal.load(file)
@game_switches = Marshal.load(file)
@game_variables = Marshal.load(file)
@game_self_switches = Marshal.load(file)
@game_actors = Marshal.load(file)
@game_party = Marshal.load(file)
@game_troop = Marshal.load(file)
@game_map = Marshal.load(file)
[url=home.php?mod=space&uid=14736]@game_player[/url] = Marshal.load(file)
# 读取截图
@file_bitmap = Marshal.load(file)
@total_sec = @frame_count / Graphics.frame_rate
rescue
@file_exist = false
ensure
file.close
end
end
end
#--------------------------------------------------------------------------
# ● 刷新
# index : 索引
#--------------------------------------------------------------------------
def refresh(index)
file_index = index
self.contents.clear
self.contents.font.color = normal_color
if @file_exist
# 描绘底部阴影
self.contents.fill_rect(12+3, 4+3, 326,249, Color.new(0,0,64))
# 描绘截图
draw_snap_bitmap(12, 4)
draw_party_characters(152, 296)
draw_playtime(0, 296+8, contents.width - 40, 2)
else
self.contents.draw_text(0, 296, 384-32, 24, "无此存档!", 1)
end
end
#--------------------------------------------------------------------------
# ◎ 更改索引
# index : 索引
#--------------------------------------------------------------------------
def file_index=(file_index)
@file_index = file_index
end
#--------------------------------------------------------------------------
# ● 描绘游戏人物
# x : 描画先 X 座標
# y : 描画先 Y 座標
#--------------------------------------------------------------------------
def draw_party_characters(x, y)
for i in [email]0...@characters.size[/email]
name = @characters[i][0]
index = @characters[i][1]
draw_character(name, index, x + i * 48, y)
end
end
#--------------------------------------------------------------------------
# ◎ 生成保存路径
# path : 路径
#--------------------------------------------------------------------------
def make_dir(path)
dir = path.split("/")
for i in 0...dir.size
unless dir == "."
add_dir = dir[0..i].join("/")
begin
Dir.mkdir(add_dir)
rescue
end
end
end
end
#--------------------------------------------------------------------------
# ◎ 生成文件名
# file_index : 存档文件索引 (0~3)
#--------------------------------------------------------------------------
def make_filename(file_index)
return "Save#{file_index + 1}.rvdata"
end
#--------------------------------------------------------------------------
# ◎ 描绘截图
# x : 描画先 X 座標
# y : 描画先 Y 座標
#--------------------------------------------------------------------------
def draw_snap_bitmap(x, y)
bitmap = @file_bitmap
if bitmap == nil
self.contents.draw_text(0, 112, 384-32, 24, "找不到截图文件!", 1)
else
self.contents.blur
rect = Rect.new(0, 0, 0, 0)
rect.width = bitmap.width
rect.height = bitmap.height
self.contents.blt(x, y, bitmap, rect)
end
end
#--------------------------------------------------------------------------
# ● 描绘游戏时间
# x : 描绘目标 X 坐标
# y : 描绘目标 Y 坐标
# width : 宽
# align : 配置
#--------------------------------------------------------------------------
def draw_playtime(x, y, width, align)
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(x, y, width, WLH, time_string, 2)
end
end
#==============================================================================
# ■ Scene_Base
#==============================================================================
class Scene_Base
#--------------------------------------------------------------------------
# ◎ 生成存档位图快照
#--------------------------------------------------------------------------
def snapshot_for_save
d_rect = Rect.new(0, 0, 326, 249)
s_rect = Rect.new(0, 0, 544, 416)
save_bitmap = Graphics.snap_to_bitmap
$game_temp.save_bitmap.dispose
$game_temp.save_bitmap = Bitmap.new(326, 249)
$game_temp.save_bitmap.stretch_blt(d_rect, save_bitmap, s_rect)
end
end
#==============================================================================
# ■ Scene_Map
#==============================================================================
class Scene_Map < Scene_Base
#--------------------------------------------------------------------------
# ● 结束处理
#--------------------------------------------------------------------------
alias save_terminate terminate
def terminate
snapshot_for_save
save_terminate
end
end
#==============================================================================
# ■ Scene_Title
#==============================================================================
class Scene_Title < Scene_Base
#--------------------------------------------------------------------------
# ● 判断继续是否有效
#--------------------------------------------------------------------------
def check_continue
@continue_enabled = (Dir.glob(SAVE_DIR + 'Save*.rvdata').size > 0)
end
end
#==============================================================================
# ■ Scene_File
#------------------------------------------------------------------------------
# 处理文件的类。
#==============================================================================
class Scene_File < Scene_Base
#--------------------------------------------------------------------------
# ● 初始化对象
# saving : 存档标志 (false 为载入画面)
# from_title : 调用标题画面的 "继续" 标志
# from_event : 事件的 "调用存档画面" 的调用标志
#--------------------------------------------------------------------------
def initialize(saving, from_title, from_event)
@saving = saving
@from_title = from_title
@from_event = from_event
end
#--------------------------------------------------------------------------
# ● 开始处理
#--------------------------------------------------------------------------
def start
super
create_menu_background
@help_window = Window_Help.new
create_command_window
if @saving
[url=home.php?mod=space&uid=370741]@Index[/url] = $game_temp.last_file_index
@help_window.set_text(Vocab::SaveMessage)
else
@index = self.latest_file_index
@help_window.set_text(Vocab::LoadMessage)
end
@refresh_index = @command_window.index = @index
@item_max = MAX_SAVE_ID
create_savefile_window
end
#--------------------------------------------------------------------------
# ● 结束处理
#--------------------------------------------------------------------------
def terminate
super
dispose_menu_background
@help_window.dispose
dispose_item_windows
end
#--------------------------------------------------------------------------
# ● 还原至原先的画面
#--------------------------------------------------------------------------
def return_scene
if @from_title
$scene = Scene_Title.new
elsif @from_event
$scene = Scene_Map.new
else
$scene = Scene_Menu.new(4)
end
end
#--------------------------------------------------------------------------
# ● 更新画面
#--------------------------------------------------------------------------
def update
super
update_menu_background
@help_window.update
update_savefile_windows
update_savefile_selection
end
#--------------------------------------------------------------------------
# ◎ 生成存档文件列表窗口
#--------------------------------------------------------------------------
def create_command_window
file_names = []
digit = MAX_SAVE_ID.to_s.size
str_f = ""
digit.times{|n| str_f += "0"}
str_f[str_f.size-1, 1] = digit.to_s
for i in 0...MAX_SAVE_ID
id = sprintf("%#{str_f}d", i+1)
file_names.push(Vocab::File + "\s" + id)
end
@command_window = Window_Command.new(160, file_names)
@command_window.height = 360
@command_window.y = 56
end
#--------------------------------------------------------------------------
# ● 生成存档文件窗口
#--------------------------------------------------------------------------
def create_savefile_window
@savefile_window = Window_SaveFile.new(@command_window.index, make_filename(@command_window.index))
end
#--------------------------------------------------------------------------
# ● 释放存档文件
#--------------------------------------------------------------------------
def dispose_item_windows
@command_window.dispose
@savefile_window.dispose
end
#--------------------------------------------------------------------------
# ● 更新存档文件窗口
#--------------------------------------------------------------------------
def update_savefile_windows
@command_window.update
@savefile_window.update
end
#--------------------------------------------------------------------------
# ● 更新存档文件选择
#--------------------------------------------------------------------------
def update_savefile_selection
if Input.trigger?(Input::C)
determine_savefile
end
if Input.trigger?(Input::B)
Sound.play_cancel
return_scene
end
if @refresh_index != @command_window.index
@refresh_index = @command_window.index
@savefile_window.dispose
create_savefile_window
end
end
#--------------------------------------------------------------------------
# ● 确定存档文件
#--------------------------------------------------------------------------
def determine_savefile
if @saving
Sound.play_save
do_save
else
if @savefile_window.file_exist
Sound.play_load
do_load
else
Sound.play_buzzer
return
end
end
$game_temp.last_file_index = @index
end
#--------------------------------------------------------------------------
# ◎ 生成文件名
# file_index : 存档文件索引
#--------------------------------------------------------------------------
def make_filename(file_index)
return "Save#{file_index + 1}.rvdata"
end
#--------------------------------------------------------------------------
# ● 按时间戳选择最新的文件
#--------------------------------------------------------------------------
def latest_file_index
index = 0
latest_time = Time.at(0) # 时间戳
for i in 0...MAX_SAVE_ID
file_name = make_filename(i)
if FileTest.exist?(SAVE_DIR + file_name)
file = File.open(SAVE_DIR + file_name, "r")
if file.mtime > latest_time
latest_time = file.mtime
index = i
end
end
end
return index
end
#--------------------------------------------------------------------------
# ● 执行存档
#--------------------------------------------------------------------------
def do_save
file_name = make_filename(@command_window.index)
file = File.open(SAVE_DIR + file_name, "wb")
write_save_data(file)
# 保存位图
$file_bitmap = $game_temp.save_bitmap
Marshal.dump($file_bitmap, file)
file.close
return_scene
end
#--------------------------------------------------------------------------
# ● 执行载入
#--------------------------------------------------------------------------
def do_load
file_name = make_filename(@command_window.index)
file = File.open(SAVE_DIR + file_name, "rb")
read_save_data(file)
file.close
$scene = Scene_Map.new
RPG::BGM.fade(1500)
Graphics.fadeout(60)
Graphics.wait(40)
@last_bgm.play
@last_bgs.play
end
end