Drago del Fato
Member
DDF Character Maker - Version: 1.4.2
By: Drago del Fato
Introduction
This script allows you to make your own characters in the game. Characters are made by selecting different parts of the body and changing its image, when you finish it is saved within the save file as an Image and loaded every time you load your game.
Features
Changelog
1.2.5 - Initial version of the script
1.4.2 - Constants are now loaded from a module, changed window for showing the icons next to body parts selection
Screenshots
Demo
Demo version 1.0 - Mediafire.com
Script
Instructions
1. Insert new script above main.
2. Paste the code.
3. Modify the constants for BGM, Parts directory and/or Player image filename.
Compatibility
SDK Compilant?
- Don't know. I don't use it so I don't really know.
Other scripts Compilant?
- Well some Save Game scripts should probably need to be modified to match this.
Terms and Conditions
1. Free for Personal and/or Commecial Use.
2. Mention my name in credits and that's all.
By: Drago del Fato
Introduction
This script allows you to make your own characters in the game. Characters are made by selecting different parts of the body and changing its image, when you finish it is saved within the save file as an Image and loaded every time you load your game.
Features
- Making characters and saving them without using any external dll's or Windows API calls.
- Character image is directly saved into the save file so that you can make different character sprites per game.
- Character image replaces the main player's (usually character with id 001) image file in cache memory so that every time you load a character image with that filename it will load main player's created image instead. (So only thing you need to do is keep your filename of the character unique and use one character sprite image only for your main character).
Changelog
1.2.5 - Initial version of the script
1.4.2 - Constants are now loaded from a module, changed window for showing the icons next to body parts selection
Screenshots



