QuasiXi

Quasi Movement

Oct 1st, 2014
667
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 36.84 KB | None | 0 0
  1. #==============================================================================
  2. # ** Quasi Movement v0.85
  3. #  Require Module Quasi
  4. #   http://quasixi.wordpress.com/2014/09/23/quasi/
  5. #==============================================================================
  6. #  Changed how movement works.  Allows players to choose how many pixels to move
  7. # per movement.  In better terms, allows players to make characters have a pixel
  8. # movement or still by by a grid like 32x32 or even 16x16.
  9. #  Changed how collisions work.  Events now have bounding boxes surrounding them.
  10. # If two boxes touch there will be a collision.  Boxes can be set in each event,
  11. # further detail in the instructions.
  12. #==============================================================================
  13. # Change Log
  14. #------------------------------------------------------------------------------
  15. # v0.8 - Changed movement speed back to vxa default
  16. #      - Changed bbox comment box it is now:
  17. #        <bbox:width,height,ox,oy> (just added the < >)
  18. #      - Adjusted map passibility, still needs work
  19. #        Region boxes work much better then tile passibilty.
  20. #      - Added a mid move passibilty check for more accurate passibilty
  21. #      - Added Region boxes (more on step 6)
  22. #      - Added Region Friction (more on step 7)
  23. # --
  24. # v0.7 - Pre-Released for feedback
  25. #------------------------------------------------------------------------------
  26. # To do / Upcoming
  27. #------------------------------------------------------------------------------
  28. # - Fix follower distance
  29. # - Add a push out of box, if you somehow got inside a box with through off.
  30. # - Fix tile passablity so you don't need use regions.
  31. # - Find more bugs~
  32. #==============================================================================
  33. module Quasi
  34.   module Movement
  35. #------------------------------------------------------------------------------
  36. # Instructions:
  37. #  Step 1. Set GRID to the amount of pixels you want to move per movement.
  38. #          Default is 1, meaning pixel movement.  This can be changed back
  39. #          to 32 which is vxa default tile movement.
  40. #------------------------------------------------------------------------------
  41.     GRID = 1
  42. #------------------------------------------------------------------------------
  43. #  Step 2. Set DIR8 to true or false.  When true it will allow for 8 direction
  44. #          movement, when false it will not.  Diagonal movement was modified
  45. #          if the diagonal movement isn't possible it will attempt the two
  46. #          directions seperatly to see if they work.
  47. #         Example:  Player tries to move UP/RIGHT (Diag 9) but it's not passible
  48. #                 Player will see if UP is passible, if it's not it will try
  49. #                 RIGHT.  If neither work, player won't move
  50. #------------------------------------------------------------------------------
  51.     DIR8 = true
  52. #------------------------------------------------------------------------------
  53. #  Step 3. Set DIAGSPEED.  This adjusts the speed when moving diagonal.  Set to
  54. #          0 if you want to stay at same speed, default at -0.5
  55. #------------------------------------------------------------------------------
  56.     DIAGSPEED = -0.5
  57. #------------------------------------------------------------------------------
  58. #  Step 4. Set PLAYERBOX.  This sets the bounding box for the player character.
  59. #          by default it is [24,16,4,8] More details on setting bounding boxes
  60. #          a few lines below.
  61. #         - Events will also default to these values.
  62. #------------------------------------------------------------------------------
  63.     PLAYERBOX = [24,16,4,16]
  64. #------------------------------------------------------------------------------
  65. #  Step 5. -Bounding boxes-
  66. #          How to set up on event:
  67. #           Make a comment anywhere in the event with the following setup:
  68. #              <bbox=width,height,ox,oy>
  69. #           bbox=   :Starts the set up for the bounding box
  70. #           width   :The width of the box, default 32
  71. #           height  :The height of the box, default 32
  72. #           ox      :The x orgin of the box, default is 0
  73. #           oy      :The y orgin of the box, default is 0
  74. #      
  75. #          ox and oy can be left out, they will default to 0 if blank.
  76. #          0 ox and oy means box starts from top left cornor of the event.
  77. #       Example Boxes:
  78. #              <bbox=32,32>
  79. #         Creates the default box which is 32x32 starting at the top left, good
  80. #         for block tiles.  Notice how ox and oy are left out.
  81.  
  82. #              <bbox=24,16,4,16>
  83. #         Creates a box that is 24x16.  The box is pushed to the left 4 pixels
  84. #         and down 16.  This is a good box for vxa characters that are 32x32.
  85. #------------------------------------------------------------------------------
  86. #------------------------------------------------------------------------------
  87. #  Step 6. REGION BOXES.  Theses give region bounding boxes.
  88. #          Regions, unlike character boxes, can have multiple boxes.
  89. #          They are set up like:
  90. #           REGIONBOXES{
  91. #            REGION NUMBER => [box parameters], # Single box
  92. #            REGION NUMBER => [[box 1 parameters],[box 2 parameters]], # Multiple boxes
  93. #           } # < ends the hash *Important!*
  94. #
  95. #         *NOTE*  Region boxes only work if you're inside the box, unlike event boxes
  96. #           what this means is, you should not make the box go outside of the
  97. #           region tile, can keep it within a 32x32 box.
  98. #         *NOTE 2* Region boxes are used to replace tile passibility for now
  99. #           tile passibility doesn't work as well as region boxes do!
  100. #           I created most of the passages with region boxes below.
  101. #         *FINAL NOTE* Region boxes prioritize over tile passibilty,
  102. #           so even if the tile is set to no direction, it will use
  103. #           the region passibilty instead, if there's a region on that tile.
  104. #        **Check Map1 in the demo for example on how they are used**
  105. #------------------------------------------------------------------------------
  106.     REGIONBOXES = {
  107.       # Passage(4 DIR), UP not allowed
  108.       46 => [32,4],
  109.       # Passage(4 DIR), UP/RIGHT not allowed
  110.       47 => [[32,4],[4,32,28]],
  111.       # Passage(4 DIR), RIGHT not allowed
  112.       55 => [4,32,28],
  113.       # Passage(4 DIR), DOWN/RIGHT not allowed
  114.       63 => [[32,4,0,28],[4,32,28]],
  115.       # Passage(4 DIR), UP/LEFT not allowed
  116.       45 => [[32,4],[4,32]],
  117.       # Passage(4 DIR), LEFT not allowed
  118.       53 => [4,32],
  119.       # Passage(4 DIR), DOWN/LEFT not allowed
  120.       61 => [[32,4,0,28],[4,32]],
  121.       # Passage(4 DIR), DOWN not allowed
  122.       62 => [32,4,0,28],
  123.       # Passage, NO DIR allowed
  124.       54 => [32,32],
  125.       44 => [32,32],
  126.       # Passage, ANY DIR allowed (not needed was used for testing.)
  127.       52 => [0,0],
  128.     }
  129. #------------------------------------------------------------------------------
  130. #  Step 7. REGION FRICTION.  Just a little extra.(Incomplete)
  131. #          Allows regions to adjust friction, ex: sliding tiles (sliding on ice)
  132. #          Setup:
  133. #            REGIONFRICTION = {
  134. #              REGION ID => NUMBER OF TILES TO SLIDE,
  135. #            } # < ends the hash *Important!*
  136. #          Tiles it slides go by 32x32 tiles and ignores the GRID variable from
  137. #          Step 1.  Friction speeds need to get added, as well as negative friction
  138. #          which slow you down.
  139. #------------------------------------------------------------------------------
  140.     REGIONFRICTION = {
  141.       60 => 99,
  142.     }
  143. #------------------------------------------------------------------------------
  144. #  For testing purposes, set the bottom value to true to see the boxes.
  145. #  Only shows during play testing.
  146. #  *Does not show region boxes!*
  147. #------------------------------------------------------------------------------
  148.     SHOWBOXES = true
  149.   end
  150. end
  151. #==============================================================================#
  152. # By Quasi (http://quasixi.wordpress.com/)
  153. #  - 9/22/14
  154. #==============================================================================#
  155. #   ** Stop! Do not edit anything below, unless you know what you      **
  156. #   ** are doing!                                                      **
  157. #==============================================================================#
  158. $imported = {} if $imported.nil?
  159. $imported["Quasi_Movement"] = 0.85
  160.  
  161. if $imported["Quasi"]
  162. #==============================================================================
  163. # ** Game_CharacterBase
  164. #------------------------------------------------------------------------------
  165. #  This base class handles characters. It retains basic information, such as
  166. # coordinates and graphics, shared by all characters.
  167. #==============================================================================
  168.  
  169. class Game_CharacterBase
  170.   alias qm_init       init_public_members
  171.   alias qm_moveto     moveto
  172.   alias qm_update     update
  173.   alias qm_straighten straighten
  174.   #--------------------------------------------------------------------------
  175.   # * Public Instance Variables
  176.   #--------------------------------------------------------------------------
  177.   attr_reader   :px            
  178.   attr_reader   :py
  179.   attr_reader   :velocity
  180.   attr_accessor :friction
  181.   #--------------------------------------------------------------------------
  182.   # * Initialize Public Member Variables
  183.   #--------------------------------------------------------------------------
  184.   def init_public_members
  185.     qm_init
  186.     @px = 0
  187.     @py = 0
  188.     @npx = 0
  189.     @npy = 0
  190.     @velocity = 0
  191.     @friction = 0
  192.     @diag = false
  193.     @grid = Quasi::Movement::GRID
  194.   end
  195.   #--------------------------------------------------------------------------
  196.   # * Determine if Passable
  197.   #     d : Direction (2,4,6,8)
  198.   #--------------------------------------------------------------------------
  199.   def passable?(x, y, d)
  200.     x1 = d == 4 ? x-move_tiles : d == 6 ? x+move_tiles : x
  201.     y1 = d == 8 ? y-move_tiles : d == 2 ? y+move_tiles : y
  202.     x2 = $game_map.round_px(x1)
  203.     y2 = $game_map.round_py(y1)
  204.     x3 = $game_map.round_x((x1/32.0).round)
  205.     y3 = $game_map.round_y((y1/32.0).round)
  206.    
  207.     return false unless $game_map.valid?(x3, y3)
  208.     return true if @through || debug_through?
  209.     return false unless midpassable?(x,y,d)
  210.     return false unless map_passable?(x2, y2, d)
  211.     #return false unless map_passable?(x2, y2, reverse_dir(d))
  212.     return false if collide_with_box?(x2, y2)
  213.     return true
  214.   end
  215.   #--------------------------------------------------------------------------
  216.   # * Determine if Midpoint is Passable
  217.   #     d : Direction (2,4,6,8)
  218.   #--------------------------------------------------------------------------
  219.   def midpassable?(x, y, d)
  220.     half_tiles = move_tiles/2.0
  221.     x2 = $game_map.round_px_with_direction(x, d, half_tiles)
  222.     y2 = $game_map.round_py_with_direction(y, d, half_tiles)
  223.    
  224.     return false unless map_passable?(x2, y2, d)
  225.     return false unless map_passable?(x2, y2, reverse_dir(d))
  226.     return false if collide_with_box?(x2, y2)
  227.     return true
  228.   end
  229.   #--------------------------------------------------------------------------
  230.   # * Determine if Map is Passable
  231.   #     d : Direction (2,4,6,8)
  232.   #--------------------------------------------------------------------------
  233.   def map_passable?(x, y, d)
  234.     rbox = Quasi::Movement::REGIONBOXES.keys
  235.     e = edge(x,y)[d]
  236.    
  237.     if rbox.include?($game_map.region_id(e[0][0],e[0][1])) ||
  238.        rbox.include?($game_map.region_id(e[1][0],e[1][1]))
  239.        (regionpass?(e[0][0],e[0][1],x,y) && regionpass?(e[1][0],e[1][1],x,y))
  240.     else
  241.       ($game_map.passable?(e[0][0], e[0][1], d) && $game_map.passable?(e[1][0], e[1][1], d))
  242.     end
  243.   end
  244.   #--------------------------------------------------------------------------
  245.   # * Determine Diagonal Passability
  246.   #     horz : Horizontal (4 or 6)
  247.   #     vert : Vertical (2 or 8)
  248.   #--------------------------------------------------------------------------
  249.   def diagonal_passable?(x, y, horz, vert)
  250.     x2 = $game_map.round_px_with_direction(x, horz, move_tiles)
  251.     y2 = $game_map.round_py_with_direction(y, vert, move_tiles)
  252.     (passable?(x, y, vert) &&  passable?(x, y2, horz)) ||
  253.     (passable?(x, y, horz) &&  passable?(x2, y, vert))
  254.   end
  255.   #--------------------------------------------------------------------------
  256.   # * Detect Collision with Character
  257.   #--------------------------------------------------------------------------
  258.   def collide_with_box?(x, y)
  259.     boxes = $game_map.bounding_xy(box_xy(x,y))
  260.     if !boxes.empty?
  261.       boxes.keep_if {|e| e != self}
  262.     end
  263.     !boxes.empty? || collide_with_vehicles?(x,y)
  264.   end
  265.   #--------------------------------------------------------------------------
  266.   # * Detect Collision with Vehicle
  267.   #--------------------------------------------------------------------------
  268.   def collide_with_vehicles?(x, y)
  269.     $game_map.boat.pos_nt?((x/32).round, (y/32).round) ||
  270.     $game_map.ship.pos_nt?((x/32).round, (y/32).round)
  271.   end
  272.   #--------------------------------------------------------------------------
  273.   # * Determine Triggering of Frontal Touch Event
  274.   #--------------------------------------------------------------------------
  275.   def check_event_trigger_touch_front
  276.     x1 = $game_map.round_px_with_direction(@px, @direction, move_tiles)
  277.     y1 = $game_map.round_py_with_direction(@py, @direction, move_tiles)
  278.     check_event_trigger_touch(x1, y1)
  279.   end
  280.   #--------------------------------------------------------------------------
  281.   # * Determine if Moving
  282.   #--------------------------------------------------------------------------
  283.   def moving?
  284.     @velocity > 0
  285.   end
  286.   #--------------------------------------------------------------------------
  287.   # * Determine if Sliding
  288.   #--------------------------------------------------------------------------
  289.   def sliding?
  290.     @friction > 0
  291.   end
  292.   #--------------------------------------------------------------------------
  293.   # * Get Move Speed (Account for Dash)
  294.   #--------------------------------------------------------------------------
  295.   def real_move_speed
  296.     @move_speed + (dash? ? 1 : 0) + (@diag ? Quasi::Movement::DIAGSPEED : 0)
  297.   end
  298.   #--------------------------------------------------------------------------
  299.   # * Move to Designated Position
  300.   #--------------------------------------------------------------------------
  301.   def moveto(x, y)
  302.     @px = x * 32.0
  303.     @py = y * 32.0
  304.     @npx = @px
  305.     @npy = @py
  306.     qm_moveto(x,y)
  307.   end
  308.   #--------------------------------------------------------------------------
  309.   # * Straighten Position
  310.   #--------------------------------------------------------------------------
  311.   def straighten
  312.     qm_straighten
  313.     @friction = 0
  314.   end
  315.   #--------------------------------------------------------------------------
  316.   # * How many tiles are you moving
  317.   #--------------------------------------------------------------------------
  318.   def move_tiles
  319.     @grid < real_move_speed ? real_move_speed : @grid
  320.   end
  321.   def speed
  322.     2**real_move_speed / 8.0
  323.   end
  324.   #--------------------------------------------------------------------------
  325.   # * Frame Update
  326.   #  Aliased, added an update friction
  327.   #--------------------------------------------------------------------------
  328.   def update
  329.     check_friction if moving?
  330.     return update_friction if sliding?
  331.     qm_update
  332.   end
  333.   #--------------------------------------------------------------------------
  334.   # * Update While Moving
  335.   #--------------------------------------------------------------------------
  336.   def update_move
  337.     @px = [@px - speed, @npx].max if @npx < @px
  338.     @px = [@px + speed, @npx].min if @npx > @px
  339.     @py = [@py - speed, @npy].max if @npy < @py
  340.     @py = [@py + speed, @npy].min if @npy > @py
  341.    
  342.     @real_x = @px/32.0 if @real_x != @px/32.0
  343.     @real_y = @py/32.0 if @real_y != @py/32.0
  344.     @x = @px/32.0 if @x != @px/32.0
  345.     @y = @py/32.0 if @y != @py/32.0
  346.    
  347.     @velocity -= speed
  348.    
  349.     update_bush_depth unless moving?
  350.   end
  351.   #--------------------------------------------------------------------------
  352.   # * Update Friction
  353.   #--------------------------------------------------------------------------
  354.   def update_friction
  355.     if passable?(@px, @py, @direction)
  356.       @friction = [@friction-1,0].max if !moving?
  357.       return if @friction == 0
  358.       move_straight(@direction) if !moving?
  359.     else
  360.       @friction = 0
  361.     end
  362.    
  363.     update_move if moving?
  364.   end
  365.   #--------------------------------------------------------------------------
  366.   # * Check for Friction
  367.   #--------------------------------------------------------------------------
  368.   def check_friction
  369.     regfric = Quasi::Movement::REGIONFRICTION.keys
  370.     mid = v_center(@npx,@npy)
  371.     mx = (mid[0]/32).truncate
  372.     my = (mid[1]/32).truncate
  373.    
  374.     if regfric.include?($game_map.region_id(mx,my))
  375.       if @friction == 0
  376.         @friction = (32.0/move_tiles)*Quasi::Movement::REGIONFRICTION[$game_map.region_id(mx,my)]
  377.       end
  378.     else
  379.       @friction = 0
  380.     end
  381.   end
  382.   #--------------------------------------------------------------------------
  383.   # * Move Straight
  384.   #     d:        Direction (2,4,6,8)
  385.   #     turn_ok : Allows change of direction on the spot
  386.   #--------------------------------------------------------------------------
  387.   def move_straight(d, turn_ok = true)
  388.     @move_succeed = passable?(@px, @py, d)
  389.     orginal_speed = @move_speed
  390.     if !@move_succeed && self.is_a?(Game_Player)
  391.       while !@move_succeed
  392.         break if @move_speed < 1
  393.         @move_speed -= 0.5
  394.         @move_succeed = passable?(@px, @py, d)
  395.       end
  396.     end
  397.     if @move_succeed
  398.       set_direction(d)
  399.       @diag = false
  400.       @velocity = move_tiles
  401.       @npx = $game_map.round_px_with_direction(@px, d, move_tiles)
  402.       @npy = $game_map.round_py_with_direction(@py, d, move_tiles)
  403.       @px = $game_map.px_with_direction(@npx, reverse_dir(d), move_tiles)
  404.       @py = $game_map.py_with_direction(@npy, reverse_dir(d), move_tiles)
  405.       increase_steps
  406.     elsif turn_ok
  407.       set_direction(d)
  408.       check_event_trigger_touch_front
  409.     end
  410.     @move_speed = orginal_speed
  411.     @velocity = 0 if !@move_succeed
  412.   end
  413.   #--------------------------------------------------------------------------
  414.   # * Move Diagonally
  415.   #     horz:  Horizontal (4 or 6)
  416.   #     vert:  Vertical (2 or 8)
  417.   #--------------------------------------------------------------------------
  418.   def move_diagonal(horz, vert)
  419.     @move_succeed = diagonal_passable?(@px, @py, horz, vert)
  420.     orginal_speed = @move_speed
  421.     if !@move_succeed && self.is_a?(Game_Player)
  422.       while !@move_succeed
  423.         break if @move_speed < 1
  424.         @move_speed -= 0.5
  425.         @move_succeed = diagonal_passable?(@px, @py, horz, vert)
  426.       end
  427.     end
  428.     if @move_succeed
  429.       @diag = true
  430.       @velocity = move_tiles
  431.       @npx = $game_map.round_px_with_direction(@px, horz, move_tiles)
  432.       @npy = $game_map.round_py_with_direction(@py, vert, move_tiles)
  433.       @px = $game_map.px_with_direction(@npx, reverse_dir(horz), move_tiles)
  434.       @py = $game_map.py_with_direction(@npy, reverse_dir(vert), move_tiles)
  435.       increase_steps
  436.     end
  437.     @move_speed = orginal_speed
  438.     set_direction(horz) if @direction == reverse_dir(horz)
  439.     set_direction(vert) if @direction == reverse_dir(vert)
  440.     if !@move_succeed
  441.       if passable?(@px, @py, horz)
  442.         move_straight(horz)
  443.       elsif passable?(@px, @py, vert)
  444.         move_straight(vert)
  445.       end
  446.     end
  447.   end
  448.   #--------------------------------------------------------------------------
  449.   # * Bounding box array
  450.   #--------------------------------------------------------------------------
  451.   def bounding_box
  452.     return @boundingbox if @boundingbox
  453.     @boundingbox = [32,32,0,0]
  454.   end
  455.   #--------------------------------------------------------------------------
  456.   # * Make Bounding box
  457.   #--------------------------------------------------------------------------
  458.   def box_xy(x=@px,y=@py)
  459.     bb = bounding_box
  460.     ox = bb[2].nil? ? 0 : bb[2]
  461.     oy = bb[3].nil? ? 0 : bb[3]
  462.     oy -= shift_y
  463.     bx = x+ox..x+bb[0]+ox
  464.     by = y+oy..y+bb[1]+oy
  465.     return [bx, by]
  466.   end
  467.   #--------------------------------------------------------------------------
  468.   # * Check for Bounding box Collision
  469.   #  Returns true if boxes are inside each other.
  470.   #--------------------------------------------------------------------------
  471.   def box?(objbox,through=nil)
  472.     through = through.nil? ? @through : through
  473.     return if !bounding_box || through
  474.     pass1 = (objbox[0].first <= box_xy[0].last) && (objbox[0].last >= box_xy[0].first)
  475.     pass2 = (objbox[1].first <= box_xy[1].last) && (objbox[1].last >= box_xy[1].first)
  476.     return pass1 && pass2
  477.   end
  478.   #--------------------------------------------------------------------------
  479.   # * Find the boxes vertices
  480.   # returns array [top left, top right, bottom left, bottom right]
  481.   #--------------------------------------------------------------------------
  482.   def vertices(x=@px,y=@py)
  483.     x1 = box_xy(x,y)[0]
  484.     y1 = box_xy(x,y)[1]
  485.     tl = [x1.first,y1.first]
  486.     tr = [x1.last,y1.first]
  487.     bl = [x1.first,y1.last]
  488.     br = [x1.last,y1.last]
  489.     return [tl, tr, bl, br]
  490.   end
  491.   #--------------------------------------------------------------------------
  492.   # * Find facing edge in 32 grid terms
  493.   #--------------------------------------------------------------------------
  494.   def edge(x=@px,y=@py)
  495.     x1 = box_xy(x,y)[0]
  496.     y1 = box_xy(x,y)[1]
  497.     tl = [(x1.first/32.0).truncate,(y1.first/32.0).truncate]
  498.     tr = [(x1.last/32.0).truncate,(y1.first/32.0).truncate]
  499.     bl = [(x1.first/32.0).truncate,(y1.last/32.0).truncate]
  500.     br = [(x1.last/32.0).truncate,(y1.last/32.0).truncate]
  501.     return {2 => [bl,br], 4 => [tl,bl], 6 => [tr, br], 8 => [tl, tr]}
  502.   end
  503.   #--------------------------------------------------------------------------
  504.   # * Find center of box
  505.   #--------------------------------------------------------------------------
  506.   def v_center(x=@px,y=@py)
  507.     x1 = box_xy(x,y)[0]
  508.     y1 = box_xy(x,y)[1]
  509.     mx = x1.first + ((x1.last - x1.first) / 2.0)
  510.     my = y1.first + ((y1.last - y1.first) / 2.0)
  511.     return [mx,my]
  512.   end
  513.   #--------------------------------------------------------------------------
  514.   # * Makes region box (Should probably be in game_map)
  515.   #--------------------------------------------------------------------------
  516.   def regbox(x,y)
  517.     bb = Quasi::Movement::REGIONBOXES[$game_map.region_id(x,y)]
  518.     return if !bb
  519.     regbox = []
  520.     if bb[0].is_a?(Array)
  521.       bb.each do |box|
  522.         x1 = x * 32; y1 = y * 32
  523.         ox = box[2].nil? ? 0 : box[2]
  524.         oy = box[3].nil? ? 0 : box[3]
  525.         bx = x1+ox..x1+box[0]+ox
  526.         by = y1+oy..y1+box[1]+oy
  527.         regbox << [bx,by]
  528.       end
  529.     else
  530.       x1 = x * 32; y1 = y * 32
  531.       ox = bb[2].nil? ? 0 : bb[2]
  532.       oy = bb[3].nil? ? 0 : bb[3]
  533.       bx = x1+ox..x1+bb[0]+ox
  534.       by = y1+oy..y1+bb[1]+oy
  535.       regbox = [bx, by]
  536.     end
  537.     return regbox
  538.   end
  539.   #--------------------------------------------------------------------------
  540.   # * Region box Collision
  541.   #  Makes region box then passes it through a check.
  542.   #  Returns true if region is passable ( No box collision. )
  543.   #--------------------------------------------------------------------------
  544.   def regionpass?(x,y,nx,ny)
  545.     bb = regbox(x,y)
  546.     return true if !bb || @through
  547.     if bb[0].is_a?(Array)
  548.       pass = []
  549.       bb.each do |box|
  550.         pass << regbox?(box,nx,ny)
  551.       end
  552.       return pass.count(false) == pass.size
  553.     else
  554.       return regbox?(bb,nx,ny) == false
  555.     end
  556.   end
  557.   #--------------------------------------------------------------------------
  558.   # * Returns true if boxes are inside each other.
  559.   #--------------------------------------------------------------------------
  560.   def regbox?(regbox,nx,ny)
  561.     insidex = (box_xy(nx,ny)[0].last >= regbox[0].first) && (box_xy(nx,ny)[0].first <= regbox[0].last)
  562.     insidey = (box_xy(nx,ny)[1].last >= regbox[1].first) && (box_xy(nx,ny)[1].first <= regbox[1].last)
  563.     return insidex && insidey
  564.   end
  565. end
  566.  
  567. #==============================================================================
  568. # ** Game_Map
  569. #------------------------------------------------------------------------------
  570. #  This class handles maps. It includes scrolling and passage determination
  571. # functions. The instance of this class is referenced by $game_map.
  572. #==============================================================================
  573.  
  574. class Game_Map
  575.   #--------------------------------------------------------------------------
  576.   # * Calculate PX Coordinate After Loop Adjustment
  577.   #--------------------------------------------------------------------------
  578.   def round_px(x)
  579.     loop_horizontal? ? (x + (width*32)) % (width*32) : x
  580.   end
  581.   #--------------------------------------------------------------------------
  582.   # * Calculate PY Coordinate After Loop Adjustment
  583.   #--------------------------------------------------------------------------
  584.   def round_py(y)
  585.     loop_vertical? ? (y + (height*32)) % (height*32) : y
  586.   end
  587.   #--------------------------------------------------------------------------
  588.   # * Calculate PX Coordinate Shifted One Tile in Specific Direction
  589.   #   (No Loop Adjustment)
  590.   #--------------------------------------------------------------------------
  591.   def px_with_direction(x, d, v)
  592.     x + (d == 6 ? v : d == 4 ? -v : 0)
  593.   end
  594.   #--------------------------------------------------------------------------
  595.   # * Calculate PY Coordinate Shifted One Tile in Specific Direction
  596.   #   (No Loop Adjustment)
  597.   #--------------------------------------------------------------------------
  598.   def py_with_direction(y, d, v)
  599.     y + (d == 2 ? v : d == 8 ? -v : 0)
  600.   end
  601.   #--------------------------------------------------------------------------
  602.   # * Calculate PX Coordinate Shifted One Pixel in Specific Direction
  603.   #   (With Loop Adjustment)
  604.   #--------------------------------------------------------------------------
  605.   def round_px_with_direction(x, d, v)
  606.     round_px(x + (d == 6 ? v : d == 4 ? -v : 0))
  607.   end
  608.   #--------------------------------------------------------------------------
  609.   # * Calculate PY Coordinate Shifted One Pixel in Specific Direction
  610.   #   (With Loop Adjustment)
  611.   #--------------------------------------------------------------------------
  612.   def round_py_with_direction(y, d, v)
  613.     round_py(y + (d == 2 ? v : d == 8 ? -v : 0))
  614.   end
  615.   #--------------------------------------------------------------------------
  616.   # * Get Array of Event Bounding Box at Designated Coordinates
  617.   #--------------------------------------------------------------------------
  618.   def bounding_xy(objbox,through=nil)
  619.     @events.values.select {|event| event.box?(objbox,through) }
  620.   end
  621. end
  622.  
  623. #==============================================================================
  624. # ** Game_Event
  625. #------------------------------------------------------------------------------
  626. #  This class handles events. Functions include event page switching via
  627. # condition determinants and running parallel process events. Used within the
  628. # Game_Map class.
  629. #==============================================================================
  630.  
  631. class Game_Event < Game_Character
  632.   alias qme_setup setup_page_settings
  633.   #--------------------------------------------------------------------------
  634.   # * Detect Collision with Character
  635.   #--------------------------------------------------------------------------
  636.   def collide_with_box?(x, y)
  637.     super || collide_with_player_characters?(x, y)
  638.   end
  639.   #--------------------------------------------------------------------------
  640.   # * Detect Collision with Player (Including Followers)
  641.   #--------------------------------------------------------------------------
  642.   def collide_with_player_characters?(x, y)
  643.     normal_priority? && $game_player.box?(box_xy(x,y))
  644.   end
  645.   #--------------------------------------------------------------------------
  646.   # * Determine if Touch Event is Triggered
  647.   #--------------------------------------------------------------------------
  648.   def check_event_trigger_touch(x, y)
  649.     return if $game_map.interpreter.running?
  650.     if @trigger == 2 && $game_player.box?(box_xy(x,y), false)
  651.       start if !jumping? && normal_priority?
  652.     end
  653.   end
  654.   #--------------------------------------------------------------------------
  655.   # * Bounding box
  656.   #--------------------------------------------------------------------------
  657.   def bounding_box
  658.     return @boundingbox if @boundingbox
  659.     pb = Quasi::Movement::PLAYERBOX
  660.      
  661.     dimension = grab_comment(/<bbox.*=(.*)>/i, "#{pb[0]},#{pb[1]},#{pb[2]},#{pb[3]}")
  662.     @boundingbox = dimension.split(",").map {|s| s.to_i}
  663.   end
  664.   #--------------------------------------------------------------------------
  665.   # * Set Up Event Page Settings
  666.   #--------------------------------------------------------------------------
  667.   def setup_page_settings
  668.     qme_setup
  669.     sub_qmove
  670.   end
  671.   #--------------------------------------------------------------------------
  672.   # * Replace q_move with real moves
  673.   #--------------------------------------------------------------------------
  674.   def sub_qmove
  675.     move = {
  676.      2 => ROUTE_MOVE_DOWN,
  677.      4 => ROUTE_MOVE_LEFT,
  678.      6 => ROUTE_MOVE_RIGHT,
  679.      8 => ROUTE_MOVE_UP,
  680.      1 => ROUTE_MOVE_LOWER_L,
  681.      3 => ROUTE_MOVE_LOWER_R,
  682.      7 => ROUTE_MOVE_UPPER_L,
  683.      9 => ROUTE_MOVE_UPPER_R
  684.      }
  685.     @move_route.list.each do |list|
  686.       next unless list.parameters[0] =~ /qmove/
  687.       qmove =  list.parameters[0].delete "qmove()"
  688.       qmove = qmove.split(",").map {|s| s.to_i}
  689.       (qmove[1]/real_move_speed).times do
  690.         @move_route.list << RPG::MoveCommand.new(move[qmove[0]])
  691.       end
  692.     end
  693.     @move_route.list.each do |list|
  694.       next unless list.parameters[0] =~ /qmove/ || list.code == 0
  695.       @move_route.list.delete(list)
  696.     end
  697.     @move_route.list << RPG::MoveCommand.new(0)
  698.     @original_move_route = @move_route
  699.   end
  700.   #--------------------------------------------------------------------------
  701.   # * Filler method, gets replaced with an actual method in event setup.
  702.   #--------------------------------------------------------------------------
  703.   def qmove(filler,method)
  704.   end
  705. end
  706.  
  707. #==============================================================================
  708. # ** Game_Player
  709. #------------------------------------------------------------------------------
  710. #  This class handles the player. It includes event starting determinants and
  711. # map scrolling functions. The instance of this class is referenced by
  712. # $game_player.
  713. #==============================================================================
  714.  
  715. class Game_Player < Game_Character
  716.   alias qm_movable?   movable?
  717.   #--------------------------------------------------------------------------
  718.   # * Determine if Movement is Possible
  719.   #--------------------------------------------------------------------------
  720.   def movable?
  721.     return false if sliding?
  722.     qm_movable?
  723.   end
  724.   #--------------------------------------------------------------------------
  725.   # * Processing of Movement via Input from Directional Buttons
  726.   #--------------------------------------------------------------------------
  727.   def move_by_input
  728.     return if !movable? || $game_map.interpreter.running?
  729.     if Quasi::Movement::DIR8
  730.       if Input.dir8 > 0
  731.         dia = {7 => [4,8], 1 => [4,2], 9 => [6,8], 3 => [6,2]}
  732.         if [1,7,9,3].include?(Input.dir8)
  733.           move_diagonal(dia[Input.dir8][0], dia[Input.dir8][1])
  734.         else
  735.           move_straight(Input.dir8)
  736.         end
  737.       end
  738.     else
  739.       move_straight(Input.dir4) if Input.dir4 > 0
  740.     end
  741.   end
  742.   #--------------------------------------------------------------------------
  743.   # * Trigger Map Event
  744.   #     triggers : Trigger array
  745.   #     normal   : Is priority set to [Same as Characters] ?
  746.   #--------------------------------------------------------------------------
  747.   def start_map_event(x, y, triggers, normal)
  748.     return if $game_map.interpreter.running?
  749.     $game_map.bounding_xy(box_xy(x,y),false).each do |event|
  750.       if event.trigger_in?(triggers) && event.normal_priority? == normal
  751.         event.start
  752.       end
  753.     end
  754.   end
  755.   #--------------------------------------------------------------------------
  756.   # * Determine if Same Position Event is Triggered
  757.   #--------------------------------------------------------------------------
  758.   def check_event_trigger_here(triggers)
  759.     start_map_event(@px, @py, triggers, false)
  760.   end
  761.   #--------------------------------------------------------------------------
  762.   # * Determine if Front Event is Triggered
  763.   #--------------------------------------------------------------------------
  764.   def check_event_trigger_there(triggers)
  765.     d = @direction
  766.     x1 = d == 4 ? @px-move_tiles : d == 6 ? @px+move_tiles : @px
  767.     y1 = d == 8 ? @py-move_tiles : d == 2 ? @py+move_tiles : @py
  768.     x2 = $game_map.round_x((x1 / 32.0).round)
  769.     y2 = $game_map.round_y((y1 / 32.0).round)
  770.     start_map_event(x1, y1, triggers, true)
  771.    
  772.     return if $game_map.any_event_starting?
  773.     x3 = d == 4 ? x1-move_tiles : d == 6 ? x1+move_tiles : x1
  774.     y3 = d == 8 ? y1-move_tiles : d == 2 ? y1+move_tiles : y1
  775.     x4 = $game_map.round_x((x3 / 32.0).round)
  776.     y4 = $game_map.round_y((y3 / 32.0).round)
  777.     start_map_event(x3, y3, triggers, true)
  778.   end
  779.   #--------------------------------------------------------------------------
  780.   # * Move Straight
  781.   #--------------------------------------------------------------------------
  782.   def move_straight(d, turn_ok = true)
  783.     @followers.move if passable?(@px, @py, d)
  784.     super
  785.   end
  786.   #--------------------------------------------------------------------------
  787.   # * Move Diagonally
  788.   #--------------------------------------------------------------------------
  789.   def move_diagonal(horz, vert)
  790.     @followers.move if diagonal_passable?(@px, @py, horz, vert)
  791.     super
  792.   end
  793.   #--------------------------------------------------------------------------
  794.   # * Bounding box
  795.   #--------------------------------------------------------------------------
  796.   def bounding_box
  797.     return @boundingbox if @boundingbox
  798.     @boundingbox = Quasi::Movement::PLAYERBOX
  799.   end
  800. end
  801.  
  802. #==============================================================================
  803. # ** Sprite_Character
  804. #------------------------------------------------------------------------------
  805. #  This sprite is used to display characters. It observes an instance of the
  806. # Game_Character class and automatically changes sprite state.
  807. #==============================================================================
  808.  
  809. class Sprite_Character < Sprite_Base
  810.   alias qbox_init initialize
  811.   alias qbox_update update
  812.   alias qbox_dispose dispose
  813.   #--------------------------------------------------------------------------
  814.   # * Object Initialization
  815.   #     character : Game_Character
  816.   #--------------------------------------------------------------------------
  817.   def initialize(viewport, character = nil)
  818.     qbox_init(viewport, character)
  819.     start_box if Quasi::Movement::SHOWBOXES && $TEST
  820.   end
  821.   #--------------------------------------------------------------------------
  822.   # * Frame Update
  823.   #--------------------------------------------------------------------------
  824.   def update
  825.     qbox_update
  826.     update_box if Quasi::Movement::SHOWBOXES
  827.   end
  828.   #--------------------------------------------------------------------------
  829.   # * Start Box Display
  830.   #--------------------------------------------------------------------------
  831.   def start_box
  832.     if @character.is_a?(Game_Follower)
  833.       return unless @character.visible?
  834.     end
  835.     return if @character.transparent
  836.     @box_sprite = Sprite.new(viewport)
  837.     bb = @character.bounding_box
  838.     bbox = bb[2].nil? ? 0 : bb[2]
  839.     bboy = bb[3].nil? ? 0 : bb[3]
  840.     @box_sprite.bitmap = Bitmap.new(bb[0],bb[1])
  841.     @box_sprite.bitmap.fill_rect(@box_sprite.bitmap.rect,Color.new(255,0,0,255))
  842.     @box_sprite.ox += 16 - bbox
  843.     @box_sprite.oy += 32 - bboy
  844.     @box_sprite.x = @character.x
  845.     @box_sprite.y = @character.y
  846.     @box_sprite.z = z
  847.     @box_sprite.blend_type = 1
  848.   end
  849.   #--------------------------------------------------------------------------
  850.   # * Free
  851.   #--------------------------------------------------------------------------
  852.   def dispose
  853.     qbox_dispose
  854.     dispose_box if Quasi::Movement::SHOWBOXES
  855.   end
  856.   #--------------------------------------------------------------------------
  857.   # * Free Box
  858.   #--------------------------------------------------------------------------
  859.   def dispose_box
  860.     @box_sprite.dispose if @box_sprite
  861.   end
  862.   #--------------------------------------------------------------------------
  863.   # * Update Box
  864.   #--------------------------------------------------------------------------
  865.   def update_box
  866.     return unless @box_sprite
  867.     @box_sprite.x = x if @box_sprite.x != x
  868.     @box_sprite.y = y if @box_sprite.y != y
  869.   end
  870. end
  871. else
  872.   msgbox(sprintf("[Quasi Movement] Requires Quasi module to run."))
  873. end
Advertisement
Add Comment
Please, Sign In to add comment