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.

[VX] New 8 way Movement

Simple 8 way Movement Version 2
By: Near

Introduction

This script makes your player/events move in 8 directions with passibility support.

ANOTHER UPDATE: Isometric event triggers! Disabling the 8 directional sprites for certain events!
Always on top is back!!

Passibility support explanation

The passability support was implement into the diagonal movements, for added
realism. When you try to move up/left, and there is an impassible tile to the left
of you, it checks if you can move up, and if that tile is passable, you move up
and vice versa.

Features
  • 8 way movement (duh!)
  • Simple-yet-effective passibility support
  • Random movement is 8 directional (This can be turned off)
  • 8 directional sprite support!!
  • many 8 directional movements (that can be turned off)
  • the ability to disable the 8 directional sprites for certain events!
  • always on top is restored (rmxp feature) !
  • 8 directional event triggers (includes action button) !

Screenshots

Can't really have screenshots of motion now can i?

Demo

Maybe later...

Script

Code:
 

module Dir8Move

  Dir8Sprite =  true  # 8 Directional sprites??

  Dir8Events =  true  # 8 Direction event movement??

  DashSprites = true  # Sprites for dashing?

  def self.comment_input(*args) # Hooray for the SDK!!

    parameters = []

    unless args[0].is_a?(Game_Event)

      return nil

    end

    list = *args[0].list

    elements = *args[1]

    trigger = *args[2]

    return nil if list == nil

    return nil unless list.is_a?(Array)

    for item in list

      next if item.code != 108

      if item.parameters[0] == trigger

        start = list.index(item) + 1

        finish = start + elements

        for id in start...finish

          next if !list[id]

          parameters.push(list[id].parameters[0])

        end

        return parameters

      end

    end

    return nil

  end

end

 

