Main Menu
  • Welcome to The RPG Maker Resource Kit.

[RMVX] Extra Movement Frames

Started by modern algebra, January 20, 2008, 05:08:10 PM

0 Members and 1 Guest are viewing this topic.

modern algebra

Extra Movement Frames
Version: 1.0
Author: modern algebra
Date: January 20, 2008

Description



This script allows you to import characters with more than 3 movement frames. In other words, It allows you to make movement animation a little bit smoother, if that is what is desired. One use for it is it allows RMXP format characters to be imported into a VX game without editing (you'll need to rename the file though)

Features


  • Unlimited number of movement frames
  • Works on a character to character basis
  • Very easy to use

Screenshots

N/A for this kind of script

Instructions

Insert this script above main in the database. To add a character with extra movement frames, simply rename the character graphic to something of the form:
      !$%[<number of movement frames>]<Regular name>

Example: !$%[4]001-Fighter01    
That would make the graphic 001-Fighter01 be interpreted as having 4 frames

Script



#==============================================================================
#  Extra Movement Frames v. 1.0
#  Author: modern algebra (rmrk.net)
#  Date: January 20, 2008
#------------------------------------------------------------------------------
#   Instructions:
#     Insert this script above main in the database. To add a character with
#     extra movement frames, simply rename the character graphic to something
#     of the form:
#          !$%[<number of movement frames>]<Regular name>
#
#     Example: !$%[4]001-Fighter01    
#     That would make the graphic 001-Fighter01 be interpreted as having 4 frames
#------------------------------------------------------------------------------
# ** Game_Character
#------------------------------------------------------------------------------
#  Summary of changes:
#     aliased methods - update_animation
#     new class variables - height divisor, width divisor
#     new methods - calculate_divisors
#==============================================================================

class Game_Character
 #--------------------------------------------------------------------------
 # * Public Instance Variables
 #--------------------------------------------------------------------------
 attr_reader :height_divisor  # The height of a single frame
 attr_reader :width_divisor   # number of frames in the x direction
 attr_reader :char_frames
 #--------------------------------------------------------------------------
 # * Calculate Divisors
 #--------------------------------------------------------------------------
 #  Sets up the instance variables required
 #--------------------------------------------------------------------------
 def calculate_divisors
   return unless @previous_character.nil? || @previous_character != @character_name
   bitmap = Cache.character (@character_name)
   sign = @character_name[/^[\!\$].[\%]\[\d*\]/]
   if !sign.nil? && sign.size > 5
     @original_pattern = 0
     @width_divisor = sign[4, sign.size - 5].to_i
     @height_divisor = 4
     @char_frames = @width_divisor
   elsif !sign.nil? && sign.include? ('$')
     @width_divisor = 3
     @height_divisor = 4
     @char_frames = 3
   else
     @width_divisor = 12
     @height_divisor = 8
     @char_frames = 3
   end
   @previous_character = @character_name
 end
 #--------------------------------------------------------------------------
 # * Update Animation
 #--------------------------------------------------------------------------
 #  Change the hard coded values to ones dependent on character graphic format
 #--------------------------------------------------------------------------
 alias ma_extra_movement_frames_anim_upd update_animation
 def update_animation
   if @width_divisor == 12 || @width_divisor == 3
     ma_extra_movement_frames_anim_upd
     return
   end
   saved_anime_count = @anime_count
   pattern_original = @pattern
   speed = @move_speed + (dash? ? 1 : 0)
   ma_extra_movement_frames_anim_upd
   if (saved_anime_count > (18 - speed * 2)) && (@step_anime || (@stop_count <= 0))
     @pattern = (pattern_original + 1) % @char_frames
   end
 end
end

#==============================================================================
# * Sprite Character
#------------------------------------------------------------------------------
#  Summary of changes:
#     aliased methods - update_src_rect, update_bitmap
#==============================================================================

class Sprite_Character
 #--------------------------------------------------------------------------
 # * Update Src Rect
 #--------------------------------------------------------------------------
 #  Interpret multiple movement frames: Changed pattern
 #--------------------------------------------------------------------------
 alias ma_extra_movement_frames_src_rect_upd update_src_rect
 def update_src_rect
   if @tile_id == 0
     ma_extra_movement_frames_src_rect_upd
     index = @character.character_index
     pattern = @character.pattern < @character.char_frames ? @character.pattern : 1
     sx = (index % 4 * 3 + pattern) * @cw
     sy = (index / 4 * 4 + (@character.direction - 2) / 2) * @ch
     self.src_rect.set(sx, sy, @cw, @ch)
   end
 end
 #--------------------------------------------------------------------------
 # * Update Bitmap
 #--------------------------------------------------------------------------
 #  Change hard coded values to ones dependent on character graphic
 #--------------------------------------------------------------------------
 alias ma_extra_movement_frames_bmp_upd update_bitmap
 def update_bitmap
   @character.calculate_divisors
   saved_tile_id = @tile_id
   saved_character_name = @character_name
   saved_character_index = @character_index
   ma_extra_movement_frames_bmp_upd
   if saved_tile_id  != @character.tile_id or
      saved_character_name != @character.character_name or
      saved_character_index != @character.character_index
     unless @tile_id > 0
       @cw = bitmap.width / @character.width_divisor
       @ch = bitmap.height / @character.height_divisor
       self.ox = @cw / 2
       self.oy = @ch
     end
   end
 end
end

#==============================================================================
# ** Window Base
#------------------------------------------------------------------------------
#  Summary of changes:
#     overwritten methods - draw_character
#==============================================================================

class Window_Base
 #--------------------------------------------------------------------------
 # * Draw Charater (overwritten for extra movement frames)
 #     character_name  : the name of the character file
 #     character_index : the index of the character in the file
 #     x               : the x position to draw
 #     y               : the y position to draw
 #--------------------------------------------------------------------------
 def draw_character(character_name, character_index, x, y)
   return if character_name == nil
   bitmap = Cache.character(character_name)
   sign = character_name[/^[\!\$].[\%]\[\d*\]/]
   if !sign.nil? && sign.size > 5
     cw = bitmap.width / sign[4, sign.size - 5].to_i
     ch = bitmap.height / 4
   elsif sign != nil and sign.include?('$')
     cw = bitmap.width / 3
     ch = bitmap.height / 4
   else
     cw = bitmap.width / 12
     ch = bitmap.height / 8
   end
   n = character_index
   src_rect = Rect.new((n%4*3+1)*cw, (n/4*4)*ch, cw, ch)
   self.contents.blt(x - cw / 2, y - ch, bitmap, src_rect)
 end
end



Credit




  • modern algebra

Support



Just post here at rmrk if you have problems.

Known Compatibility Issues

Sorry, I overwrote a method (draw_character in Window_Base). Because of that, there might be some major compatibility issues. If I write a next version, my one goal will be to avoid overwriting that method, but it made things easier this time around.

Author's Notes



I wrote this a while ago, but with Synthesize posting VX scripts, I don't want to fall behind :P




Falcon


HEast

#2
QuoteWell, I would like to use it... BUT:
Known Compatibility Issues

Sorry, I overwrote a method (draw_character in Window_Base). Because of that, there might be some major compatibility issues. If I write a next version, my one goal will be to avoid overwriting that method, but it made things easier this time around.

Author's Notes



I wrote this a while ago, but with Synthesize posting VX scripts, I don't want to fall behind

Did you fixed it allready  ???
I really need that script.

Question:
!$%[8]001-Fighter01 <- Now Fighter01 should have 8 movement frames, right ?
But how should the Charset look like ?

Like this 8 x 4 (just an example):


Could you please make an example Charset for a Char with 6-8 movement frames ?

Im a bit confused  ???
Thnx.
Its Dangerous To Have A Signature These Days.

modern algebra

The one you posted is the correct format.

As for the compatibility thing - it will only be a problem is somebody else overwrites the draw_character method. I have yet to encounter another VX script that does, so you should be safe for now. If you do come across one. Post a link to it here and I will see if I can make them compatible.

HEast

#4
Quote from: modern algebra on May 28, 2008, 09:06:41 PM
The one you posted is the correct format.

As for the compatibility thing - it will only be a problem is somebody else overwrites the draw_character method. I have yet to encounter another VX script that does, so you should be safe for now. If you do come across one. Post a link to it here and I will see if I can make them compatible.
Just let me know if i understood u right.
So ur saying that the script is ok as long as not another script make use of that "draw_character"...
right or wrong ?
???
sry im pretty new to that "script" stuff  :dog:

BtW:
Is this ur forum ?
I see millions of ur scripts on other forums.
Looks like ur one of those smart brains ^^
I cant handle scripts but i can work pretty fine with common events... the old school ya know ^^

Thanks for all ur scripts your really a enrichment for the VX.
Its Dangerous To Have A Signature These Days.

modern algebra

No, other scripts can make use of that method too, they just can't overwrite it. If it's overwritten by another script, you'll have a problem in the menu and stuff where you expect to see your sprite drawn. Just don't worry about it though - I don't think it is that likely that another script will do that, so you'll probably not encounter any problems whatsoever.

And as to your question, this is the forum I am most active on yes, but I do not own the forum. That would be Roph, who is currently masquerading as Roach.

HEast

#6
Aha, cool  ;D
Well I actually just need your Extra Picture & Extra Sprites Script for my game coz everything is basecly build with common events.
So i wont get any trouble with yours & other scripts.
Thanks for your Scripts MA.
Cya  :huge:
Its Dangerous To Have A Signature These Days.

Ratty524

Nice script. I've been waiting for something like this.

Leventhan

Hmhmhm.
I may need to use this.

Great job, MA. ;8

Be kind, everyone you meet is fighting a hard battle.

lomastul

#9
hello modern algebra, i was wondering , is there any way to change this script to work well with a normal sprite sheet? [without the $ sign]
or to change kylock's 8 direction movement+sprite support to work with this script? because i have tryed any possible way to make them work well together,and well... they work, but it does not show any of the diagonal movement frames, so i was wondering if it is possible to edit this script or kylock's script to use a sprite sheet like: "!$%[6]Actor6" and that it will use 8 rows instead of 4 [for going up/down/left/right/lower right/upper right/lower left/upper left].
so 1st row will be used to walk up, 2nd row will be used to go left, 3rd will be used to go right, 4th will be used to go down, 5th will be used to go lower right, 6th to go to lower left, 7th will be used to go to upper left, and 8th will be used to go to upper right.
here's an example of a picture i intend to use:


and here is kylock's 8 direction movement + sprite support:
[spoiler]
[sub]#==============================================================================
# 8 Way Directional Movement
#------------------------------------------------------------------------------
# Kylock
# 21.3.2008
# Version 1.1
#==============================================================================
# Special thanks to Arrow-1 for the script request and supplying sprites for
#   testing purposes.
#==============================================================================
# Instructions:
#    Add this script towards the top, since methods are rewritten and not
#      aliased.  Once you add it and run your game, the script will
#      automagically enable 8-way directional movement for your hero.
# Features:
#    * Added movement functionality to allow your hero to move in diagonal
#        directions
#    * Corrects directional issues resulting from trying to activate events
#        while facing a diaganol direction. (could be better implemented,
#        but does work as it is)
#==============================================================================
# Changelog
#   1.0 Initial Release
#   1.1 Added support for no custom sprites and added compatibility with
#         Anaryu's Anti-Lag script (must be loaded above the anti-lag script)
#==============================================================================

#==============================================================================
# ** Script Configuration
#==============================================================================
module KMDM
  DIRSPRITE = true         # set to true if you are using a custom
                             # character sprite for diagonal movement
end

#==============================================================================
# ** Game_Player
#------------------------------------------------------------------------------
#  rewrote def move_by-input to enable extra directions
#==============================================================================

class Game_Player < Game_Character
  def move_by_input
    return unless movable?
    return if $game_map.interpreter.running?
    case Input.dir8
      when 1;  move_lower_left
      when 2;  move_down
      when 3;  move_lower_right
      when 4;  move_left
      when 7;  move_upper_left
      when 6;  move_right
      when 8;  move_up
      when 9;  move_upper_right
    end
  end
end

#==============================================================================
# ** Game_Character
#------------------------------------------------------------------------------
# Corrects direction so events will respond when hero is facing diagonal.
#  Modifies: def move_lower_left, def move_lower_right, def move_upper_left,
#            and def move_upper_right
#==============================================================================

class Game_Character
  #--------------------------------------------------------------------------
  # * Move Lower Left
  #--------------------------------------------------------------------------
  def move_lower_left(turn_ok = true)
    set_direction(5)
    if (passable?(@x, @y+1) and passable?(@x-1, @y+1)) or
       (passable?(@x-1, @y) and passable?(@x-1, @y+1))
      @x -= 1
      @y += 1
      increase_steps
      @move_failed = false
    else
      @move_failed = true
    end
  end
  #--------------------------------------------------------------------------
  # * Move Lower Right
  #--------------------------------------------------------------------------
  def move_lower_right(turn_ok = true)
    set_direction(3)
    if (passable?(@x, @y+1) and passable?(@x+1, @y+1)) or
       (passable?(@x+1, @y) and passable?(@x+1, @y+1))
      @x += 1
      @y += 1
      increase_steps
      @move_failed = false
    else
      @move_failed = true
    end
  end
  #--------------------------------------------------------------------------
  # * Move Upper Left
  #--------------------------------------------------------------------------
  def move_upper_left(turn_ok = true)
    if KMDM::DIRSPRITE == true
      set_direction(7)
    else
      set_direction(8)
    end
    if (passable?(@x, @y-1) and passable?(@x-1, @y-1)) or
       (passable?(@x-1, @y) and passable?(@x-1, @y-1))
      @x -= 1
      @y -= 1
      increase_steps
      @move_failed = false
    else
      @move_failed = true
    end
  end
  #--------------------------------------------------------------------------
  # * Move Upper Right
  #--------------------------------------------------------------------------
  def move_upper_right(turn_ok = true)
    set_direction(9)
    if (passable?(@x, @y-1) and passable?(@x+1, @y-1)) or
       (passable?(@x+1, @y) and passable?(@x+1, @y-1))
      @x += 1
      @y -= 1
      increase_steps
      @move_failed = false
    else
      @move_failed = true
    end
  end
end

#==============================================================================
# ** Sprite_Character
#------------------------------------------------------------------------------
# Adds functionality for diagonal character sprites.
#  Modifies: def update_src_rect
#==============================================================================

class Sprite_Character < Sprite_Base
  #--------------------------------------------------------------------------
  # * Update Transfer Origin Rectangle
  #--------------------------------------------------------------------------
  def update_src_rect
    if @tile_id == 0
      index = @character.character_index
      #if the character is facing diagonally, use the second spriteset
      if @character.direction % 2 != 0 && KMDM::DIRSPRITE == true
        index = @character.character_index + 1
      end
      pattern = @character.pattern < 3 ? @character.pattern : 1
      sx = (index % 4 * 3 + pattern) * @cw
      sy = (index / 4 * 4 + (@character.direction - 2) / 2) * @ch
      self.src_rect.set(sx, sy, @cw, @ch)
    end
  end
end
[/spoiler]

p.s will it work also with your running script? [with 6 frames aswell].
ill be waiting for your response.

--LoMastul



jedah vulture

#10
Quote from: lomastul on November 10, 2008, 02:33:58 PM
hello modern algebra, i was wondering , is there any way to change this script to work well with a normal sprite sheet? [without the $ sign]
or to change kylock's 8 direction movement+sprite support to work with this script? because i have tryed any possible way to make them work well together,and well... they work, but it does not show any of the diagonal movement frames, so i was wondering if it is possible to edit this script or kylock's script to use a sprite sheet like: "!$%[6]Actor6" and that it will use 8 rows instead of 4 [for going up/down/left/right/lower right/upper right/lower left/upper left].
so 1st row will be used to walk up, 2nd row will be used to go left, 3rd will be used to go right, 4th will be used to go down, 5th will be used to go lower right, 6th to go to lower left, 7th will be used to go to upper left, and 8th will be used to go to upper right.
here's an example of a picture i intend to use:


and here is kylock's 8 direction movement + sprite support:
[spoiler]
[sub]#==============================================================================
# 8 Way Directional Movement
#------------------------------------------------------------------------------
# Kylock
# 21.3.2008
# Version 1.1
#==============================================================================
# Special thanks to Arrow-1 for the script request and supplying sprites for
#   testing purposes.
#==============================================================================
# Instructions:
#    Add this script towards the top, since methods are rewritten and not
#      aliased.  Once you add it and run your game, the script will
#      automagically enable 8-way directional movement for your hero.
# Features:
#    * Added movement functionality to allow your hero to move in diagonal
#        directions
#    * Corrects directional issues resulting from trying to activate events
#        while facing a diaganol direction. (could be better implemented,
#        but does work as it is)
#==============================================================================
# Changelog
#   1.0 Initial Release
#   1.1 Added support for no custom sprites and added compatibility with
#         Anaryu's Anti-Lag script (must be loaded above the anti-lag script)
#==============================================================================

#==============================================================================
# ** Script Configuration
#==============================================================================
module KMDM
  DIRSPRITE = true         # set to true if you are using a custom
                             # character sprite for diagonal movement
end

#==============================================================================
# ** Game_Player
#------------------------------------------------------------------------------
#  rewrote def move_by-input to enable extra directions
#==============================================================================

class Game_Player < Game_Character
  def move_by_input
    return unless movable?
    return if $game_map.interpreter.running?
    case Input.dir8
      when 1;  move_lower_left
      when 2;  move_down
      when 3;  move_lower_right
      when 4;  move_left
      when 7;  move_upper_left
      when 6;  move_right
      when 8;  move_up
      when 9;  move_upper_right
    end
  end
end

#==============================================================================
# ** Game_Character
#------------------------------------------------------------------------------
# Corrects direction so events will respond when hero is facing diagonal.
#  Modifies: def move_lower_left, def move_lower_right, def move_upper_left,
#            and def move_upper_right
#==============================================================================

class Game_Character
  #--------------------------------------------------------------------------
  # * Move Lower Left
  #--------------------------------------------------------------------------
  def move_lower_left(turn_ok = true)
    set_direction(5)
    if (passable?(@x, @y+1) and passable?(@x-1, @y+1)) or
       (passable?(@x-1, @y) and passable?(@x-1, @y+1))
      @x -= 1
      @y += 1
      increase_steps
      @move_failed = false
    else
      @move_failed = true
    end
  end
  #--------------------------------------------------------------------------
  # * Move Lower Right
  #--------------------------------------------------------------------------
  def move_lower_right(turn_ok = true)
    set_direction(3)
    if (passable?(@x, @y+1) and passable?(@x+1, @y+1)) or
       (passable?(@x+1, @y) and passable?(@x+1, @y+1))
      @x += 1
      @y += 1
      increase_steps
      @move_failed = false
    else
      @move_failed = true
    end
  end
  #--------------------------------------------------------------------------
  # * Move Upper Left
  #--------------------------------------------------------------------------
  def move_upper_left(turn_ok = true)
    if KMDM::DIRSPRITE == true
      set_direction(7)
    else
      set_direction(8)
    end
    if (passable?(@x, @y-1) and passable?(@x-1, @y-1)) or
       (passable?(@x-1, @y) and passable?(@x-1, @y-1))
      @x -= 1
      @y -= 1
      increase_steps
      @move_failed = false
    else
      @move_failed = true
    end
  end
  #--------------------------------------------------------------------------
  # * Move Upper Right
  #--------------------------------------------------------------------------
  def move_upper_right(turn_ok = true)
    set_direction(9)
    if (passable?(@x, @y-1) and passable?(@x+1, @y-1)) or
       (passable?(@x+1, @y) and passable?(@x+1, @y-1))
      @x += 1
      @y -= 1
      increase_steps
      @move_failed = false
    else
      @move_failed = true
    end
  end
end

#==============================================================================
# ** Sprite_Character
#------------------------------------------------------------------------------
# Adds functionality for diagonal character sprites.
#  Modifies: def update_src_rect
#==============================================================================

class Sprite_Character < Sprite_Base
  #--------------------------------------------------------------------------
  # * Update Transfer Origin Rectangle
  #--------------------------------------------------------------------------
  def update_src_rect
    if @tile_id == 0
      index = @character.character_index
      #if the character is facing diagonally, use the second spriteset
      if @character.direction % 2 != 0 && KMDM::DIRSPRITE == true
        index = @character.character_index + 1
      end
      pattern = @character.pattern < 3 ? @character.pattern : 1
      sx = (index % 4 * 3 + pattern) * @cw
      sy = (index / 4 * 4 + (@character.direction - 2) / 2) * @ch
      self.src_rect.set(sx, sy, @cw, @ch)
    end
  end
end
[/spoiler]

p.s will it work also with your running script? [with 6 frames aswell].
ill be waiting for your response.

--LoMastul




I need exactly the same :D could you do it?
I'd also like your personal opinion about how many frames would be enough to make a character walk naturally, but without forcing the sistem too much...

modern algebra

I'll look into it, but I have quite a bit to do now, so don't expect anything for a while.

Kylock

Ok, here it is.

#==============================================================================
# 8 Way Directional Movement and Extra Movement Frames Compatibility Script
#------------------------------------------------------------------------------
# Kylock
# 9.1.2009
# Version 1.0
# Extra Movement Frames by modern algebra (rmrk.net)
#==============================================================================
# Requested by Lomastul
#==============================================================================
# Instructions:
#    Add this script BELOW the other two scripts.  The other scripts shoud work
#      in any order.  Ensure DIRSPRITE = true in the 8-way movement script.
#------------------------------------------------------------------------------
# ORIGINAL SCRIPTS:
#    8 Way Directional Movement by Kylock:
#       http://www.rpgrevolution.com/forums/index.php?showtopic=13487
#    Extra Movement Frames by modern algebra:
#       http://rmrk.net/index.php/topic,24191.0.html
#==============================================================================

#==============================================================================
# * Sprite Character
#------------------------------------------------------------------------------
#  Summary of changes:
#     aliased methods - update_src_rect, update_bitmap
#==============================================================================

class Sprite_Character
  #--------------------------------------------------------------------------
  # * Update Src Rect
  #--------------------------------------------------------------------------
  #  Interpret multiple movement frames: Changed pattern
  #--------------------------------------------------------------------------
  alias ma_extra_movement_frames_src_rect_upd2 update_src_rect
  def update_src_rect
    if @tile_id == 0
      ma_extra_movement_frames_src_rect_upd2
      index = @character.character_index
      #if the character is facing diagonally, use the second spriteset
      if @character.direction % 2 != 0 && KMDM::DIRSPRITE == true
        index = @character.character_index + 1
      end
      pattern = @character.pattern < @character.char_frames ? @character.pattern : 1
      sx = (index % 4 * @character.char_frames + pattern) * @cw
      sy = (index / 4 * 4 + (@character.direction - 2) / 2) * @ch
      self.src_rect.set(sx, sy, @cw, @ch)
    end
  end
  #--------------------------------------------------------------------------
  # * Update Bitmap
  #--------------------------------------------------------------------------
  #  Change hard coded values to ones dependent on character graphic
  #--------------------------------------------------------------------------
  alias ma_extra_movement_frames_bmp_upd2 update_bitmap
  def update_bitmap
    @character.calculate_divisors
    saved_tile_id = @tile_id
    saved_character_name = @character_name
    saved_character_index = @character_index
    ma_extra_movement_frames_bmp_upd2
    if saved_tile_id  != @character.tile_id or
       saved_character_name != @character.character_name or
       saved_character_index != @character.character_index
      unless @tile_id > 0
        if KMDM::DIRSPRITE
          @cw = bitmap.width / @character.width_divisor / 2
        else
          @ch = bitmap.height / @character.height_divisor
        end
        self.ox = @cw / 2
        self.oy = @ch
      end
    end
  end
end


I had to reformat your sprite for functionality.




Enjoy,
Kylock

modern algebra

Oh, cool. Thanks for doing all the work  ;D

I had forgotten all about this request.

Kylock

I see... so it's YOUR fault that Lomastul is buggin me on MSN =p

rafidelis

Very good script Modern Algebra ^ ^
I am amazed to see how you mastered the RGSS, a question you program in other languages?
Parabens by the script, he is very good

modern algebra

Well, thanks, though I would not consider myself a master of RGSS. This script is actually pretty old and there are a few things I'd do differently if I were to write the script today. And no, I don't program in other languages.

And yeah, sorry about that Kylock :P

bluegrazz

Dear Sir,

I registered to this site for 1 reason, and 1 reason only- To thank you for your skill and hard work and for sharing this with us so we can create great games without an understanding of "programming".

You Sir, have allowed me to do things with my game far beyond the scope of my knowledge and limits and for this I thank you immensely.

modern algebra

#18
Well, you're welcome.

I enjoy writing them when I can, and thanks for taking the effort to post that ~ it means a lot  :lol:

jwburks

I wish I could understand how this script worked... I feel like a complete moron. I don't know how I'm ever going to learn how to script that well.

jwburks

Been studying this script more closely the past few days... I can just about understand what's going on, except for one thing... I'll try to explain, here...

It seems to me that @character_pattern (or pattern, or whatever--it's called different things all over the place) represents the "frame" of animation. By default that would be 0 for the left frame, 1 for the middle (the standing-still-with-arms-at-both-sides frame) and 2 for the right frame.

What I can't figure out amongst all the junk going on is where what frame to be displayed is determined. "1" should be default in a normal 3/4 character sheet. The sequence in a default game seems to be "1, 2, 1, 0... 1, 2, 1, 0..."  If you have more than 3 frames in a sequence, not only should the default "stand-still" position be changed to a different number (in this case, it appears to be the variable @original_pattern, which is set to 0 for some reason)... and this scripts seems to play the sequence from 0 to the highest, then wrap around again...

If you had a character sheet 5 frames wide with the stand-still frame in the center (2), the sequence should play out (2, 3, 4, 3, 2, 1, 0, 1... 2, 3, 4, 3, 2, 1, 0, 1...)...

But I've looked all over in this script and the original and can't seem to figure out how the game determines which frame is played next... just can't figure it out.

modern algebra

In the update_animation method of Game_Character:


  #--------------------------------------------------------------------------
  # * Update Animation
  #--------------------------------------------------------------------------
  #  Change the hard coded values to ones dependent on character graphic format
  #--------------------------------------------------------------------------
  alias ma_extra_movement_frames_anim_upd update_animation
  def update_animation
    if @width_divisor == 12 || @width_divisor == 3
      ma_extra_movement_frames_anim_upd
      return
    end
    saved_anime_count = @anime_count
    pattern_original = @pattern
    speed = @move_speed + (dash? ? 1 : 0)
    ma_extra_movement_frames_anim_upd
    if (saved_anime_count > (18 - speed * 2)) && (@step_anime || (@stop_count <= 0))
      @pattern = (pattern_original + 1) % @char_frames
    end
  end


Most specifically:


    if (saved_anime_count > (18 - speed * 2)) && (@step_anime || (@stop_count <= 0))
      @pattern = (pattern_original + 1) % @char_frames
    end


pattern_original is basically just @pattern, preserved from before it is modified in the original method. So what that code does is add 1, and then use modular division. Modular division is basically it takes the remainder of the division. So, for instance,

5 % 3 = 2, since 5 = 1*(3) + 2. Or 34 % 6 = 4 because 34 = 5*(6) + 4. In general, x % y = x - (x / y), where division rounds down.

So:

@pattern = (pattern_original + 1) % @char_frames


adds 1, mods by the number of char_frames already determined. So, if @char_frames = 5, then we could run through each instance of the pattern. It starts at 1, since that is something I did not change:

1, then that code adds 1 and mods by 5, so 2, 3, 4, 0 (5 % 5 = 0). and then it goes back to 1.

jwburks

#22
I know what you mean, but it still doesn't make sense...
Take, for instance, the original script... don't even worry about the extra movement frames add-on, but take a look here at the original...

under Sprite_Character

#--------------------------------------------------------------------------
  # * Update Transfer Origin Rectangle
  #--------------------------------------------------------------------------
  def update_src_rect
    if @tile_id == 0
      index = @character.character_index
      pattern = @character.pattern < 3 ? @character.pattern : 1     # <-- Huh?
      sx = (index % 4 * 3 + pattern) * @cw
      sy = (index / 4 * 4 + (@character.direction - 2) / 2) * @ch
      self.src_rect.set(sx, sy, @cw, @ch)
    end
  end


Not sure what's going on in the 4th line. If I had to guess, pattern = character.pattern 1 (what is the : for?) unless character.pattern is less than 3... yeah I'm not complete in my search for ruby knowledge. I've seen ? before, sort of like an "if" on the fly... but ":" escapes me at the moment... could this be the answer, I wonder..
(edit:) Hm actually... it seems this means: pattern = @character.pattern if @character.pattern is less than 3, otherwise pattern = 1. I am more confused than before, now.

Anyway...
Under Game_Character...

#--------------------------------------------------------------------------
  # * Update Animation Count
  #--------------------------------------------------------------------------
  def update_animation
    speed = @move_speed + (dash? ? 1 : 0)
    if @anime_count > 18 - speed * 2
      if not @step_anime and @stop_count > 0
        @pattern = @original_pattern
      else
        @pattern = (@pattern + 1) % 4
      end
      @anime_count = 0
    end
  end


Follows the same formula, but modulus 4... and since @original_pattern = 1...
pattern = (pattern + 1) % 4
2
pattern = (pattern + 1) % 4
3
pattern = (pattern + 1) % 4
0
pattern = (pattern + 1) % 4
1


So... there are actually 4 patterns, even though in a character file you only have 3 frames horizontally... this tells me patterns are stored in a sequence somewhere. And the game seems to play them in the order of 1, 2, 1, 0, repeat... because 1, 2, 0, 1 ... would look ridiculous... hope I'm making sense there...

The question is, where is this sequence being stored, and how is the 1 2 1 0... order determined? This turned out more complicated than it seemed, I think....

Hm... maybe this is it, then...
okay, say @original_pattern = 1, which it is by default (the "standing" frame, the one in the middle... the one on the left is 0, and the one on the right is 2)...

the modulus division keeps the pattern incrementing by 1... BUT... this line here...

      pattern = @character.pattern < 3 ? @character.pattern : 1

This means that if the current pattern is 3 or more, then use pattern 1...

So, with that...

1..2..NOT 3, BUT 1, since 3 is NOT less than 3...0...1

So the pattern is 1 2 1 0... repeat...

Now, this works fine with default character sets... and I could be wrong here, but what do you think? Am I onto something?

modern algebra

OK, well you're right about the ? : thingy, basically:

pattern = @character.pattern < 3 ? @character.pattern : 1

is the same as:


if @character.pattern < 3
  pattern = @character.pattern
else
  pattern = 1
end


As for the other part, yes it is sequenced in the way you describe, but the sequence is calculated in the expression you are having trouble with. Consider the sequence as you describe it. 1 => 2 => 1 => 0.

Now put it through that conditional.

Let's do it on a case by case basis. Obviously the potential values for @character.pattern are 0, 1, 2, and 3, as you say.

So:


pattern = @character.pattern < 3 ? @character.pattern : 1

when @character.pattern = 0, it is less than 3, so pattern = @character.pattern = 0.
when @character.pattern = 1, it is less than 3, so pattern = @character.pattern = 1.
when @character.pattern = 2, it is less than 3, so pattern = @character.pattern = 2.
when @character.pattern = 3, it is not less than 3, so pattern = 1.


Thus, that forms the 1 => 2 => 1 => 0 sequence you have noted.

jwburks

Cool... well then... knowing that, one can come up with a formula to deal with just about any size of character file.