Demo
Demo version 1.0 - Mediafire.com
Script
Code:
#==============================================================================
# ** [Name] DDF Character Maker
# * [Author] Drago del Fato
# * [Version] 1.4.2
#------------------------------------------------------------------------------
# This script allows you to make characters directly in the game.
# Main Character image are SAVED as an array of colors directly in the
# save file and are normally loaded when loading them from a save file.
#==============================================================================
module CHR
# Directory where parts are stored
PARTS_DIR = "Graphics/Parts/"
# BGM to be played
BGM_FILENAME = "043-Positive01"
# BGM's volume
BGM_VOLUME = 100
# BGM's Pitch, you can change it from 50 to 150. 100 is normal.
BGM_PITCH = 100
# Name of the Character Maker in-game
CH_MAKER = "Character Maker"
# Description of the usage in-game
CH_DESC = "C, B -> Decision, Left, Right -> Change, Up, Down -> Change Position, C twice - Finish"
# Body Icon
BODY = '013-Body01'
# Head Icon
HEAD = '010-Head01'
# Shoes Icon
BOOTS = '020-Accessory05'
# Eyes Icon
EYES = '036-Item05'
# For example 001-Fighter01 is Aluxes (or Arshes for those who like that name)
# so each time you use 001-Fighter01 in the game it will be replaced by player
# character which is made by this character maker.
# Change this variable to match your main character filename
PLAYER_IMAGE_FILE = "001-Fighter01"
end
# Variable which contains color array of the main character image
$data_player_image = nil
# Stores old magic random number of the player image
# this is to ensure that loading a new save game will replace the player
# image in cache.
$old_magic_number = -1
class Scene_Char_Maker
#--------------------------------------------------------------------------
# * Initialization
#--------------------------------------------------------------------------
def initialize
# Ensure smooth transtion
Graphics.transition(20)
# Freeze the graphics to initialize the scene
Graphics.freeze
# Make background image
@background = Sprite.new
@background.bitmap = Bitmap.new(CHR::PARTS_DIR + "back")
@background.opacity = 160
# Initialize body part variables
@part_id = [0, 0, 0, 0] # File number of each body part
@part_name = ["Boots", "Body", "Eyes", "Head"] # Folder name of each body part
@part_changed = false # Part changed variable
@position = 0 # Sprite position
@position_changed = false # Sprite position changed variable
# Make character on the screen
@char = [Sprite_Char_Sel.new(0, CHR::PARTS_DIR + "0"),
Sprite_Char_Sel.new(0, CHR::PARTS_DIR + "Boots/0"),
Sprite_Char_Sel.new(0, CHR::PARTS_DIR + "Body/0"),
Sprite_Char_Sel.new(0, CHR::PARTS_DIR + "Eyes/0"),
Sprite_Char_Sel.new(0, CHR::PARTS_DIR + "Head/0")]
# Move character to designed point on the screen
@char.each {|part| part.x = 355
part.y = 150
part.zoom_x = 2
part.zoom_y = 2 }
# Make left and right arrows and position them
@arrow_left = Sprite_Arrow_Sel.new(0)
@arrow_right = Sprite_Arrow_Sel.new(1)
@arrow_left.x = 318
@arrow_right.x = 400
@arrow_left.y = 260
@arrow_right.y = 260
@old_part = 0
# Make top caption window
@help_window_top = Window_Help.new
@help_window_top.set_text(CHR::CH_MAKER,1)
@help_window_top.opacity = 160
# Make bottom text window
@help_window_bottom = Window_Help.new
@help_window_bottom.y = 416
@help_window_bottom.opacity = 160
@help_window_bottom.contents.font.size = 20
@help_window_bottom.contents.font.bold = true
@help_window_bottom.set_text(CHR::CH_DESC, 1)
# Make part select window
@part_sel = Window_ParSel.new
@s_end = false # Selection ended variable
@part_sel.active # Make part selection window active
end
#--------------------------------------------------------------------------
# * Main Processing
#--------------------------------------------------------------------------
def main
# Load BGM music into memory
bgm_file = RPG::AudioFile.new(CHR::BGM_FILENAME, CHR::BGM_VOLUME,
CHR::BGM_PITCH)
# Play BGM music
$game_system.bgm_play(bgm_file)
# After everything is initializes transition the scene
# and begin the loop
Graphics.transition(20)
loop do
Graphics.update
Input.update
update
break if @s_end # If selection ended break the loop
end
# Stop graphics
Graphics.freeze
# Dispose sprites and windows
@arrow_left.dispose
@arrow_right.dispose
@help_window_top.dispose
@help_window_bottom.dispose
@background.bitmap.dispose
@background.dispose
# If selection ended by choosing (not by pressing B twice)
# make character image
if @part_sel.active == false
# Create Character Saver class
$data_player_image = Char_Saver.new
# Fill colors while flattening the image layers of the selected
# body parts.
$data_player_image.fill_color_array(transform_to_bitmap)
# Go to Map Scene
$scene = Scene_Map.new
else
# If pressed B twice return to title scene
$scene = Scene_Title.new
end
# Dispose character body parts
@char.size.times {|i| @char[i].bit_dispose; @char[i].dispose}
# Dispose character selection window
@part_sel.dispose
end
#--------------------------------------------------------------------------
# * Update processing
#--------------------------------------------------------------------------
def update
# If position number goes over the boundary return it to first position
@position = 0 if @position > 3
@position = 3 if @position < 0
# Update part selection window if active
@part_sel.update if @part_sel.active
# Update arrows
@arrow_left.update
@arrow_right.update
# Update character body parts sprites
@char.size.times {|i|
@char[i].update
@char[i].refresh(@position) if @position_changed
}
# Reset changed position if true
@position_changed = false if @position_changed
# Load a new part image if changed
if @part_changed
# Form a part file directory
part_file = CHR::PARTS_DIR + @part_name[@part_sel.index] + "/" +
@part_id[@part_sel.index].to_s
# Add .png extension at the end (you need to use PNG images with this)
part_file << ".png"
# Put the last part file number if over the boundary
# (if there is no such file with that number as filename)
@part_id[@part_sel.index] = @old_part if File.exist?(part_file) == false
# Load the new part
@char[@part_sel.index + 1].refresh(@position, part_file)
# Refresh each body part sprite to synch them
@char.size.times {|i| @char[i].refresh(@position)}
@part_changed = false # Put part changed to false
end
# Do various actions depending on Input triggers and activness of the
# part selection window
# If C is pressed and part selection window is active
# then deactivate it.
if Input.trigger?(Input::C) && @part_sel.active
$game_system.se_play($data_system.decision_se)
@part_sel.active = false
# If LEFT is pressed and par selection window is NOT active
# change part depending on the index of the part selection window
elsif Input.trigger?(Input::LEFT) && @part_sel.active == false
$game_system.se_play($data_system.cursor_se)
@arrow_left.flash_it
@old_part = @part_id[@part_sel.index]
@part_id[@part_sel.index] -= 1
@part_changed = true
# If RIGHT is pressed and par selection window is NOT active
# change part depending on the index of the part selection window
elsif Input.trigger?(Input::RIGHT) && @part_sel.active == false
$game_system.se_play($data_system.cursor_se)
@arrow_right.flash_it
@old_part = @part_id[@part_sel.index]
@part_id[@part_sel.index] += 1
@part_changed = true
# If DOWN is pressed and par selection window is NOT active
# change position of the character on the screen
elsif Input.trigger?(Input::DOWN) && @part_sel.active == false
$game_system.se_play($data_system.cursor_se)
@position += 1
@position_changed = true
# If UP is pressed and par selection window is NOT active
# change position of the character on the screen
elsif Input.trigger?(Input::UP) && @part_sel.active == false
$game_system.se_play($data_system.cursor_se)
@position -= 1
@position_changed = true
# If B is pressed and par selection window is NOT active
# reactivate character window to choose another part
elsif Input.trigger?(Input::B) && @part_sel.active == false
$game_system.se_play($data_system.buzzer_se)
@part_sel.active = true
# If C is pressed and par selection window is NOT active
# end character selection and go to map screen
elsif Input.trigger?(Input::C) && @part_sel.active == false
$game_system.se_play($data_system.decision_se)
@s_end = true
# If B is pressed and par selection window is active
# end character selection and return to title screen
elsif Input.trigger?(Input::B) && @part_sel.active
$game_system.se_play($data_system.buzzer_se)
@s_end = true
end
end
#--------------------------------------------------------------------------
# * Joining all body part sprites into one complete sprite
#--------------------------------------------------------------------------
def transform_to_bitmap
# This is one-time process
# it sets each body part a full sprite image consisting
# of 4x4 tiles
@char.size.times{|i| @char[i].set_full_image}
# Put the first (BODY) part into variable
char_bitmap = @char[0].bitmap.clone
# Copy pixels of all other body parts into char_bitmap
for i in [email=1..@char.size]1..@char.size[/email] - 1
x, y = 0, 0
while (y < @char[i].bitmap.height)
if @char[i].bitmap.get_pixel(x, y).alpha > 0
char_bitmap.set_pixel(x, y, @char[i].bitmap.get_pixel(x, y))
end
x += 1
if x > @char[i].bitmap.width
x = 0
y += 1
end
end
end
# Return it. If it's return by clone function
# it is returned as a copy not as a reference
return char_bitmap.clone
end
end
#==============================================================================
# * Char_Saver
# -----------------------------------------------------------------------------
# What an image is? It's a collection of pixels each of different color
# so we just save each pixel in an array and we can reconstruct an image
# exact as it was before, so by using this method we CAN save images from
# within RGSS.
#==============================================================================
class Char_Saver
attr_reader :magic_number # Random number different for each character made
#--------------------------------------------------------------------------
# * Initialization
#--------------------------------------------------------------------------
def initialize
@color_array = [] # Array in which colors of the player image are stored
@max_width = 0 # Maximum width of the character sprite
@max_height = 0 # Maximum height of the character sprite
@magic_number = rand(999) # Make a magic random number
end
#--------------------------------------------------------------------------
# * Joining all body part sprites into one complete sprite
# bitmap : a bitmap from which all colors will be copied
#--------------------------------------------------------------------------
def fill_color_array(bitmap)
# Get width and height from a bitmap
@max_width = bitmap.width
@max_height = bitmap.height
# Set x and y vars for passing trough each pixel
x, y = 0, 0
# Fill y side with arrays
while y < bitmap.height
@color_array.push([])
y += 1
end
y = 0 # Reset y var for another use
# Fill color array with colors
while y < bitmap.height
@color_array[y].push(bitmap.get_pixel(x, y))
x += 1
if x > bitmap.width
x = 0
y += 1
end
end
end
#--------------------------------------------------------------------------
# * Reverse process, combining all colors into a bitmap and returning it
#--------------------------------------------------------------------------
def create_a_bitmap
# If wrong file or something bad happened
raise "Color Array is empty!" if @color_array.size < 1
# Set x and y vars for passing trough each pixel
x, y = 0, 0
# Create a bitmap
bitmap = Bitmap.new(@max_width, @max_height)
# Set each pixel of an bitmap forming a character image
while y < bitmap.height
bitmap.set_pixel(x, y, @color_array[y][x])
x += 1
if x > @max_width
x = 0
y += 1
end
end
# Return completed bitmap
return bitmap.clone
end
# Disposing of each color separately when called dispose
def dispose
for y in 0..@color_array.size - 1
for x in 0..@color_array.size - 1
@color_array[y][x] = nil
end
end
end
end
#=============================================================================
# * Window_ParSel
# ---------------------------------------------------------------------------
# This is window for selecting body parts to change.
#=============================================================================
class Window_ParSel < Window_Command
#--------------------------------------------------------------------------
# * Initialization
#--------------------------------------------------------------------------
def initialize
super(250, ["Boots", "Body", "Eyes", "Head"])
self.x = 0
self.y = 140
self.height = 180
self.opacity = 0
end
#--------------------------------------------------------------------------
# * Draw each item and put shadow on text
#--------------------------------------------------------------------------
def draw_item(index, color)
# Set color for shadow
self.contents.font.color = Color.new(0, 0, 0)
# Align position of the text to center
t_size = self.contents.width / 2 - self.contents.text_size(@commands[index]).width / 2
# Create new rect for shadow
rect = Rect.new(t_size, 32 * index, self.contents.width - 8, 32)
# Fill rect for seleciton
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
# Draw shadow text
self.contents.draw_text(rect, @commands[index])
# Rect for normal text and drawind it
rect = Rect.new(t_size - 2, 32 * index - 2, self.contents.width - 8, 32)
self.contents.font.color = color
self.contents.draw_text(rect, @commands[index])
# Drawing individual icons
x, y = t_size - 32, index * 32 + 4
case index
when 0 # Draw Boots
self.contents.blt(x, y, RPG::Cache.icon(CHR::BOOTS), Rect.new(0, 0, 32, 32))
when 1 # Draw Body
self.contents.blt(x, y, RPG::Cache.icon(CHR::BODY), Rect.new(0, 0, 32, 32))
when 2 # Draw Eyes
self.contents.blt(x, y, RPG::Cache.icon(CHR::EYES), Rect.new(0, 0, 32, 32))
when 3 # Draw Head
self.contents.blt(x, y, RPG::Cache.icon(CHR::HEAD), Rect.new(0, 0, 32, 32))
end
end
end
#=============================================================================
# * Sprite_Arr_Sel
# --------------------------------------------------------------------------
# Sprite for selection arrows.
#=============================================================================
class Sprite_Arrow_Sel < Sprite
#--------------------------------------------------------------------------
# * Initialization
# lr : show left or right arrow
# 0 - Left, 1 - Right
#--------------------------------------------------------------------------
def initialize(lr)
super(nil)
@sel_arrow = Bitmap.new(CHR::PARTS_DIR + "arrow")
self.bitmap = Bitmap.new(64, 64)
self.bitmap.blt(0, 0, @sel_arrow, Rect.new(lr * 64, 0, 64, 64))
end
#--------------------------------------------------------------------------
# * Flashes the sprite when clicked
#--------------------------------------------------------------------------
def flash_it
self.flash(Color.new(255, 255, 255), 20)
end
end
#=============================================================================
# * Sprite_Char_Sel
# ---------------------------------------------------------------------------
# Character sprite for each of the body parts
#=============================================================================
class Sprite_Char_Sel < Sprite
#--------------------------------------------------------------------------
# * Initialization
# part : current position of the character sprite
# filename : filename of the character sprite
#--------------------------------------------------------------------------
def initialize(part, filename)
super(nil) # Send nil to original sprite (viewport)
@sel_char = Bitmap.new(filename) # Load character sprite
@part = part # Set position of the character sprite to part
@pos = 0 # Set animation position of character sprite to 0
# Load bitmap and set block transfer
self.bitmap = Bitmap.new(@sel_char.width / 4, @sel_char.height / 4)
self.bitmap.blt(0, 0, @sel_char, Rect.new(0, part * @sel_char.height / 4, 64, 64))
end
#--------------------------------------------------------------------------
# * Refreshing sprite
# part : current position of the character sprite
# filename : filename of the character sprite
#--------------------------------------------------------------------------
def refresh(part, filename = "")
# Load new bitmap only if the filename exists
@sel_char = Bitmap.new(filename) if File.exists?(filename)
# Clear sprite's bitmap and get a new block transfer
self.bitmap.clear
self.bitmap.blt(0, 0, @sel_char, Rect.new(0, part * @sel_char.height / 4, 64, 64))
# Reset animation position
@pos = 0
# Set refresh part as active
@part = part
end
#--------------------------------------------------------------------------
# * Update Processing
#--------------------------------------------------------------------------
def update
return if Graphics.frame_count % 5 != 0 # Do not update each frame
# Clear contents of the sprite and perform a new block transfer
self.bitmap.clear
self.bitmap.blt(0, 0, @sel_char, Rect.new(@pos * @sel_char.width / 4, @part * @sel_char.height / 4, 64, 64))
# Increase animation position by 1 and if over boundaries set it to 0
@pos += 1
@pos = 0 if @pos > 3
end
#--------------------------------------------------------------------------
# * Drawing full sprite image of an character sprite
#--------------------------------------------------------------------------
def set_full_image
self.bitmap = nil
self.bitmap = @sel_char.clone
end
#--------------------------------------------------------------------------
# * Dispose both bitmaps
#--------------------------------------------------------------------------
def bit_dispose
self.bitmap.dispose
@sel_char.dispose
end
end
#==============================================================================
# ** RPG::Cache
# -> self.load_bitmap - redefinition to load player image only once in memory
# so it can be used troughout the game.
# NOTE: Every time you load a file wihich filename is
# in PLAYER_IMAGE_FILE it WILL be replaced by this.
# So keep your character unique.
#==============================================================================
module RPG
module Cache
def self.load_bitmap(folder_name, filename, hue = 0)
path = folder_name + filename
if $data_player_image != nil && $old_magic_number != $data_player_image.magic_number && filename == CHR::PLAYER_IMAGE_FILE
@cache[path].dispose if @cache[path] != nil
$old_magic_number = $data_player_image.magic_number
end
if not @cache.include?(path) or @cache[path].disposed?
if filename != ""
if filename == CHR::PLAYER_IMAGE_FILE
@cache[path] = $data_player_image.create_a_bitmap
else
@cache[path] = Bitmap.new(path)
end
else
@cache[path] = Bitmap.new(32, 32)
end
end
if hue == 0
@cache[path]
else
key = [path, hue]
if not @cache.include?(key) or @cache[key].disposed?
@cache[key] = @cache[path].clone
@cache[key].hue_change(hue)
end
@cache[key]
end
end
end
end
#==============================================================================
# * Scene_Title
# -> command_new_game - redefinition to start character maker
#==============================================================================
class Scene_Title
def command_new_game
$game_system.se_play($data_system.decision_se)
Audio.bgm_stop
Graphics.frame_count = 0
$game_temp = Game_Temp.new
$game_system = Game_System.new
$game_switches = Game_Switches.new
$game_variables = Game_Variables.new
$game_self_switches = Game_SelfSwitches.new
$game_screen = Game_Screen.new
$game_actors = Game_Actors.new
$game_party = Game_Party.new
$game_troop = Game_Troop.new
$game_map = Game_Map.new
$game_player = Game_Player.new
$game_party.setup_starting_members
$game_map.setup($data_system.start_map_id)
$game_player.moveto($data_system.start_x, $data_system.start_y)
$game_player.refresh
$game_map.autoplay
$game_map.update
$scene = Scene_Char_Maker.new
end
end
#==============================================================================
# * Window_SaveFile
# -> initialize - redefinition to load player saved image.
# -> refresh - redefinition to draw player saved image.
#==============================================================================
class Window_SaveFile < Window_Base
def initialize(file_index, filename)
super(0, 64 + file_index % 4 * 104, 640, 104)
self.contents = Bitmap.new(width - 32, height - 32)
@file_index = file_index
@filename = "Save#{@file_index + 1}.rxdata"
@time_stamp = Time.at(0)
@file_exist = FileTest.exist?(@filename)
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)
# Real image variable load
@game_image = Marshal.load(file)
@total_sec = @frame_count / Graphics.frame_rate
file.close
end
refresh
@selected = false
end
def refresh
self.contents.clear
self.contents.font.color = normal_color
name = "File#{@file_index + 1}"
self.contents.draw_text(4, 0, 600, 32, name)
@name_width = contents.text_size(name).width
if @file_exist
for i in [email=0...@characters.size]0...@characters.size[/email]
bitmap = RPG::Cache.character(@characters[i][0], @characters[i][1]) if i > 0
# Set the first character to be a players created image if i is 0
bitmap = @game_image.create_a_bitmap if i < 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, 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, 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, 600, 32, time_string, 2)
end
end
end
#==============================================================================
# * Scene_Save
# -> write_save_data - redefinition to save player image into save file
#==============================================================================
class Scene_Save < Scene_File
def write_save_data(file)
characters = []
for i in 0...$game_party.actors.size
actor = $game_party.actors[i]
characters.push([actor.character_name, actor.character_hue])
end
Marshal.dump(characters, file)
Marshal.dump(Graphics.frame_count, file)
$game_system.save_count += 1
$game_system.magic_number = $data_system.magic_number
Marshal.dump($game_system, file)
Marshal.dump($game_switches, file)
Marshal.dump($game_variables, file)
Marshal.dump($data_player_image, file) # Save Data of the Image to Savefile
Marshal.dump($game_self_switches, file)
Marshal.dump($game_screen, file)
Marshal.dump($game_actors, file)
Marshal.dump($game_party, file)
Marshal.dump($game_troop, file)
Marshal.dump($game_map, file)
Marshal.dump($game_player, file)
end
end
#==============================================================================
# * Scene_Load
# -> read_save_data - redefinition to load player image into save file
#==============================================================================
class Scene_Load < Scene_File
def read_save_data(file)
characters = Marshal.load(file)
Graphics.frame_count = Marshal.load(file)
$game_system = Marshal.load(file)
$game_switches = Marshal.load(file)
$game_variables = Marshal.load(file)
$data_player_image = Marshal.load(file) # Reload player image
$game_self_switches = Marshal.load(file)
$game_screen = Marshal.load(file)
$game_actors = Marshal.load(file)
$game_party = Marshal.load(file)
$game_troop = Marshal.load(file)
$game_map = Marshal.load(file)
$game_player = Marshal.load(file)
if $game_system.magic_number != $data_system.magic_number
$game_map.setup($game_map.map_id)
$game_player.center($game_player.x, $game_player.y)
end
$game_party.refresh
end
end
Instructions
1. Insert new script above main.
2. Paste the code.
3. Modify the constants for BGM, Parts directory and/or Player image filename.
Compatibility
SDK Compilant?
- Don't know. I don't use it so I don't really know.
Other scripts Compilant?
- Well some Save Game scripts should probably need to be modified to match this.
Terms and Conditions
1. Free for Personal and/or Commecial Use.
2. Mention my name in credits and that's all.