class Game_Character

  attr_accessor :always_on_top

  alias old_init initialize

  alias old_screen_z screen_z

  def initialize

    old_init

    @always_on_top = false

  end

  def screen_z

    if @always_on_top

      return 999

    end

    old_screen_z

  end

  def set_always_on_top(bool)

    @always_on_top = bool

  end

  #--------------------------------------------------------------------------

  # * Move Lower Left

  #--------------------------------------------------------------------------

  def move_lower_left(turn_ok=true)

    @direction = 5 if turn_ok

    if passable?(@x-1,@y+1) && passable?(@x-1,@y) && passable?(@x,@y+1)

      unless @direction_fix

        @direction = 5

      end

      @x -= 1

      @y += 1

      increase_steps

      @move_failed = false

    else

      return if check_event_trigger_touch(@x-1,@y+1)

      return if check_event_trigger_touch(@x-1,@y)

      return if check_event_trigger_touch(@x,@y+1)

      if passable?(@x-1,@y)

        @x -= 1

        return

      elsif passable?(@x,@y+1)

        @y += 1

        return

      end

      @move_failed = true

    end

  end

  #--------------------------------------------------------------------------

  # * Move Lower Right

  #--------------------------------------------------------------------------

  def move_lower_right(turn_ok=true)

    @direction = 3 if turn_ok

    if passable?(@x+1,@y+1) && passable?(@x+1,@y) && passable?(@x,@y+1)

      unless @direction_fix

        @direction = 3

      end

      @x += 1

      @y += 1

      increase_steps

      @move_failed = false

    else

      return if check_event_trigger_touch(@x+1,@y+1)

      return if check_event_trigger_touch(@x+1,@y)

      return if check_event_trigger_touch(@x,@y+1)

      if passable?(@x+1,@y)

        @x += 1

        return

      elsif passable?(@x,@y+1)

        @y += 1

        return

      end

      @move_failed = true

    end

  end

  #--------------------------------------------------------------------------

  # * Move Upper Left

  #--------------------------------------------------------------------------

  def move_upper_left(turn_ok=true)

    @direction = 7 if turn_ok

    if passable?(@x-1, @y-1) && passable?(@x-1,@y) && passable?(@x,@y-1)

      unless @direction_fix

        @direction = 7

      end

      @x -= 1

      @y -= 1

      increase_steps

      @move_failed = false

    else

      return if check_event_trigger_touch(@x-1,@y-1)

      return if check_event_trigger_touch(@x-1,@y)

      return if check_event_trigger_touch(@x,@y-1)

      if passable?(@x-1,@y)

        @x -= 1

        return

      elsif passable?(@x,@y-1)

        @y -= 1

        return

      end

      @move_failed = true

    end

  end

  #--------------------------------------------------------------------------

  # * Move Upper Right

  #--------------------------------------------------------------------------

  def move_upper_right(turn_ok=true)

    @direction = 9 if turn_ok

    if passable?(@x+1, @y-1) && passable?(@x+1,@y) && passable?(@x,@y-1)

      unless @direction_fix

        @direction = 9

      end

      @x += 1

      @y -= 1

      increase_steps

      @move_failed = false

    else

      return if check_event_trigger_touch(@x+1,@y-1)

      return if check_event_trigger_touch(@x+1,@y)

      return if check_event_trigger_touch(@x,@y-1)

      if passable?(@x+1,@y)

        @x += 1

        return

      elsif passable?(@x,@y-1)

        @y -= 1

        return

      end

      @move_failed = true

    end

  end

  #--------------------------------------------------------------------------

  # * Move at Random

  #--------------------------------------------------------------------------

  if Dir8Move::Dir8Events

    def move_random

      case rand(8)

      when 0;  move_down(false);  when 1;  move_left(false)

      when 2; move_right(false);  when 3;  move_up(false)

      when 4;  move_lower_left(false);  when 5;  move_lower_right(false)

      when 6;  move_upper_left(false);  when 7;  move_upper_right(false)

      end

    end

   #--------------------------------------------------------------------------

  # * Move toward Player

  #--------------------------------------------------------------------------

  def move_toward_player

    # Get difference in player coordinates

    sx = distance_x_from_player

    sy = distance_y_from_player

    # If coordinates are equal

    if sx == 0 and sy == 0

      return

    end

    # Get absolute value of difference

    abs_sx = sx.abs

    abs_sy = sy.abs

    #get diagonal differences

    sh = (abs_sx / 2) - abs_sy

    sv = (abs_sy / 2) - abs_sx

    # Is the player more towards a 45? angle?

    if abs_sx == abs_sy || (sv < 0 and sh < 0)

      if $game_player.y > @y

        #if the player is lower left

        if $game_player.x < @x

          move_lower_left

        #If the player is lower right

        else

          move_lower_right

        end

      else

        #if the player is upper left

        if $game_player.x < @x

          move_upper_left

        #if the player is upper right

        else

          move_upper_right

        end

      end

    # If horizontal distance is longer

    elsif abs_sx > abs_sy

      # Move towards player, prioritize left and right directions

      sx > 0 ? move_left : move_right

      if not moving? and sy != 0

        sy > 0 ? move_up : move_down

      end

    # If vertical distance is longer

    else

      # Move towards player, prioritize up and down directions

      sy > 0 ? move_up : move_down

      if not moving? and sx != 0

        sx > 0 ? move_left : move_right

      end

    end

  end

  #--------------------------------------------------------------------------

  # * Move away from Player

  #--------------------------------------------------------------------------

  def move_away_from_player

    # Get difference in player coordinates

    sx = distance_x_from_player

    sy = distance_y_from_player

    # If coordinates are equal

    if sx == 0 and sy == 0

      return

    end

    # Get absolute value of difference

    abs_sx = sx.abs

    abs_sy = sy.abs

    #get diagonal differences

    sh = (abs_sx / 2) - abs_sy

    sv = (abs_sy / 2) - abs_sx

    # Is the player more towards a 45? angle?

    if abs_sx == abs_sy || (sv < 0 and sh < 0)

      if $game_player.y > @y

        #if the player is lower left

        if $game_player.x < @x

          move_upper_right

        #If the player is lower right

        else

          move_upper_left

        end

      else

        #if the player is upper left

        if $game_player.x < @x

          move_lower_right

        #if the player is upper right

        else

          move_lower_left

        end

      end

    # If horizontal distance is longer

    elsif abs_sx > abs_sy

      # Move away from player, prioritize left and right directions

      sx > 0 ? move_right : move_left

      if not moving? and sy != 0

        sy > 0 ? move_down : move_up

      end

    # If vertical distance is longer

    else

      # Move away from player, prioritize up and down directions

      sy > 0 ? move_down : move_up

      if not moving? and sx != 0

        sx > 0 ? move_right : move_left

      end

    end

  end

  #--------------------------------------------------------------------------

  # * 1 Step Forward

  #--------------------------------------------------------------------------

  def move_forward

    case @direction

    when 2;  move_down(false);  when 8;  move_up(false)

    when 4;  move_left(false);  when 6;  move_right(false)

    when 5;  move_lower_left(false); when 3;  move_lower_right(false)

    when 7;  move_upper_left(false); when 3;  move_upper_right(false)

    end

  end

  #--------------------------------------------------------------------------

  # * 1 Step Backward

  #--------------------------------------------------------------------------

  def move_backward

    last_direction_fix = @direction_fix

    @direction_fix = true

    case @direction

    when 2;  move_up(false);  when 8;  move_down(false)

    when 4;  move_right(false);  when 6;  move_left(false)

    when 5;  move_lower_left(false); when 3;  move_lower_right(false)

    when 7;  move_upper_left(false); when 3;  move_upper_right(false)

    end

    @direction_fix = last_direction_fix

  end

  #--------------------------------------------------------------------------

  # * Turn Lower Left

  #--------------------------------------------------------------------------

  def turn_lower_left

    unless @direction_fix

      @direction = 5

      @stop_count = 0

    end

  end

  #--------------------------------------------------------------------------

  # * Turn Lower Right

  #--------------------------------------------------------------------------

  def turn_lower_right

    unless @direction_fix

      @direction = 3

      @stop_count = 0

    end

  end

  #--------------------------------------------------------------------------

  # * Turn Upper Left

  #--------------------------------------------------------------------------

  def turn_upper_left

    unless @direction_fix

      @direction = 7

      @stop_count = 0

    end

  end

  #--------------------------------------------------------------------------

  # * Turn Upper Right

  #--------------------------------------------------------------------------

  def turn_upper_right

    unless @direction_fix

      @direction = 9

      @stop_count = 0

    end

  end

  #--------------------------------------------------------------------------

  # * Turn 90? Right

  #--------------------------------------------------------------------------

  def turn_right_90

    case @direction

    when 2

      turn_left

    when 4

      turn_up

    when 6

      turn_down

    when 8

      turn_right

    when 1

      turn_upper_left

    when 3

      turn_lower_left

    when 7

      turn_upper_right

    when 9

      turn_lower_right

    end

  end

  #--------------------------------------------------------------------------

  # * Turn 90? Left

  #--------------------------------------------------------------------------

  def turn_left_90

    case @direction

    when 2

      turn_right

    when 4

      turn_down

    when 6

      turn_up

    when 8

      turn_left

    when 1

      turn_upper_right

    when 3

      turn_upper_left

    when 7

      turn_lower_right

    when 9

      turn_lower_left

    end

  end

  #--------------------------------------------------------------------------

  # * Turn 180?

  #--------------------------------------------------------------------------

  def turn_180

    case @direction

    when 2

      turn_up

    when 4

      turn_right

    when 6

      turn_left

    when 8

      turn_down

    when 1

      turn_upper_left

    when 3

      turn_lower_left

    when 7

      turn_upper_right

    when 9

      turn_lower_right

    end

  end

  #--------------------------------------------------------------------------

  # * Turn 90? Right or Left

  #--------------------------------------------------------------------------

  def turn_right_or_left_90

    if rand(2) == 0

      turn_right_90

    else

      turn_left_90

    end

  end

  #--------------------------------------------------------------------------

  # * Turn at Random

  #--------------------------------------------------------------------------

  def turn_random

    case rand(8)

    when 0

      turn_up

    when 1

      turn_right

    when 2

      turn_left

    when 3

      turn_down

    when 4

      turn_lower_left

    when 5

      turn_lower_right

    when 6

      turn_upper_left

    when 7

      turn_upper_right

    end

  end

  #--------------------------------------------------------------------------

  # * Turn 45? Right

  #--------------------------------------------------------------------------

  def turn_right_45

    case @direction

    when 2

      turn_lower_left

    when 4

      turn_upper_left

    when 6

      turn_lower_right

    when 8

      turn_upper_right

    when 1

      turn_left

    when 3

      turn_down

    when 7

      turn_up

    when 9

      turn_right

    end

  end

  #--------------------------------------------------------------------------

  # * Turn 45? Left

  #--------------------------------------------------------------------------

  def turn_left_45

    case @direction

    when 2

      turn_lower_right

    when 4

      turn_lower_left

    when 6

      turn_upper_right

    when 8

      turn_upper_left

    when 1

      turn_down

    when 3

      turn_right

    when 7

      turn_left

    when 9

      turn_up

    end

  end

  #--------------------------------------------------------------------------

  # * Turn 45? Right or Left

  #--------------------------------------------------------------------------

  def turn_right_or_left_45

    if rand(2) == 0

      turn_right_45

    else

      turn_left_45

    end

  end

  #--------------------------------------------------------------------------

  # * Turn Towards Player

  #--------------------------------------------------------------------------

  def turn_toward_player

    # Get difference in player coordinates

    sx = distance_x_from_player

    sy = distance_y_from_player

    # If coordinates are equal

    if sx == 0 and sy == 0

      return

    end

    # Get absolute value of difference

    abs_sx = sx.abs

    abs_sy = sy.abs

    #get diagonal differences

    sh = (abs_sx / 2) - abs_sy

    sv = (abs_sy / 2) - abs_sx

    # If the diagonal distance is equal

    if (sh == 0 or sv == 0) &&

       ((abs_sx != 1 and abs_sy != 0) or (abs_sx != 0 and abs_sy != 1))

      return

    end

    # Is the player more towards a 45? angle?

    if abs_sx == abs_sy || (sv < 0 and sh < 0)

      if $game_player.y > @y

        #if the player is lower left

        if $game_player.x < @x

          turn_lower_left

        #If the player is lower right

        else

          turn_lower_right

        end

      else

        #if the player is upper left

        if $game_player.x < @x

          turn_upper_left

        #if the player is upper right

        else

          turn_upper_right

        end

      end

    # If horizontal distance is longer

    elsif abs_sx > abs_sy

      # Turn to the right or left toward player

      sx > 0 ? turn_left : turn_right

    # If vertical distance is longer

    else

      # Turn up or down toward player

      sy > 0 ? turn_up : turn_down

    end

  end

  #--------------------------------------------------------------------------

  # * Turn Away from Player

  #--------------------------------------------------------------------------

  def turn_away_from_player

    # Get difference in player coordinates

    sx = distance_x_from_player

    sy = distance_y_from_player

    # If coordinates are equal

    if sx == 0 and sy == 0

      return

    end

    # Get absolute value of difference

    abs_sx = sx.abs

    abs_sy = sy.abs

    #get diagonal differences

    sh = (abs_sx / 2) - abs_sy

    sv = (abs_sy / 2) - abs_sx

    # If the diagonal distance is equal

    if (sh == 0 or sv == 0) &&

       ((abs_sx != 1 and abs_sy != 0) or (abs_sx != 0 and abs_sy != 1))

      return

    end

    # Is the player more towards a 45? angle?

    if abs_sx == abs_sy || (sv < 0 and sh < 0)

      if $game_player.y > @y

        #if the player is lower left

        if $game_player.x < @x

          turn_upper_right

        #If the player is lower right

        else

          turn_upper_left

        end

      else

        #if the player is upper left

        if $game_player.x < @x

          turn_lower_right

        #if the player is upper right

        else

          turn_lower_left

        end

      end

    # If horizontal distance is longer

    elsif abs_sx > abs_sy

      # Turn to the right or left away from player

      sx > 0 ? turn_right : turn_left

    # If vertical distance is longer

    else

      # Turn up or down away from player

      sy > 0 ? turn_down : turn_up

    end

  end

  end

