Chaos Project

RPG Maker => RPG Maker Scripts => Script Troubleshooting => Topic started by: TestScripts on June 30, 2012, 10:01:24 pm

Title: [XP] Isometry and 8-directional movement
Post by: TestScripts on June 30, 2012, 10:01:24 pm
Okay, so I got a nice script for isometric gameplay/height but the real issue with it was that to get to many places you'd end up tacking which is even more noticable and awkward in isometric gaming than it is in overhead. I found a basic (tile-based) diagonal movement script that allowed for 8-directional sprites and put that in the game.

The isometric script worked by creating a sub-map for events/blockages and a visual map for the isometric tiles so up/down/left/right movements are translated to diagonal movements and diagonal movements in the diagonal-movement script became straight. To call this awkward to control is an understatement. So I set about changing the controls so that this was corrected - up became diagonally up/right and so on. This was largely achieved by swapping around the 1/3/7/9 and 2/4/6/8 values in the diagonal movement and default player scripts.

The only problem this has created thus far is that whilst movement typically moves as it should the first moment you press up/down/left/right the character moves diagonally to the right for one square before continuing on its straight course. This only ever happens when you go from no input/movement to pressing a movement key. If you immediately switch from moving, say, up to down this will not occur. There is no issue with the actual diagonal movements either. What simple element have I missed here?

The modified Game_Player script:
#==============================================================================
# ** Game_Player
#------------------------------------------------------------------------------
#  This class handles the player. Its functions include event starting
#  determinants and map scrolling. Refer to "$game_player" for the one
#  instance of this class.
#==============================================================================

