Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

[Review] Make Character sprites directly in the game [RMXP]

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
  • 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

scr1.jpg

scr2.jpg

scr3.jpg

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. :)
 
I'd prefer to see you include some sprites for the body parts menu in your script instead of using a standard menu window. IDK, I just think it'd look better, less boring...
 
Well I that's not a big problem to do at all, but I would like a bit more feedback on bugs and glitches than cosmetic appearances, although if somebody really needs that I will do it.

I don't understand how is this boring to you? :S
There a lot of commercial games which use character makers to form your own characters when you start a game, this one is no different. :)
 
Well, I took a look at this, and I noticed some things right away. While I haven't tested the script for bugs, I do have some comments on coding style for you. Please keep in mind that these comments are intended to help you make scripts that are formatted in a way that makes them easier for scripters of all levels to get at least a basic understanding of what you've done, as well as to help you improve your coding style to prevent unnecessary waste. Anyway, on to the comments.

First off, you have constants and globals. I recommend getting rid of them ASAP, because the way you used them is not a part of any standard coding styles from the lest decade. You can find whole books dedicated to the reasons why you should never use a global variable or constant when you don't have to. Suffice to say, it's a waste of data and memory, there are more efficient methods of doing it that are accepted in most programming communities, and it is no longer necessary. In this script's case, I recommend taking all of those constants and variables, and bundling them up and placing them into a module. That way, you can still access them when you need to, but they won't be constantly active code that needs to be checked and reinterpreted every time you iterate through the Ruby loop.

Next, I have a few comments on your commenting, or general lack of it. Commenting is considered a requirement if you plan on sharing your code with others. While the RM* community doesn't stress it nearly as much as most communities, that is simply because we're not a programming-oriented community.

While I'm not saying to comment every line (commenting end statements would be sort of silly, don't you think?), I am recommending that you comment actions. Specifically, when something gets done, place a comment about it. If several lines in a row are all very similar in function, place one comment before them that says what they all do. When things happen fast, you may need to comment most or all lines. And when you set up a lot of variables in a structure like an array or a hash, format them so that you can not only read them easily, but also so you can place comments about what they are for.

If you have a great deal of trouble commenting, to the point where it puts you off scripting, I recommend that you comment as you go. Turn it into part of your logical scripting process. Write a comment saying what you're about to do, and then write the line of code that actually does it. I've found that that method actually helps me crystallize my thoughts, as well as making my in-progress code clean and understandable. It also gives the added benefit of letting myself and others know where I left off, so that I can finish it later.

And if you know you need to fix something, but need to move on or do something else, tag the spot with a "fixme" comment, something that will always be the same, and that you can just search for when you're done, so that you can go back and fix or change what you tagged. (I have a friend who does that with comments to the effect of #zzhack) Plus, this takes some of the load off of you when you're scripting. Instead of being forced to remember what you were doing a hundred lines ago, because you need to fix it, you can forget about it and fix it after you're done.

Finally, on to formatting. This is the subject you need the least work on, and I'm guessing that at least some of the issues I'm seeing are a result of the code tags and not your scripting. First, when something goes to a second line, it's actually cleaner to indent it with a standard inde3nt, instead of indenting the second line to a point dependent on the first line. (I'm guessing you were using the first thing after the equals sign, but the formatting I see prevents me from being sure, because that is not what is actually there) Indenting with the same standard indent (2 spaces in RMXP) will result in code that looks cleaner and better formatted, because you don't have odd indentations all over the place.

Next in formatting is your structures. I went into this earlier, but it's better to format them so that they are easy to read, and so that you can actually place a comment to the right of the structure itself, explaining what each variable does.

Finally, I want to talk about line length. While you don't actually force me to scroll sideways, it does go all the way to the edge of the screen, if you're using default settings. I recommend that, if you're going to be using the screen as a guideline, you should make sure that nothing goes past the gray line they placed on the right. I tend to prefer leaving a full space between the end of any line of code and that border. While this may seem like a nitpick, it isn't. I say this because the way you have it set up, it looks like some lines should scroll to the side, and it makes people go for a scrollbar that isn't there. When you format it like Enterbrain did, it actually looks clean and easy to understand, far more than most scripts currently on this forum.