end

 

class Game_Event < Game_Character

  attr_accessor :direction

end

 

class Game_Player

  def move_by_input

    return unless movable? && !$game_map.interpreter.running?

    case Input.dir8

    when 2;  move_down;  when 8;  move_up

    when 4;  move_left;  when 6;  move_right

    when 1;  move_lower_left;  when 3;  move_lower_right

    when 7;  move_upper_left;  when 9;  move_upper_right

    end

  end

end

 

class Sprite_Character < Sprite_Base

  def update_src_rect

    if @tile_id == 0

      index = @character.character_index

      index += 1 if @character.direction%2 != 0 && Dir8Move::Dir8Sprite

      index += 2 if @character.dash? && Dir8Move::DashSprites

      comment = Dir8Move.comment_input(character, 2, 'Dir8Comment')

      if @character.direction%2 != 0 && comment_nodir8(comment)

        @character.direction = make_dir

        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

  def comment_nodir8(comment = [])

    return false unless @character.is_a?(Game_Event)

    return false if comment == nil

    return comment.include?('Disable Dir8Sprite')

  end

  def make_dir

    case @character.direction

    when 5

      result = 2

    when 3

      result = 2

    when 7

      result = 8

    when 9

      result = 8

    end

    return result

  end

end

 

class Game_Map

  def x_with_direction(x, direction)

    case direction

    when 4..5;  r = -1

    when 3;  r = 1

    when 6;  r = 1

    when 7;  r = -1

    when 9;  r = 1

    else;  r = 0

    end

    return round_x(x+r)

  end

  def y_with_direction(y, direction)

    case direction

    when 2..3;  r = 1

    when 5;  r = 1

    when 7..9;  r = -1

    else;  r = 0

    end

    return round_y(y+r)

  end