class Game_Player < Game_Character
  #--------------------------------------------------------------------------
  # * Invariables
  #--------------------------------------------------------------------------
  CENTER_X = (320 - 16) * 4   # Center screen x-coordinate * 4
  CENTER_Y = (240 - 16) * 4   # Center screen y-coordinate * 4
  #--------------------------------------------------------------------------
  # * Passable Determinants
  #     x : x-coordinate
  #     y : y-coordinate
  #     d : direction (0,2,4,6,8)
  #         * 0 = Determines if all directions are impassable (for jumping)
  #--------------------------------------------------------------------------
  def passable?(x, y, d)
    # Get new coordinates
    new_x = x + (d == 6 ? 1 : d == 4 ? -1 : 0)
    new_y = y + (d == 2 ? 1 : d == 8 ? -1 : 0)
    # If coordinates are outside of map
    unless $game_map.valid?(new_x, new_y)
      # Impassable
      return false
    end
    # If debug mode is ON and ctrl key was pressed
    if $DEBUG and Input.press?(Input::CTRL)
      # Passable
      return true
    end
    super
  end
  #--------------------------------------------------------------------------
  # * Set Map Display Position to Center of Screen
  #--------------------------------------------------------------------------
  def center(x, y)
    max_x = ($game_map.width - 20) * 128
    max_y = ($game_map.height - 15) * 128
    $game_map.display_x = [0, [x * 128 - CENTER_X, max_x].min].max
    $game_map.display_y = [0, [y * 128 - CENTER_Y, max_y].min].max
  end
  #--------------------------------------------------------------------------
  # * Move to Designated Position
  #     x : x-coordinate
  #     y : y-coordinate
  #--------------------------------------------------------------------------
  def moveto(x, y)
    super
    # Centering
    center(x, y)
    # Make encounter count
    make_encounter_count
  end
  #--------------------------------------------------------------------------
  # * Increaase Steps
  #--------------------------------------------------------------------------
  def increase_steps
    super
    # If move route is not forcing
    unless @move_route_forcing
      # Increase steps
      $game_party.increase_steps
      # Number of steps are an even number
      if $game_party.steps % 2 == 0
        # Slip damage check
        $game_party.check_map_slip_damage
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Get Encounter Count
  #--------------------------------------------------------------------------
  def encounter_count
    return @encounter_count
  end
  #--------------------------------------------------------------------------
  # * Make Encounter Count
  #--------------------------------------------------------------------------
  def make_encounter_count
    # Image of two dice rolling
    if $game_map.map_id != 0
      n = $game_map.encounter_step
      @encounter_count = rand(n) + rand(n) + 1
    end
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    # If party members = 0
    if $game_party.actors.size == 0
      # Clear character file name and hue
      @character_name = ""
      @character_hue = 0
      # End method
      return
    end
    # Get lead actor
    actor = $game_party.actors[0]
    # Set character file name and hue
    @character_name = actor.character_name
    @character_hue = actor.character_hue
    # Initialize opacity level and blending method
    @opacity = 255
    @blend_type = 0
  end
  #--------------------------------------------------------------------------
  # * Same Position Starting Determinant
  #--------------------------------------------------------------------------
  def check_event_trigger_here(triggers)
    result = false
    # If event is running
    if $game_system.map_interpreter.running?
      return result
    end
    # All event loops
    for event in $game_map.events.values
      # If event coordinates and triggers are consistent
      if event.x == @x and event.y == @y and triggers.include?(event.trigger)
        # If starting determinant is same position event (other than jumping)
        if not event.jumping? and event.over_trigger?
          event.start
          result = true
        end
      end
    end
    return result
  end
  #--------------------------------------------------------------------------
  # * Front Envent Starting Determinant
  #--------------------------------------------------------------------------
  def check_event_trigger_there(triggers)
    result = false
    # If event is running
    if $game_system.map_interpreter.running?
      return result
    end
    # Calculate front event coordinates
    new_x = @x + (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
    new_y = @y + (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
    # All event loops
    for event in $game_map.events.values
      # If event coordinates and triggers are consistent
      if event.x == new_x and event.y == new_y and
         triggers.include?(event.trigger)
        # If starting determinant is front event (other than jumping)
        if not event.jumping? and not event.over_trigger?
          event.start
          result = true
        end
      end
    end
    # If fitting event is not found
    if result == false
      # If front tile is a counter
      if $game_map.counter?(new_x, new_y)
        # Calculate 1 tile inside coordinates
        new_x += (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
        new_y += (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
        # All event loops
        for event in $game_map.events.values
          # If event coordinates and triggers are consistent
          if event.x == new_x and event.y == new_y and
             triggers.include?(event.trigger)
            # If starting determinant is front event (other than jumping)
            if not event.jumping? and not event.over_trigger?
              event.start
              result = true
            end
          end
        end
      end
    end
    return result
  end
  #--------------------------------------------------------------------------
  # * Touch Event Starting Determinant
  #--------------------------------------------------------------------------
  def check_event_trigger_touch(x, y)
    result = false
    # If event is running
    if $game_system.map_interpreter.running?
      return result
    end
    # All event loops
    for event in $game_map.events.values
      # If event coordinates and triggers are consistent
      if event.x == x and event.y == y and [1,2].include?(event.trigger)
        # If starting determinant is front event (other than jumping)
        if not event.jumping? and not event.over_trigger?
          event.start
          result = true
        end
      end
    end
    return result
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    # Remember whether or not moving in local variables
    last_moving = moving?
    # If moving, event running, move route forcing, and message window
    # display are all not occurring
    unless moving? or $game_system.map_interpreter.running? or
           @move_route_forcing or $game_temp.message_window_showing
      # Move player in the direction the directional button is being pressed
      case Input.dir4
      when 1
        move_down
      when 3
        move_left
      when 7
        move_right
      when 9
        move_up
      end
    end
    # Remember coordinates in local variables
    last_real_x = @real_x
    last_real_y = @real_y
    super
    # If character moves down and is positioned lower than the center
    # of the screen
    if @real_y > last_real_y and @real_y - $game_map.display_y > CENTER_Y
      # Scroll map down
      $game_map.scroll_down(@real_y - last_real_y)
    end
    # If character moves left and is positioned more let on-screen than
    # center
    if @real_x < last_real_x and @real_x - $game_map.display_x < CENTER_X
      # Scroll map left
      $game_map.scroll_left(last_real_x - @real_x)
    end
    # If character moves right and is positioned more right on-screen than
    # center
    if @real_x > last_real_x and @real_x - $game_map.display_x > CENTER_X
      # Scroll map right
      $game_map.scroll_right(@real_x - last_real_x)
    end
    # If character moves up and is positioned higher than the center
    # of the screen
    if @real_y < last_real_y and @real_y - $game_map.display_y < CENTER_Y
      # Scroll map up
      $game_map.scroll_up(last_real_y - @real_y)
    end
    # If not moving
    unless moving?
      # If player was moving last time
      if last_moving
        # Event determinant is via touch of same position event
        result = check_event_trigger_here([1,2])
        # If event which started does not exist
        if result == false
          # Disregard if debug mode is ON and ctrl key was pressed
          unless $DEBUG and Input.press?(Input::CTRL)
            # Encounter countdown
            if @encounter_count > 0
              @encounter_count -= 1
            end
          end
        end
      end
      # If C button was pressed
      if Input.trigger?(Input::C)
        # Same position and front event determinant
        check_event_trigger_here([0])
        check_event_trigger_there([0,1,2])
      end
    end
  end
end

The modified diagonal movement script:
#==============================================================================
# Test
#==============================================================================

#==============================================================================
# ¡ Game_Player
#==============================================================================

class Game_Player < Game_Character
#--------------------------------------------------------------------------
# œ ƒtƒŒ[ƒ€XV
#--------------------------------------------------------------------------
alias update_para_quarter update
def update
   update_para_quarter
   unless moving? or $game_system.map_interpreter.running? or
          @move_route_forcing or $game_temp.message_window_showing
     # •ûŒüƒ{ƒ^ƒ",ª‰Ÿ,³,ê,Ä,¢,ê,΁A,»,Ì•ûŒü,ÖƒvƒŒƒCƒ,,[,ðˆÚ"®
     case Input.dir8
     when 4  # ¶‰º,ɈÚ"®
       move_lower_left
     when 2  # ‰E‰º,ɈÚ"®
       move_lower_right
     when 8  # ¶ã,ɈÚ"®
       move_upper_left
     when 6  # ‰Eã,ɈÚ"®
       move_upper_right
     end
   end
end
end

#==============================================================================
# ¡ Sprite_Character
#==============================================================================

class Sprite_Character < RPG::Sprite
#--------------------------------------------------------------------------
# œ ƒtƒŒ[ƒ€XV
#--------------------------------------------------------------------------
alias update_para_quarter update
def update
   update_para_quarter
   if @tile_id == 0
     if (@character.direction - 2) % 2 == 1
       # ŽÎ,߉æ'œ,Ì--L-³,ðƒ`ƒFƒbƒN
       if quarter_graphic_exist?(@character)
         # ŽÎ,߉æ'œ,ðƒZƒbƒg
         if character.dash_on and dash_quarter_graphic_exist?(@character)
           @character_name = @character.character_name + "_dash_quarter"
         else
           @character_name = @character.character_name + "_quarter"
         end
         self.bitmap = RPG::Cache.character(@character_name,
           @character.character_hue)
         # Œü,«,ðŽæ"¾
         case @character.direction
           when 1
             n = 0
           when 3
             n = 2
           when 7
             n = 1
           when 9
             n = 3
         end
       else
         @character.direction = @character.sub_direction
         # ŽÎ,߉æ'œ,ª'¶Ý,µ,È,¢,Æ,«,ÌŒü,«
         n = (@character.direction - 2) / 2
       end
       # "]'--Œ³,Ì‹éŒ`,ðÝ'è
       sx = @character.pattern * @cw
       sy = n * @ch
       self.src_rect.set(sx, sy, @cw, @ch)
     else
       self.bitmap = RPG::Cache.character(@character.character_name,
         @character.character_hue)
       # "]'--Œ³,Ì‹éŒ`,ðÝ'è
       sx = @character.pattern * @cw
       sy = (@character.direction - 2) / 2 * @ch
       self.src_rect.set(sx, sy, @cw, @ch)
     end
   end
end
#--------------------------------------------------------------------------
# › ŽÎ,߉æ'œ,Ì--L-³,ðƒ`ƒFƒbƒN
#--------------------------------------------------------------------------
def quarter_graphic_exist?(character)
   # "Ç,ݍž,݃eƒXƒg
   begin
     RPG::Cache.character(character.character_name.to_s + "_quarter", character.character_hue)
   rescue
     return false
   end
   return true
end
#--------------------------------------------------------------------------
# › ŽÎ,߃_ƒbƒVƒ...‰æ'œ,Ì--L-³,ðƒ`ƒFƒbƒN
#--------------------------------------------------------------------------
def dash_quarter_graphic_exist?(character)
   # "Ç,ݍž,݃eƒXƒg
   begin
     RPG::Cache.character(character.character_name.to_s + "_dash_quarter", character.character_hue)
   rescue
     return false
   end
   return true
end
end

#==============================================================================
# ¡ Game_Character
#==============================================================================

class Game_Character
#--------------------------------------------------------------------------
# œ ŒöŠJƒCƒ"ƒXƒ^ƒ"ƒX•ϐ"
#--------------------------------------------------------------------------
attr_accessor   :direction        # Œü,«
attr_accessor   :sub_direction    # ŽÎ,߉æ'œ,ª'¶Ý,µ,È,¢,Æ,«,ÌŒü,«
#--------------------------------------------------------------------------
# œ ¶‰º,ɈÚ"®
#--------------------------------------------------------------------------
def move_lower_left
   # Œü,«ŒÅ'è,Å,È,¢ê‡
   unless @direction_fix
     @sub_direction = @direction
     @direction = 4
     # ‰EŒü,«,¾,Á,½ê‡,͍¶,ðAãŒü,«,¾,Á,½ê‡,͉º,ðŒü,­
     @sub_direction = (@sub_direction == 6 ? 4 : @sub_direction == 8 ? 2 : @sub_direction)
   end
   # ‰º¨¶A¶¨‰º ,Ì,Ç,¿,ç,©,̃R[ƒX,ª'ʍs‰Â"\,ȏꍇ
   if (passable?(@x, @y, 2) and passable?(@x, @y + 1, 4)) or
      (passable?(@x, @y, 4) and passable?(@x - 1, @y, 2))
     # À•W,ðXV
     @x -= 1
     @y += 1
     # •à"'‰Á
     increase_steps
   end
end
#--------------------------------------------------------------------------
# œ ‰E‰º,ɈÚ"®
#--------------------------------------------------------------------------
def move_lower_right
   # Œü,«ŒÅ'è,Å,È,¢ê‡
   unless @direction_fix
     @sub_direction = @direction
     @direction = 2
     # ¶Œü,«,¾,Á,½ê‡,͉E,ðAãŒü,«,¾,Á,½ê‡,͉º,ðŒü,­
     @sub_direction = (@sub_direction == 4 ? 6 : @sub_direction == 8 ? 2 : @sub_direction)
   end
   # ‰º¨‰EA‰E¨‰º ,Ì,Ç,¿,ç,©,̃R[ƒX,ª'ʍs‰Â"\,ȏꍇ
   if (passable?(@x, @y, 2) and passable?(@x, @y + 1, 6)) or
      (passable?(@x, @y, 6) and passable?(@x + 1, @y, 2))
     # À•W,ðXV
     @x += 1
     @y += 1
     # •à"'‰Á
     increase_steps
   end
end
#--------------------------------------------------------------------------
# œ ¶ã,ɈÚ"®
#--------------------------------------------------------------------------
def move_upper_left
   # Œü,«ŒÅ'è,Å,È,¢ê‡
   unless @direction_fix
     @sub_direction = @direction
     @direction = 8
     # ‰EŒü,«,¾,Á,½ê‡,͍¶,ðA‰ºŒü,«,¾,Á,½ê‡,͏ã,ðŒü,­
     @sub_direction = (@sub_direction == 6 ? 4 : @sub_direction == 2 ? 8 : @sub_direction)
   end
   # ã¨¶A¶¨ã ,Ì,Ç,¿,ç,©,̃R[ƒX,ª'ʍs‰Â"\,ȏꍇ
   if (passable?(@x, @y, 8) and passable?(@x, @y - 1, 4)) or
      (passable?(@x, @y, 4) and passable?(@x - 1, @y, 8))
     # À•W,ðXV
     @x -= 1
     @y -= 1
     # •à"'‰Á
     increase_steps
   end
end
#--------------------------------------------------------------------------
# œ ‰Eã,ɈÚ"®
#--------------------------------------------------------------------------
def move_upper_right
   # Œü,«ŒÅ'è,Å,È,¢ê‡
   unless @direction_fix
     @sub_direction = @direction
     @direction = 6
     # ¶Œü,«,¾,Á,½ê‡,͉E,ðA‰ºŒü,«,¾,Á,½ê‡,͏ã,ðŒü,­
     @sub_direction = (@sub_direction == 4 ? 6 : @sub_direction == 2 ? 8 : @sub_direction)
   end
   # ã¨‰EA‰E¨ã ,Ì,Ç,¿,ç,©,̃R[ƒX,ª'ʍs‰Â"\,ȏꍇ
   if (passable?(@x, @y, 8) and passable?(@x, @y - 1, 6)) or
      (passable?(@x, @y, 6) and passable?(@x + 1, @y, 8))
     # À•W,ðXV
     @x += 1
     @y -= 1
     # •à"'‰Á
     increase_steps
   end
end
#--------------------------------------------------------------------------
# › ƒ_ƒbƒVƒ...ƒXƒNƒŠƒvƒg"±"ü"»'è
#--------------------------------------------------------------------------
def dash_on
   if @dash_on != nil
     return @dash_on
   else
     return false
   end
end
end
Title: Re: [XP] Isometry and 8-directional movement
Post by: Zexion on August 09, 2012, 11:52:55 am
I don't know how to fix that, but I also use an isometric script and I searched around for like months. The best ones I've found are these:

1. http://save-point.org/thread-4046.html
2. http://save-point.org/thread-2578.html

1. This one seems to be the best overall engine for an isometric game, but it is very complicated to learn. It has a config where you can switch between the controls that you metioned feel awkward and the controls you are trying to get.

2. This is the easiest and most compatible one. You can set up a custom number of walking frames, and even running/jumping/sneaking/attacking/magic frames. Each is optional, and with the correct configuration can make developing the game easy. I use this just for the 8-directional sprites and jumping.
Also supports using a ninth(first frame) frame as a standing frame.