03-07-2008, 04:33 AM
Rataime's Image Save Files
Hi guys ! Nice to see some of you again !
After playing Master of the Wind, and not having opened RMXP for one year, I wanted to check if I was still able to make original scripts (with an heavy dose of eye-candy, obviously). Well, you tell me. I've coded this script in a few hours today, inspired by http://www.squidi.net/three/entry.php?id=12
This script allows you to save your game in .png (picture) files. That way, you can distribute, host and share them easily, for example as a forum signature. You can also use thumbnail views for quick sorting and browsing, given that you can put whatever information you want on the picture.
For example, the following pictures :
are actual savegames of my demo. You can put them in my demo and load them in rmxp !
It's obviously up to you to configure how are generated the pictures, the ones above are just an example automatically using the battleback of the last map I was on.
The script needs the SDK, and can't be converted to non-SDK. Dealing with savefiles without the SDK is a sure way to mess with other scripts... Even now, it will still probably mess with non-SDK save scripts.
Here's the code :
Content Hidden
Code:
#==============================================================================
# ** Image Save File
#------------------------------------------------------------------------------
# Rataime
# Version 1.0
# 11/08/2008 (2008-08-11)
# Original Idea : Squdi (http://www.squidi.net/three/entry.php?id=12)
#------------------------------------------------------------------------------
#
# This script allows you to save your game in .png (picture) files. That way,
# you can distribute and host them easily, for example as a forum signature.
# You can also use thumbnail views for quick sorting and browsing, given that
# you can put whatever innformation you want on the picture.
#
# The files will be saved as Save1.png, Save2.png... If both Save1.rxdata and
# Save1.png exist, Save1.png will be loaded.
#
# If for whatever reason you want your game to be able to load .png files but
# still saving as .rxdata, set IMAGE_SAVEFILE_SAVE_AS_PNG to false. I don't
# recommand it, as it will become complicated when there's both a Save1.rxdata
# and Save1.png...
#
# To configure your own picture, see rataime_generate_png_file_from_template
#
#==============================================================================
#==============================================================================
# IMAGE_SAVEFILE_SAVE_AS_PNG : Set to false to save as .rxdata
#==============================================================================
IMAGE_SAVEFILE_SAVE_AS_PNG = true
class Scene_Save < Scene_File
#--------------------------------------------------------------------------
# * rataime_generate_png_file_from_template
#
# This method generates the png file that will be use by the save file.
# Do whatever you want here, the following code is just a demo
# I've extended the Bitmap class a bit to include some common Window
# methods like draw_actor_level. Feel free to experiment new ways of creating
# the picture !
#--------------------------------------------------------------------------
def rataime_generate_png_file_from_template
# We load Graphics\Pictures\save_template_demo.png to use as a background
bitmap = RPG::Cache.picture('save_template_demo')
# We draw the 4 actor graphics and their levels
bitmap.draw_actor_graphic($game_party.actors[0],52,277)
bitmap.draw_actor_level($game_party.actors[0], 73, 237)
if $game_party.actors[1] != nil
bitmap.draw_actor_graphic($game_party.actors[1],52,350)
bitmap.draw_actor_level($game_party.actors[1], 73, 310)
if $game_party.actors[2] != nil
bitmap.draw_actor_graphic($game_party.actors[2],167,277)
bitmap.draw_actor_level($game_party.actors[2], 188, 237)
if $game_party.actors[3] != nil
bitmap.draw_actor_graphic($game_party.actors[3],167,350)
bitmap.draw_actor_level($game_party.actors[3], 188, 310)
end
end
end
# We draw the play time
bitmap.draw_playtime(100,182)
# We draw the battleback of the last map on our picture
# The size is ajusted so the recatngle is filled without stretching
# the battleback, by discarding the sides of the battleback
battleback = RPG::Cache.battleback($game_map.battleback_name)
from = Rect.new(42, 0, 556, 320)
to = Rect.new(32, 49, 217, 125)
bitmap.stretch_blt(to, battleback, from)
return bitmap
end
alias rataime_image_save_file_on_decision on_decision
def on_decision(filename)
if IMAGE_SAVEFILE_SAVE_AS_PNG
filename = filename.split('.')[0] + '.png'
end
rataime_image_save_file_on_decision(filename)
end
alias rataime_image_save_file_write_save_data write_save_data
def write_save_data(file)
if IMAGE_SAVEFILE_SAVE_AS_PNG
rataime_generate_png_file_from_template.rataime_write_png(file)
end
rataime_image_save_file_write_save_data(file)
end
end
class Scene_Load < Scene_File
alias rataime_image_save_file_on_decision on_decision
alias rataime_image_save_file_read_save_data read_save_data
def on_decision(filename)
@extension = filename.split('.')[-1].downcase
rataime_image_save_file_on_decision(filename)
end
def read_save_data(file)
if @extension.downcase == 'png'
file.gets('IEND')
4.times do
file.getc
end
end
rataime_image_save_file_read_save_data(file)
end
end
class Scene_File
alias rataime_image_save_file_make_filename make_filename
def make_filename(file_index)
if FileTest.exist?("Save#{file_index + 1}.png")
return "Save#{file_index + 1}.png"
else
return "Save#{file_index + 1}.rxdata"
end
end
end
class Scene_Title
alias rataime_image_save_file_main_test_continue main_test_continue
def main_test_continue
rataime_image_save_file_main_test_continue
for i in 0..3
if FileTest.exist?("Save#{i+1}.png")
# Sets Continued Enable Flag On
@continue_enabled = true
end
end
end
end
class Window_SaveFile < Window_Base
alias rataime_image_save_file_init_gamedata init_gamedata
def init_gamedata
if @filename.split('.')[-1].downcase == 'png'
file = File.open(@filename, "rb")
@time_stamp = file.mtime
file.gets('IEND')
4.times do
file.getc
end
@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
else
rataime_image_save_file_init_gamedata
end
end
end
#==============================================================================
# ** Bitmap
#==============================================================================
class Bitmap
def normal_color
return Color.new(255, 255, 255, 255)
end
def system_color
return Color.new(192, 224, 255, 255)
end
def draw_actor_graphic(actor, x, y)
bmp = RPG::Cache.character(actor.character_name, actor.character_hue)
cw = bmp.width / 4
ch = bmp.height / 4
src_rect = Rect.new(0, 0, cw, ch)
self.blt(x - cw / 2, y - ch, bmp, src_rect)
end
def draw_playtime(x,y)
total_sec = Graphics.frame_count / Graphics.frame_rate
hour = total_sec / 60 / 60
min = total_sec / 60 % 60
sec = total_sec % 60
text = sprintf("%02d:%02d:%02d", hour, min, sec)
self.font.color = normal_color
self.draw_text(x, y, 120, 32, text, 2)
end
def draw_actor_level(actor, x, y)
self.font.color = system_color
self.draw_text(x, y, 32, 32, "Lv")
self.font.color = normal_color
self.draw_text(x + 24, y, 24, 32, actor.level.to_s, 2)
end
def rataime_write_png(f)
Zlib::Png_File.open('temp.gz') { |gz| gz.make_png(self, 0) }
Zlib::GzipReader.open('temp.gz') { |gz| $read = gz.read }
f.write($read)
File.delete('temp.gz')
end
end
#==============================================================================
# ** Modules.Zlib
#------------------------------------------------------------------------------
# Description:
# ------------
# Adds PNG_File class to save Bitmap's to PNG Files
#
# Class List:
# -----------
# Png_File
#==============================================================================
#==============================================================================
# ** Zlib
#==============================================================================
module Zlib
#============================================================================
# ** Png_File
#-------------------------------------------------------------------------
# Info : Saves Bitmap to File
# Author : ??? - http://www.66rpg.com/htm/news624.htm
#============================================================================
class Png_File < GzipWriter
#--------------------------------------------------------------------------
# * Make PNG
#--------------------------------------------------------------------------
def make_png(bitmap, mode = 0)
# Save Bitmap & Mode
@bitmap, @mode = bitmap, mode
# Create & Save PNG
self.write(make_header)
self.write(make_ihdr)
self.write(make_idat)
self.write(make_iend)
end
#--------------------------------------------------------------------------
# * Make Header
#--------------------------------------------------------------------------
def make_header
return [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a].pack('C*')
end
#--------------------------------------------------------------------------
# * Make IHDR
#--------------------------------------------------------------------------
def make_ihdr
ih_size = [13].pack("N")
ih_sign = 'IHDR'
ih_width = [@bitmap.width].pack('N')
ih_height = [@bitmap.height].pack('N')
ih_bit_depth = [8].pack('C')
ih_color_type = [6].pack('C')
ih_compression_method = [0].pack('C')
ih_filter_method = [0].pack('C')
ih_interlace_method = [0].pack('C')
string = ih_sign + ih_width + ih_height + ih_bit_depth + ih_color_type +
ih_compression_method + ih_filter_method + ih_interlace_method
ih_crc = [Zlib.crc32(string)].pack('N')
return ih_size + string + ih_crc
end
#--------------------------------------------------------------------------
# * Make IDAT
#--------------------------------------------------------------------------
def make_idat
header = "\x49\x44\x41\x54"
data = @mode == 0 ? make_bitmap_data0 : make_bitmap_data1
data = Zlib::Deflate.deflate(data, 8)
crc = [Zlib.crc32(header + data)].pack('N')
size = [data.length].pack('N')
return size + header + data + crc
end
#--------------------------------------------------------------------------
# * Make Bitmap Data 0
#--------------------------------------------------------------------------
def make_bitmap_data0
gz = Zlib::GzipWriter.open('hoge.gz')
t_Fx = 0
w = @bitmap.width
h = @bitmap.height
data = []
for y in 0...h
data.push(0)
for x in 0...w
t_Fx += 1
if t_Fx % 10000 == 0
Graphics.update
end
if t_Fx % 100000 == 0
s = data.pack("C*")
gz.write(s)
data.clear
end
color = @bitmap.get_pixel(x, y)
red = color.red
green = color.green
blue = color.blue
alpha = color.alpha
data.push(red)
data.push(green)
data.push(blue)
data.push(alpha)
end
end
s = data.pack("C*")
gz.write(s)
gz.close
data.clear
gz = Zlib::GzipReader.open('hoge.gz')
data = gz.read
gz.close
File.delete('hoge.gz')
return data
end
#--------------------------------------------------------------------------
# * Make Bitmap Data Mode 1
#--------------------------------------------------------------------------
def make_bitmap_data1
w = @bitmap.width
h = @bitmap.height
data = []
for y in 0...h
data.push(0)
for x in 0...w
color = @bitmap.get_pixel(x, y)
red = color.red
green = color.green
blue = color.blue
alpha = color.alpha
data.push(red)
data.push(green)
data.push(blue)
data.push(alpha)
end
end
return data.pack("C*")
end
#--------------------------------------------------------------------------
# * Make IEND
#--------------------------------------------------------------------------
def make_iend
ie_size = [0].pack('N')
ie_sign = 'IEND'
ie_crc = [Zlib.crc32(ie_sign)].pack('N')
return ie_size + ie_sign + ie_crc
end
end
end
And here's the demo :
http://rataime.free.fr/rmxp/Demos/rataime_demo.zip
Enjoy !