end

 

 

Instructions

This script is essentially plug 'n' play. Just edit 'Dir8Random = true' to turn off 8 way
random movement. Also, you need to have spritesets like this:

One more thing: You can disable the event 8 directional sprites, by putting 2 comments in an event's list.

Comment: Dir8Comment
Comment: Disable Dir8Sprite

FAQ

No question yet...

Compatibility

Not sure, should be compatible with anything but maybe a pixel-movement script.

Author's Notes

I like pie, especially dutch apple.

Also, I thank the SDK Team for the 'comment_input()' method.

Terms and Conditions

Please give credit if you use this, it was really hard to figure out the 'move_toward_player' type commands!
 
Hmmm... simple and easy, I LIKE IT!
good job, but something that im sure everyone would like is being able to use diogonal sprites when moving diogonaly with the character. Could u add that in as well?
 
I'm either missing the 1.4 in there, or you didn't take care of the altered movement speed the character needs for diagonal movement. The modifier is the square root of 2, being roughly 1.414. You should definately include that.

Other than that, nice job. It's indeed very simple, so just what everyone needs. Yay for specialized scripts instead of huge packages! :thumb: 8-way-sprite support wouldn't hurt, though...

Keep up the excellent work!
 
A'ight, I'll do that. I was going to put in the reduced move speed, but I decided against it, because the diagonal movement didn't look too much
faster.

