Partagez
Aller en bas
fake66
fake66
Membre

Nombre de messages : 61
Age : 32
Localisation : Vendée
Distinction : aucune
Date d'inscription : 17/05/2013

Event qui vous suis en esquivant les obstacles Empty Event qui vous suis en esquivant les obstacles

le Sam 28 Mai 2016 - 0:43
Bonjour tout le monde. je voulais créer un event utilisant l'algorithme de Dijkstra (c'est ce qu'utilise vos gps pour choisir le chemin le plus court), et du coup faire des event allant jusqu'au héro en contournant les murs et obstacles.
En me renseignant si c'était possible sur rpg maker vx ace je suis tombé sur un script utilisant cet algorithme.
Pour faire simple, ce script permet de faire traverser une carte à vos pnj, monstre ou autre, sans bloquer contre des murs.
Sur l'image suivante, on vois un petit labyrinthe fait vite fait, et le chemin que parcours le monstre pour me rejoindre. (de manière très fluide)
Event qui vous suis en esquivant les obstacles Dijkst10

Une fois le script installé, il suffit de mettre l'event en question en mode "trajectoire personnalisée" et d'y coller (dans les options de mouvements) la commande de script "find_path($game_player.x, $game_player.y)"
Il y a plusieurs fonctionnalités, comme le faite de faire allez l'event ailleurs que sur le héros, le faire s'arrêter x cases avant, on peut faire partir l'event depuis les commandes et pas forcement depuis la trajectoire personnalisée.

Voici le liens vers le site (anglais)
http://forums.rpgmakerweb.com/index.php?/topic/3064-pathfinding/

et voici le script
script:
#===============================================================================
# Pathfinding
# By Jet10985(Jet)
# Minor modifications by Venima
#===============================================================================
# This script will allow you to use a pathfinder to move players or events.
# This script has: 0 customization options.
#
# Modifications:
# Goal location may now be inpassable, pathfinder will still reach it.
# Pathfinder still works "as intended" when the move route is set to repeat.
# Added parameter: distance (explained below).
# Note: Pathfinder is a bit more processor heavy when used with a repeating
# move route (it was useless before, so this is only a benefit)
#===============================================================================
# Overwritten Methods:
# None
#-------------------------------------------------------------------------------
# Aliased methods:
# None
#===============================================================================
=begin
To move a player or event, use this in an event "Script..." command:

find_path(x, y, ev = 0, wait = false, distance = 0)

x is the target x
y is the targey y

ev is set to 0 by default and can be omitted like so: find_path(9, 0)
ev represents what character is to be moved. -1 is the player, 0 is the
calling event, and anything above is an event on the map whose ID is the ev.

wait if set to false and can be ommitted like so:
find_path(9, 0) or find_path(9, 0, -1)
wait specifies if the player will have to wait for the move route to finish
to start moving again.

distance is set to 0 by default and can be omitted in the same way as above.
while x and y represent the target location, the event will only be moved
up to the specified distance from the target. This makes it easier to have
an event follow the player, without getting in the player's way. This could
be used as an alternative to following, except it works on any events,
not just party members. If you do specify distance, you must also specify
all optional parameters.

Example of following the player at a distance, either using:

Event's custom move route (on repeat):
 find_path($game_player.x, $game_player.y, 3)
Or set move route command in a loop:
 find_path($game_player.x, $game_player.y, 0, true, 3)



You may also use find_path(x, y) (no ev or wait) inside of an event's
"Set Move Route..." command, using the "Script..." tab. This does the same
as above, but takes on the properties of the move route you are making,
including the affected character.
=end

module Jet
 module Pathfinder
   
   # While mainly for coders, you may change this value to allow the
   # pathfinder more time to find a path. 1000 is default, as it is enough for
   # a 100x100 MAZE so, yeah.
   MAXIMUM_ITERATIONS = 1000
   
 end
end

class Node
 
 include Comparable

 attr_accessor :point, :parent, :cost, :cost_estimated

 def initialize(point)
   @point = point
   @cost = 0
   @cost_estimated = 0
   @on_path = false
   @parent = nil
 end

 def mark_path
   @on_path = true
   @parent.mark_path if @parent
 end
 
 def total_cost
   cost + cost_estimated
 end

 def <=>(other)
   total_cost <=> other.total_cost
 end
 
 def ==(other)
   point == other.point
 end
end

class Point
 
 attr_accessor :x, :y
 
 def initialize(x, y)
   @x, @y = x, y
 end

 def ==(other)
   return false unless Point === other
   @x == other.x && @y == other.y
 end

 def distance(other)
   (@x - other.x).abs + (@y - other.y).abs
 end

 def relative(xr, yr)
   Point.new(x + xr, y + yr)
 end
end