Anyway, these comments are, as I said, intended to make your script far more legible, accessible, and, most importantly of all, easier to understand. With a script like this, you'll never win The Third Man's Golden Left-Sided Shoe Of Walking-Where-Nobody's-Been-Before.
 
Glitch":38rjbbs1 said:
Finally, on to formatting. This is the subject you need the least work on, and I'm guessing that at least some of the issues I'm seeing are a result of the code tags and not your scripting. First, when something goes to a second line, it's actually cleaner to indent it with a standard inde3nt, instead of indenting the second line to a point dependent on the first line. (I'm guessing you were using the first thing after the equals sign, but the formatting I see prevents me from being sure, because that is not what is actually there) Indenting with the same standard indent (2 spaces in RMXP) will result in code that looks cleaner and better formatted, because you don't have odd indentations all over the place.
Well, it'd also happen because his text editor automatically indent those line in such a weird way... I always face that small problem while using Kate, but I prefer not to use too long words and just assign the value of that thing to a new local variable... and then I just keep using the local variable until the end of the method or condition.
 
Glitch":3gwcio55 said:
First off, you have constants and globals. I recommend getting rid of them ASAP, because the way you used them is not a part of any standard coding styles from the lest decade. You can find whole books dedicated to the reasons why you should never use a global variable or constant when you don't have to. Suffice to say, it's a waste of data and memory, there are more efficient methods of doing it that are accepted in most programming communities, and it is no longer necessary. In this script's case, I recommend taking all of those constants and variables, and bundling them up and placing them into a module. That way, you can still access them when you need to, but they won't be constantly active code that needs to be checked and reinterpreted every time you iterate through the Ruby loop.

Well thanks for that info. I didn't know it would interpret them every time, as for that global one, it's needed because I need to store player's image class somewhere where it will be accessible from other scripts. Specifically RPG::Cache. It's used per each loading and saving and starting a new game so I can't put it anywhere else. As for my coding style I don't need to change it, I think I'm not doing much wrong except these globals and constants which you told me and that's because I'm not used to interpreter languages, languages which I mostly work are compiler oriented (C/C++ and Delphi). I only work with ruby in RGSS for RMXP/VX.

Glitch":3gwcio55 said:
Next, I have a few comments on your commenting, or general lack of it. Commenting is considered a requirement if you plan on sharing your code with others. While the RM* community doesn't stress it nearly as much as most communities, that is simply because we're not a programming-oriented community.

You got me here, it's something I don't really like to do but on the other side I see no point, since I commented those things which needed attention (like how an image is actually saved and loaded). Other than that it's pretty obvious for anyone who is into scripting to understand what I do, I won't say I'm expert but all other things I did falls unto standard ruby (or in this case RGSS) syntax knowledge.

Glitch":3gwcio55 said:
Finally, on to formatting. This is the subject you need the least work on, and I'm guessing that at least some of the issues I'm seeing are a result of the code tags and not your scripting. First, when something goes to a second line, it's actually cleaner to indent it with a standard inde3nt, instead of indenting the second line to a point dependent on the first line. (I'm guessing you were using the first thing after the equals sign, but the formatting I see prevents me from being sure, because that is not what is actually there) Indenting with the same standard indent (2 spaces in RMXP) will result in code that looks cleaner and better formatted, because you don't have odd indentations all over the place.

Well (if I got you right here) that's more problem of this forum formatting scripts for showing than my coding. When I write it I do indenting for one space after each definition, condition and loop and I go back one space after end.

Glitch":3gwcio55 said:
Finally, I want to talk about line length. While you don't actually force me to scroll sideways, it does go all the way to the edge of the screen, if you're using default settings. I recommend that, if you're going to be using the screen as a guideline, you should make sure that nothing goes past the gray line they placed on the right. I tend to prefer leaving a full space between the end of any line of code and that border. While this may seem like a nitpick, it isn't. I say this because the way you have it set up, it looks like some lines should scroll to the side, and it makes people go for a scrollbar that isn't there. When you format it like Enterbrain did, it actually looks clean and easy to understand, far more than most scripts currently on this forum.

(Hope I understood here what you meant)
Ever saw some of the Tilemap rewrited classes here on forum. Although I haven't seen Seph's yet, some of them which I saw went waaay much in length putting much code in one line. In my case I try too put code in line as long as it doesn't go over the silver RGSS line, it's there for a reason, to let limit your writing. :)
Although there are some times when I really need to pass it.
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top