Also, I'm going to look into 8-directional sprite support tonight.
 
COOL! u added the sprite support!
but how do u work it though? does the 8-way sprite need to be right next to the normal sprite?
 
Yeah, just look at the example spritesheet. you put the vertical and horizontal facing in one part of the sheet, and the VERY next part of the sheet must have his diagonals.

Also, if you have the 'Dir8Events' on then your 'Approach' and 'Random' move types, they will have 8 directions.

And, one more thing I forgot to mention something! I have restored the 'Always on top' attribute, just put in an event a 'Set move route', and go to script and put in 'set_always_on_top(<true or false>)'.
 
Thats cool, i'll just take off that feature for the events i guess...
Is there also a wasy to switch the 8-way walking sprites to running sprites when a person runs?
 
If you take off the Dir8Events, it will only disable the 8 directional move types.
I'll see if I can make events not need 8 directional sprites, and I'll make dashing options if I can. Thanks for the feedback ^^ don't understand why other people can't give any though. :|:
 
I have a question: Are there exact dimensions for the spritesheets or is it double the actual sprite width+height?

Edit: NVM worked it out. I have another question: Can you talk to events ISO? Like from a diagonal view? If not are you going to add this feature?
 
UPDATE!! I have added 8 directional event triggers, the ability to disable 8 directional sprites on events, and restored an awesome rmxp feature, always on top!!
 
Ok well I tested the script with the new updates and had an error. This occurs when an event ries to turn ISO:

script '8 directions' line 632: NoMethodError occurred.
undefined method 'include?' for nil:NilClass
 

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