class Game_Map
 
 def each_neighbor(node, char = $game_player)
   x = node.point.x
   y = node.point.y
   nodes = []
   4.times {|i|
     i += 1
     new_x = round_x_with_direction(x, i * 2)
     new_y = round_y_with_direction(y, i * 2)
     next unless char.passable?(x, y, i * 2)
     #removed line below (technically, if your goal is an inpassable block,
     # e.g. an event, you can still reach it)
     #next unless char.passable?(new_x, new_y, 10 - i * 2)
     nodes.push(Node.new(Point.new(new_x, new_y)))
   }
   nodes
 end
 
 #modified line below (added distance parameter)
 def find_path(tx, ty, sx, sy, dist, char = $game_player)
   start = Node.new(Point.new(sx, sy))
   goal = Node.new(Point.new(tx, ty))
   #modified line below (added distance handling)
   return [] if start == goal or (dist > 0 and start.point.distance(goal.point) <= dist)
   return [] if ![2, 4, 6, 8].any? {|i| char.passable?(tx, ty, i) }
   open_set = [start]
   closed_set = []
   path = []
   iterations = 0
   loop do
     return [] if iterations == Jet::Pathfinder::MAXIMUM_ITERATIONS
     iterations += 1
     current = open_set.min
     return [] unless current
     each_neighbor(current, char).each {|node|
       #modified line below (added distance handling)
       if node == goal or (dist > 0 and node.point.distance(goal.point) <= dist)
         node.parent = current
         node.mark_path
         return recreate_path(node)
       end
       next if closed_set.include?(node)
       cost = current.cost + 1
       if open_set.include?(node)
         if cost < node.cost
           node.parent = current
           node.cost = cost
         end
       else
         open_set << node
         node.parent = current
         node.cost = cost
         node.cost_estimated = node.point.distance(goal.point)
       end
     }
     closed_set << open_set.delete(current)
   end
 end
 
 def recreate_path(node)
   path = []
   hash = {[1, 0] => 6, [-1, 0] => 4, [0, 1] => 2, [0, -1] => 8}
   until node.nil?
     pos = node.point
     node = node.parent
     next if node.nil?
     ar = [pos.x <=> node.point.x, pos.y <=> node.point.y]
     path.push(RPG::MoveCommand.new(hash[ar] / 2))
   end
   return path
 end
end

class Game_Character
 
 #modified function (added handling for repeated move route (recalculates path
 # each step so it doesn't just loop it's old path route and will revalidate  
 # if x or y changes, will follow variable value if x and y are set to it)
 def find_path(x, y, dist = 0)
   path = $game_map.find_path(x, y, self.x, self.y, dist).reverse
   if !@move_route.repeat
     @move_route.list.delete_at(@move_route_index)
     @move_route.list.insert(@move_route_index, *path)
     @move_route_index -= 1
   elsif path.length > 0
     process_move_command(path[0])
     @move_route_index -= 1
   end
   
 end
end

class Game_Interpreter
 
 #modified line below (added distance parameter)
 def find_path(x, y, ev = 0, wait = false, dist = 0)
   char = get_character(ev)
   #modified line below (added distance parameter)
   path = $game_map.find_path(x, y, char.x, char.y, dist)
   path.reverse!
   path.push(RPG::MoveCommand.new(0))
   route = RPG::MoveRoute.new
   route.list = path
   route.wait = wait
   route.skippable = true
   route.repeat = false
   char.force_move_route(route)
 end
 
end
Les auteurs sont JET pour la création du script et VENIMA pour des petites améliorations. Il me semble qu'il faut les cité si vous utilisez leur script.
Shinokishi
Shinokishi
Membre

Nombre de messages : 523
Age : 19
Localisation : Quelque part en France (mais je sais pas où)
Distinction : Message-minute (Spy)
Date d'inscription : 23/08/2015

Event qui vous suis en esquivant les obstacles Empty Re: Event qui vous suis en esquivant les obstacles

le Sam 28 Mai 2016 - 11:52
merci pour ce script fort intéressant et comme je ne peux pas donner de points de participations voici un cookie

juste ici:
Event qui vous suis en esquivant les obstacles 37001100-biscuits-brun-croquant-sur-un-fond-blanc
fake66
fake66
Membre

Nombre de messages : 61
Age : 32
Localisation : Vendée
Distinction : aucune
Date d'inscription : 17/05/2013

Event qui vous suis en esquivant les obstacles Empty Re: Event qui vous suis en esquivant les obstacles

le Sam 28 Mai 2016 - 16:19
haha merci miam Smile

Petite infos: Pour ce script, je l'ai essayé. Il marche sauf que si le ou les chemins menant à vous sont obstrué par, non pas un mur, mais un event, alors le jeu rameras vraiment à fond.
Par exemple, vous empruntez un couloir et un event vous suis avec ce script. Si dans ce couloir un autre event viens le boucher, et bloquant donc le chemin à celui qui vous suit. même si l'event qui bouche le chemin n'as rien à voir avec ce script. Alors le script va galerer à calculer le chemin et feras ramer votre jeu.
Revenir en haut
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum