C'est pour des soucis de fluidité que je choisis un timer répétitif de 0.01.
I/ Les droites a) GUI
Beaucoup de technique existe. Le principe est de partir de la position de l'unité ciblée, et de la décaler sur une courte distance à haute fréquence dans l'angle souhaité.
Il existe déjà une action en GUI remplissant parfaitement cette définition :
Gui:
Trigger:
Unité - Move (UniteCible) instantly to ((Position of (UnitCible)) offset by Vitesse towards Direction degrees)
UniteCible est la variable de type unit qui désignera l'unité à déplacer.
Vitesse est la variable qui déterminera la distance à laquelle on doit déplacer périodiquement l'unité.
Direction est la variable qui déterminera l'angle de déplacement (l'orientation de la droite).
Avec ça, on a une belle droite d'origine la position de UniteCible de sens vers la droite si Vitesse > 0 ou vers la gauche sur Vitesse < 0, et de direction Direction.
Remarque : Il faut faire attention au leak que va produire cette action. Le point "position of unit" est à supprimer, pour ceci pour le stockez dans une variable et le supprimer via un custom script (voir ce lien).
b) JASS
En JASS, la technique consiste à matérialiser l'axe des abscisses et des ordonnées comme en mathématique pour faire y = f(x). On procède comme ceci :
D'abord don définit toutes les valeur de x :
La particularité, afin d'avoir une vitesse bien égale à celle rentré, est qu'il faut multiplier la vitesse sur l'axe x par le cosinus de l'angle correspondant à la direction choisie. Pour cela on calcule l'angle que forme la droite avec l'axe x de cette façon :
Jass:
if Direction > 0 then
set a = ACosBJ(1/SquareRoot(1 + Direction * Direction))
else
set a = -1 * ACosBJ(1/SquareRoot(1 + Direction * Direction))
endif
car l'éditeur va par défaut donner une valeur positive de l'angle, et que cos(x) = cos(-x) mais on peut savoir lequel est le bon en sachant si la droite croît ou décroit.
Puis les valeur de y en fonction de x :
Jass:
call SetUnitY(u, GetUnitX(u) * Direction + GetUnitY(u))
Ainsi, on a une belle droite bien définie selon son équation mathématique y = ax + b avec b = GetUnitY(u) pour que l'origine soit la position de l'unité u. De plus, ça ne provoque aucun leak.
II/ Toutes les courbes du type y = f(x) a) GUI
En GUI, c'est très pénible à faire.
L'idée est de reprendre ce que l'on a fait en JASS précédemment mais en GUI, et vous allez voir c'est beaucoup plus long.
On commence donc par définir l'axe des abscisses :
Gui:
Trigger:
Set x = ((X of (Position of (UnitCible))) + Vitesse)
Puis l'axe des ordonnées :
Gui:
Trigger:
Set y = (Y of (Position of (UnitCible))) + f(x)
avec f une fonction définie sur l'intervalle choisit (ici ça part de la position de l'unité et ça continue jusqu'à la limite de la map).
Ensuite, on crée une variable de type point et on lui met comme valeur (x;y) :
Gui:
Trigger:
Set p = (Point(x, y))
On a plus qu'à déplacer notre unité ciblée sur ce point et ne pas oublier de le remove pour unleaker :
Gui:
Trigger:
Unité - Move (UniteCible) instantly to p Custom script: call RemoveLocation(udg_p)
(ça vous fait un exemple de remove comme ça)
b) JASS
En JASS, on ne change pas de technique. Ce n'est que la généralisation de ce qui a été fait précédemment. Cela donne :
Avec f une fonction définit sur votre intervalle ayant comme argument un réel et retournant un réel.
III/ Les formes géométriques particulières
Une forme géométrique prend pour base la technique d'une fonction mathématique seulement au lieu de n'utiliser une variable de type incrémentation pour les abscisses et une fonction mathématique poru les ordonnées, on définit une variable d'incrémentation et 2 fonctions mathématiques pour les coordonnées.
a) Le cercle :
On l'étudie au lycée, le cercle n'est autre que le déplacement d'un point selon 2 fonctions : cosinus et sinus.
On retrouve donc que notre point a pour coordonnée : (cos(x);sin(x))
Seulement en refaisant bêtement ça comme ça, on se retrouve avec un cercle de centre (0;0) et de rayon 1, ce qui n'arrange pas nos affaires. En faite, ce qui se cache la dessous, c'est un point de coordonnée : (0 + cos(x) * 1;0 + sin(x) * 1)
Vous voyez toujours pas ?
Et si j'vous dit : (Centre_x_du_cercle + cos(x) * rayon;Centre_y_du_cercle + sin(x) * rayon) ? Ah ba oui la c'est mieux :p
en GUI :
Il n'y a qu'à refaire ce qui a été dit, définir notre variable d'incrémentation (pour des soucis de nomonclature, j'vais changer et mettre "angle" à la place de "x", c'est plus approprié) :
Gui:
Trigger:
Set angle = angle + Vitesse
Puis la coordonnée x de notre unité :
Gui:
Trigger:
Set x = (Centre_x_du_cercle + ((Cos(angle)) x rayon))
Et enfin la coordonnée y de notre unité :
Gui:
Trigger:
Set y = (Centre_y_du_cercle + ((Sin(angle)) x rayon))
Bon ça reste du GUI, donc pour unleaker il vous reste encore à créer votre point(x;y), déplacer votre unité directos dessus, et supprimer ce point.
J'vous le fais pas c'est la même que tout à l'heure.
en JASS :
Alors pour le coup, en JASS la méthode que j'vous propose sera complètement différente. On va faire en sorte que se soit une fonction générale que l'on placera dans le script de la map et qui ne nécessitera qu'une ligne par utilisation dans un trigger avec notre event définit au début.
Qu'est-ce que l'utilisation doit choisir ? L'unité, le centre, le rayon, et la vitesse de rotation. Bon...
Jass:
function Cercle takes unit u, real center_x, real center_y, real radius, real speed returns nothing
Rien de compliqué, juste l'applicaiton d'un raisonnement logique. Bon c'est vrai qu'il y a un peu beaucoup de paramètre, ça fait un peu lourd. Pas de problème, il suffit de remplacer les 2 coordonnées du centre par une région. Et c'est vrai aussi que pour définir le rayon, au pifomètre comme ça c'est assez chiant. Pour être plus précis on peut demander à l'utilisateur de placer un point du cercle en région, et on calculera la distance entre ce point et le centre. Donc on se retrouve avec :
Jass:
function Cercle takes unit u, rect center, rect b, real speed returns nothing
Et voila, voici la première ligne de notre fonction.
Bon, comme l'utilisation doit permettre le MUI (multi unit instance), on utilisera aucune variable globale.
Déjà, on va définir le rayon :
Jass:
local real dx = GetRectCenterX(b) - GetRectCenterX(center)
local real dy = GetRectCenterY(b) - GetRectCenterY(center)
local real rayon = SquareRoot(dx * dx + dy * dy)
Pour cela, j'ai refait la fonction DistanceBetweenPoint, ça nous permet d'éviter de passer par des points.
C'est parfait, pas de variable globale, on utilise uniquement les paramètres qui sont propre à chaque utilisation de la fonction.
Ensuite il faut déplacer l'unité ciblée, d'abord sur les X comme on a fait en GUI :
Notez cependant qu'au lieu d'utiliser une variable globale comme incrémentation, je prend à chaque fois l'orientation de l'unité ciblée. Encore une fois pour ne pas avoir de problème lors d'une utilisation simultanée de la fonction. Mais comme je prend cette valeur directement sur l'unité comme si c'était ma variable réel d'incrémentation, il faut que je la traite ainsi donc je rajoute une ligne :
Jass:
call SetUnitFacing(u, GetUnitFacing(u) + speed)
Ainsi, lorsque notre trigger à répétition s'activera, il changera à chaque fois le facing unit, et donc dans notre cos et sin la valeur facing unit sera comme il faut.
Attention : Il faut cependant faire attention, que lorsque l'on place l'unité, son angle soit cohérent avec al direction que l'on veut voir prendre au début. Ce que je vous conseille c'est de créer l'unité sur la région b que l'on met en paramètre, avec un angle égale à celui que retournerait la fonction :
Mais n'utilisez pas cette fonction, elle leak. Refaite la à la main sinon ça leak ou placez votre unité à l'angle 0, facing 0, ça sera plus simple pour tout le monde.
b) L'ovale
L'ovale n'est qu'un dérivé du cercle. Ou si vous préférez, le cercle n'est qu'un cas particulier d'ovale.
Je vais donc pas trop détailler, car la technique en GUI ou en JASS et la même que tout à l'heure.
en GUI :
Je reprend le déclos du cercle de tout à l'heure (sans le move qui est comme vu dans le II avec le remove) :
Gui:
Trigger:
Set angle = angle + Vitesse Set x = (Centre_x_du_cercle + ((Cos(angle)) x rayon)) Set y = (Centre_y_du_cercle + ((Sin(angle)) x rayon))
De la, je n'est qu'à réfléchir un peu. Qu'est-ce que me cache cette formule ?
Si j'vous dis que c'est pareil que :
Gui:
Trigger:
Set angle = angle + Vitesse Set x = (Centre_x_du_cercle + ((1 x Cos(angle)) x rayon)) Set y = (Centre_y_du_cercle + ((1 x Sin(angle)) x rayon))
Rien de surprenant, à première vue je n'ai fait que rajouter une multiplication par 1. Mais si j'vous dis que je ne l'ai pas rajouté, mais dévoilé ? Il était déjà la, juste qu'il était caché. On a alors un indice sur la situation, les 2 coefficients sont ici égaux, seulement vous vous apercevrez que si on donne 2 valeurs différentes, le cercle changera de forme pour s'écraser soit sur l'axe des abscisses soit sur l'ordonnée.
J'en viens alors à la nouvelle formule pour l'ovale :
Gui:
Trigger:
Set angle = angle + Vitesse Set x = (Centre_x_du_cercle + (distorsion_horizontale x ((Cos(angle)) x rayon))) Set y = (Centre_y_du_cercle + (distorsion_laterale x ((Sin(angle)) x rayon)))
J'appelle ça distorsion, car ça me semble pas mal comme nom, et horizontale et latérale, car c'est l'axe sur lequel ça aura un effet.
en JASS :
C'est exactement la même chose, sauf qu'on peut le rajouter en paramètre, ce qui donnerait :
Jass:
function Ovale takes unit u, rect center, rect b, real vitesse, real distorsion_lateral, real distorsion_horizontale returns nothing
local real dx = GetRectCenterX(b) - GetRectCenterX(center)
local real dy = GetRectCenterY(b) - GetRectCenterY(center)
local real rayon = SquareRoot(dx * dx + dy * dy)
Remarque : Avec ça, on ne fait que des spirales écrasé latéralement ou horizontalement. Changer l'angle d'écrasement est légèrement plus compliqué, voir beaucoup plus. Donc je ne le développerais que en cas de demande (donc si vous validez sans, cette remarque sera à supprimer).
c) La spirale
Une spirale est une autre forme dérivée du cercle. Si on y réfléchit, un cercle est une spiral à nombre de tour infinie. De la on peut facilement trouver la formule de la spirale.
en GUI :
Vous êtes d'accord que :
Gui:
Trigger:
Set angle = angle + Vitesse Set x = (Centre_x_du_cercle + ((Cos(angle)) x rayon)) Set y = (Centre_y_du_cercle + ((Sin(angle)) x rayon))
C'est la même chose que :
Gui:
Trigger:
Set angle = angle + Vitesse Set x = (Centre_x_du_cercle + ((Cos(angle)) x (rayon - 0))) Set y = (Centre_y_du_cercle + ((Sin(angle)) x (rayon - 0)))
Bon ba j'vais pas vous rechanter la chanson, vous l'aurez compris, la formule c'est :
Gui:
Trigger:
Set angle = angle + Vitesse Set x = (Centre_x_du_cercle + ((Cos(angle)) x (rayon - a))) Set y = (Centre_y_du_cercle + ((Sin(angle)) x (rayon - a))) Set a = a + vitesse_diminution
Et vous vous débrouillez pour définir a en fonction du nombre de tour que vous voulez que ça fasse, car franchement le GUI... Voila quoi... Donc... Bon ok j'vous le fais... C'est la dernière fois que chuis gentil avec vous !
Nous disions donc, c'est bien beau mais rayon - a ça parle pas beaucoup pour qu'on sache à quelle vitesse notre spirale va arriver diminuer.
Et pi c'est chiant de devoir faire a = a + vitesse_diminution, ça parle pas ça non plus.
Bon ba on change pour un truc plus ergonomique. Que pensez vous de :
Gui:
Trigger:
Set rayon_spiral = rayon - a Set angle = angle + Vitesse Set x = (Centre_x_du_cercle + ((Cos(angle)) x rayon_spiral)) Set y = (Centre_y_du_cercle + ((Sin(angle)) x rayon_spiral))
C'est mieux ! Comme ça on a un a constant, c'est plus facile pour lui trouver une valeur significative que l'on comprendra facilement.
C'est mathématiquement qu'on déterminera a.
Gui:
Trigger:
Set a = rayon / nb_de_tour
C'est logique, j'vais pas vous faire la démonstration car il n'y a pas d'intérêt. En tout cas, c'est dans votre trigger d'initialisation que j'vous propose de foutre ça, ainsi vous pourrez choisir très précisément combien de tour vous voulez avant d'atteindre un rayon nul, et surtout vous pourrez facilement rajouter une condition comme arrêter la spirale une fois que rayon = 0, sinon votre spirale va de nouveau augmenter.
en JASS :
On va encore faire une fonction généraliste, qui part du cercle et où l'on n'a qu'à rajouter des arguments.
On a vu en GUI, qu'il n'y avait qu'à soustraire à chaque exécution de la fonction, une valeur a au rayon, et que cette valeur a = rayon / nb_de_tour
Voila c'que j'vous propose :
Jass:
function Spiral takes unit u, rect center, real vitesse, real nb_de_tour returns nothing
local real dx = GetUnitX(u) - GetRectCenterX(center)
local real dy = GetUnitY(u) - GetRectCenterY(center)
local real rayon = SquareRoot(dx * dx + dy * dy)
local real a = rayon / nb_de_tour
set rayon = rayon - a
call SetUnitX(u, GetRectCenterX(center) + CosBJ(GetUnitFacing(u))*rayon)
call SetUnitY(u, GetRectCenterY(center) + SinBJ(GetUnitFacing(u))*rayon)
call SetUnitFacing(u, GetUnitFacing(u) + vitesse)
endfunction
Faites attention, il y a beaucoup de changement. On ne pouvait plus garder un rayon constant, et on devait aussi conserver le mui de la fonction et ne surtout pas utiliser de globales.
J'ai donc, au lieu de définir le rayon par la distance entre le centre et un point du cercle, pris la distance entre le centre et la position de l'unité ciblée. Comme à chaque tour l'unité ciblée se rapproche du centre, on arrive à conserver la valeur du rayon sur le terrain et à la récupérer grâce à cette supercherie.
Avec ça, on a une spirale exactement comme on la veut.
Remarque : 1) On peut combiner la spirale et un ovale, j'vous laisse voir comment.
2) On peut, au lieu de soustraire une valeur a au rayon pour la coordonnée x et y, mettre 2 valeurs différentes. Si vous êtes malin, vous pouvez deviner que on va passer d'une spirale basée sur un cercle à une spirale basée sur un ovale.
TRES IMPORTANT : La méthode que j'ai utilisé ici correspond à une utilisation spécifique. Passer par des régions est plus pratique seulement dans le cas où l'on crée nos déplacements dans l'éditeur. Cela convient donc parfaitement à des mappers du type slide ou maze.
Pour les spell maker, il est bien plus efficace de passer par les coordonnées reals et d'actionner la fonction en passant par cette event :
Tu as regardé le tuto sur le déplacement par clavier ?
Citation:
[Définition : Une fonction affine, est une fonction f :
allant de R vers R
auquel à x on associe ax+b
elle est continue, monotone, et croissante ou décroissante en fonction du signe de a.
une fonction qui a x associe ax+b _________________
Si vous recherchez quelque chose, il y a de très grandes chances que vous trouviez la réponse ici alors jetez y un oeil. Topic indispensable
Inscrit le: 11 Fév 2011 Messages: 2151 Sujets: 114 Spécialité en worldedit: Chasser le Dragon, puis l'exterminer proprement avec une petite cuillère et une poêle.
Posté le: 06/10/11 11:51 Sujet du message:
Dark77 a écrit:
Citation:
je parlerais du leak plus tard, la ce n'était pas le sujet ^^
Inscrit le: 14 Avr 2011 Messages: 1846 Sujets: 119 Spécialité en worldedit: fonctions paramétriques, équation de mouvement.
Posté le: 06/10/11 15:16 Sujet du message:
hein ? non j'ai regardé aucun tuto x)
merci pour la correction, j'ai pas les signes mathématiques donc j'avais un peu de mal à retranscrire. _________________
Inscrit le: 14 Avr 2011 Messages: 1846 Sujets: 119 Spécialité en worldedit: fonctions paramétriques, équation de mouvement.
Posté le: 07/01/12 02:01 Sujet du message:
sinon tuto mi à jour selon la demande de Lord. (oui c'est extrêmement baclé mais quand j'l'ai commencé je pensais pas qu'un jour on me demanderait de continuer) _________________
Inscrit le: 12 Nov 2011 Messages: 1062 Sujets: 107 Spécialité en worldedit: Inactif(Enfin presque) Médailles: 1 (En savoir plus...)
Posté le: 07/01/12 15:26 Sujet du message:
Merci beaucoup OOOOOOHHH grand Fulldragon (je pense en faire trop mais bon)
EDIT: juste une question y'a un moyen de limiter la taille de l'ellipse,parce que mon unité de test va tellement vite et loin qu'elle se bloque dans un coin de la map _________________
Inscrit le: 14 Avr 2011 Messages: 1846 Sujets: 119 Spécialité en worldedit: fonctions paramétriques, équation de mouvement.
Posté le: 07/01/12 16:07 Sujet du message:
1) vitesse = distance / temps, lis le début du tuto tu verras comment la régler
2) la taille va dépendre des rayons que tu mets.
3) si ça se bloque dans un coin c'est pas normal, tu as mal fait ton trigger. c'est censé avoir une trajectoire répétitive, donc un jour elle devrait revenir en arrière (sauf si ça se met à bugger du à la limite de la map, ça m'étonnerait pas)
4) j'aime l'adulation xD _________________
22:27:43<Seiraw> Bah y a deux genre de personnes
22:27:57<Seiraw> les soumis et les soumises
Inscrit le: 14 Avr 2011 Messages: 1846 Sujets: 119 Spécialité en worldedit: fonctions paramétriques, équation de mouvement.
Posté le: 08/03/12 18:24 Sujet du message:
bon j'ai refait entièrement mon tuto.
il est GUI/JASS (un peu baclé en GUI)
j'en suis au cercle, je compte rajouter la spiral et l'ovale _________________
Inscrit le: 12 Nov 2011 Messages: 1062 Sujets: 107 Spécialité en worldedit: Inactif(Enfin presque) Médailles: 1 (En savoir plus...)
Posté le: 08/03/12 18:31 Sujet du message:
Belle amélioration, je vois qu'il comprend aussi le jass, pour le cercle, tu peux set une variable d'angle +ton nombre car un angle de 360° c'est un cercle. _________________
Toutes les heures sont au format GMT + 1 Heure Aller à la page 1, 2Suivante
Page 1 sur 2
Vous ne pouvez pas poster de nouveaux sujets dans ce forum Vous ne pouvez pas répondre aux sujets dans ce forum Vous ne pouvez pas éditer vos messages dans ce forum Vous ne pouvez pas supprimer vos messages dans ce forum Vous ne pouvez pas voter dans les sondages de ce forum