Worldedit
  Worldedit
Le site sur l'éditeur de warcraft 3 !
 
  FAQFAQ   RechercherRechercher   Liste des MembresListe des Membres    Groupes d'utilisateursGroupes d'utilisateurs   medals.php?sid=5ffa3efedd0368ebccc3f81e2a76627eMédailles   S'enregistrerS'enregistrer 
 ProfilProfil   Se connecter pour vérifier ses messages privésSe connecter pour vérifier ses messages privés   ConnexionConnexion 
  FAQFAQ World Editor   UploadUploader une map ou une image    UploadAjouter sa map à l'annuaire   UploadConsulter l'annuaire

Faire un déplacement en arc

 
Poster un nouveau sujet   Répondre au sujet    Worldedit Index du Forum -> Aide sur les déclencheurs
Voir le sujet précédent :: Voir le sujet suivant  
Auteur Message
 Ectelion
Membre reconnu


Inscrit le: 12 Nov 2011
Messages: 1062
Sujets: 107
Spécialité en worldedit: Inactif(Enfin presque)
Médailles: 1 (En savoir plus...)
Créateur d'unité (Quantité : 1)

MessagePosté le: 27/03/16 15:25    Sujet du message: Faire un déplacement en arc Citer

Le week-end de 3 jours m'a fait revenir sur war3 parce que j'avais rien à faire et donc du coup je reviens vers vous. J'ai codé un projectile tout simple(une boule de feu) et je voudrais qu'il se déplace en arc comme la compétence mortar de D3, sauf que je n'ai pas la formule donc si quelqu'un pouvait me la donner (je met le code au cas où il faudrait que je rajoute des attributs.).

Le code:
Secret:

Jass:
library Fireball uses CONSTANTS
    //CONSTANTS OF THE SPELL
    globals
        private constant real VELOCITY = 17.50
        private constant real TIME = 0.03125000
        private constant real DAMAGE_SMALL = 250.00
        private constant real DAMAGE_BIG = 75.00
        private constant integer DUMMY_ID = 'h000'
        private timer TIMER = CreateTimer()
    endglobals
   
    //CODE
    struct Fball
        //ATTRIBUTES
        static integer count = -1
        static Fball array Instance
        private unit dummy
        private unit pointer_small
        private unit pointer_big
        private real dummy_x
        private real dummy_y
        private real dummy_z
        private real pointer_x
        private real pointer_y
        private real dummy_angle
        private real distance
        //METHODS
       
        private static method loop_fireball takes nothing returns nothing
            local integer i = 0
            local real x = 0
            local real y = 0
            loop
                exitwhen i > Fball.count
                set x = Fball.Instance[i].pointer_x - Fball.Instance[i].dummy_x
                set y = Fball.Instance[i].pointer_y - Fball.Instance[i].dummy_y
                if SquareRoot(x * x + y * y ) > CST_AREA_SMALL then
                    set x = Fball.Instance[i].dummy_x + VELOCITY * Cos(Fball.Instance[i].dummy_angle)
                    set y = Fball.Instance[i].dummy_y + VELOCITY * Sin(Fball.Instance[i].dummy_angle)
                    call SetUnitX(Fball.Instance[i].dummy, x)
                    call SetUnitY(Fball.Instance[i].dummy, y)
                    set Fball.Instance[i].dummy_x = x
                    set Fball.Instance[i].dummy_y = y
                else
                    //DEALING DAMAGE
                    /*TO DO LATER*/
                    //KILLING THE DUMMIES
                    call KillUnit(Fball.Instance[i].dummy)
                    call RemoveUnit(Fball.Instance[i].pointer_small)
                    call RemoveUnit(Fball.Instance[i].pointer_big)
                    if i < Fball.count then
                        set Fball.Instance[i].pointer_x = Fball.Instance[Fball.count].pointer_x
                        set Fball.Instance[i].pointer_y = Fball.Instance[Fball.count].pointer_y
                        set Fball.Instance[i].pointer_small = Fball.Instance[Fball.count].pointer_small
                        set Fball.Instance[i].pointer_big = Fball.Instance[Fball.count].pointer_big
                        set Fball.Instance[i].dummy_x = Fball.Instance[Fball.count].dummy_x
                        set Fball.Instance[i].dummy_y = Fball.Instance[Fball.count].dummy_y
                        set Fball.Instance[i].dummy_z = Fball.Instance[Fball.count].dummy_z
                        set Fball.Instance[i].dummy_angle = Fball.Instance[Fball.count].dummy_angle
                        set Fball.Instance[i].dummy = Fball.Instance[Fball.count].dummy
                        set Fball.Instance[i].distance = Fball.Instance[Fball.count].distance
                        call Fball.Instance[Fball.count].deallocate()
                    else
                        call Fball.Instance[i].deallocate()
                    endif
                    set Fball.count = (Fball.count - 1)
                    if Fball.count == -1 then
                        call PauseTimer( TIMER )
                    endif
                endif
                set i = i + 1
            endloop
        endmethod
       
        static method create_fireball takes player owner, real start_x, real start_y, real end_x, real end_y returns nothing
            local real angle = Atan2(end_y - start_y, end_x - start_x)
            local real d = SquareRoot((end_x - start_x) * (end_x - start_x) + (end_y - start_y) * (end_y - start_y))
            set Fball.count = Fball.count + 1
            set Instance[Fball.count] = Fball.allocate()
            set Fball.Instance[Fball.count].dummy = CreateUnit( owner, DUMMY_ID, start_x, start_y, angle )
            set Fball.Instance[Fball.count].dummy_angle = angle
            set Fball.Instance[Fball.count].dummy_x = start_x
            set Fball.Instance[Fball.count].dummy_y = start_y
            set Fball.Instance[Fball.count].dummy_z = GetUnitFlyHeight( Fball.Instance[Fball.count].dummy )
            set Fball.Instance[Fball.count].pointer_x = end_x
            set Fball.Instance[Fball.count].pointer_y = end_y
            set Fball.Instance[Fball.count].pointer_small = CreateUnit( owner, CST_POINTER_SMALL_ID, end_x, end_y, 90.00 )
            set Fball.Instance[Fball.count].pointer_big = CreateUnit( owner, CST_POINTER_BIG_ID, end_x, end_y, 90.00 )
            set Fball.Instance[Fball.count].distance = d
            if Fball.count == 0 then
                call TimerStart( TIMER, TIME, true, function Fball.loop_fireball )
                call BJDebugMsg("Timer Started")
            endif
        endmethod
       
    endstruct

endlibrary



En tout cas, joyeuses Pâquesà ceux qui liront ce post.
_________________
Inactif(Enfn presque)
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 rgf
Membre reconnu


Inscrit le: 09 Mar 2009
Messages: 1154
Sujets: 54
Spécialité en worldedit: Croâ ?


MessagePosté le: 27/03/16 20:57    Sujet du message: Citer

C'est censé être quoi pointer_x et pointer_y ?
Je ne sais pas à quoi ressemble la compétence mortar de D3, mais sinon, sans l'adapter à ton code, voici la formule d'une trajectoire de projectile (parabolique) :

En notant a l'angle de lancer (l'arc) et r la distance (sur le plan XY) parcourue :

z = ((tz - oz)/D² - tan(a)/D) * r² + tan(a) * r + oz

où oz est le z initial, tz le z final et D la distance entre le point de lancer et le point d'arrivée (sur le plan XY toujours).

Est-ce bien ce que tu cherches ?
_________________
Croâh ?
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Ayane
Bot administrateur


Inscrit le: 17 Sep 2007
Messages: 2009
Sujets: 49

Médailles: 2 (En savoir plus...)
Ayane (Quantité : 1) Rédacteur de tuto #1 (Quantité : 1)

MessagePosté le: 27/03/16 21:27    Sujet du message: Citer

Il a dit un arc et non pas une parabole.
x = cos(alpha)
y = sin(alpha)
_________________
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé MSN Messenger
 rgf
Membre reconnu


Inscrit le: 09 Mar 2009
Messages: 1154
Sujets: 54
Spécialité en worldedit: Croâ ?


MessagePosté le: 27/03/16 21:53    Sujet du message: Citer

Ce que tu donnes est une formule d'arc de cercle. En mathématique un arc n'est pas forcément un arc de cercle donc ce que tu dis est inexact.
De plus, étant donné ce qu'il demande on peut s'attendre à ce qu'il cherche la courbe d'une trajectoire de projectile balistique (arc parabolique donc) et pas un arc de cercle qui n'a rien à voir dans le contexte. Je pense donc que la formule que j'ai proposée est plus adaptée.
_________________
Croâh ?
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Ayane
Bot administrateur


Inscrit le: 17 Sep 2007
Messages: 2009
Sujets: 49

Médailles: 2 (En savoir plus...)
Rédacteur de tuto #1 (Quantité : 1) Ayane (Quantité : 1)

MessagePosté le: 27/03/16 22:24    Sujet du message: Citer

C'est vrai, je viens de regarder les vidéos et cela a l'air d'être un arc légèrement parabolique.
Avec la formule que j'ai donné cela fait un arc de cercle si on interpole linéairement alpha avec le temps. En utilisant une interpolation non linéaire avec un ease-out on peut obtenir une parabole.
Demo d'interpolation: http://demos111.mootools.net/Fx.Transitions

L'algorithme correspondant pour toutes les interpolations de la démo:
Code:
Fx.Transition = function(transition, params){
   params = Array.from(params);
   var easeIn = function(pos){
      return transition(pos, params);
   };
   return Object.append(easeIn, {
      easeIn: easeIn,
      easeOut: function(pos){
         return 1 - transition(1 - pos, params);
      },
      easeInOut: function(pos){
         return (pos <= 0.5 ? transition(2 * pos, params) : (2 - transition(2 * (1 - pos), params))) / 2;
      }
   });
};

Fx.Transitions = {

   linear: function(zero){
      return zero;
   }

};



Fx.Transitions.extend = function(transitions){
   for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]);
};

Fx.Transitions.extend({

   Pow: function(p, x){
      return Math.pow(p, x && x[0] || 6);
   },

   Expo: function(p){
      return Math.pow(2, 8 * (p - 1));
   },

   Circ: function(p){
      return 1 - Math.sin(Math.acos(p));
   },

   Sine: function(p){
      return 1 - Math.cos(p * Math.PI / 2);
   },

   Back: function(p, x){
      x = x && x[0] || 1.618;
      return Math.pow(p, 2) * ((x + 1) * p - x);
   },

   Bounce: function(p){
      var value;
      for (var a = 0, b = 1; 1; a += b, b /= 2){
         if (p >= (7 - 4 * a) / 11){
            value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2);
            break;
         }
      }
      return value;
   },

   Elastic: function(p, x){
      return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x && x[0] || 1) / 3);
   }

});

['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){
   Fx.Transitions[transition] = new Fx.Transition(function(p){
      return Math.pow(p, i + 2);
   });
});


L'avantage d'implémenter les interpolations c'est que l'on peut intuitivement modifier n'importe quelle fonction de géométrie pour obtenir l'effet voulu, et on peut facilement tester différente interpolation; notamment très utile pour toute animation sur le temps.
_________________
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé MSN Messenger
 rgf
Membre reconnu


Inscrit le: 09 Mar 2009
Messages: 1154
Sujets: 54
Spécialité en worldedit: Croâ ?


MessagePosté le: 27/03/16 22:58    Sujet du message: Citer

Peu importe la manière dont tu considères alpha en fonction du temps (peu importe la transition que tu appliques), la formule que tu as donnée reste un arc de cercle, cela ne changera que la vitesse de tracé du cercle.
Je ne suis pas sûr de voir où tu veux en venir.
_________________
Croâh ?
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Ectelion
Membre reconnu


Inscrit le: 12 Nov 2011
Messages: 1062
Sujets: 107
Spécialité en worldedit: Inactif(Enfin presque)
Médailles: 1 (En savoir plus...)
Créateur d'unité (Quantité : 1)

MessagePosté le: 28/03/16 09:00    Sujet du message: Citer

@Ayane: Je recherchais effectivement la formule de la parabole(ce qui pour moi était quand même un arc), rgf avait vu juste.

@rgf: pointer_x et pointeur_y représentent la zone d'impact du projectile(qui est montrée au joueur) ça correspond concrètement au point d'arrivée.

J'avais juste une question sur a dans ta formule, plus il est élevé plus le projectile montera haut c'est ça ?

edit: Et r correspond à quoi dans ta formule ? à la vitesse de déplacement du projectile ?
_________________
Inactif(Enfn presque)
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 rgf
Membre reconnu


Inscrit le: 09 Mar 2009
Messages: 1154
Sujets: 54
Spécialité en worldedit: Croâ ?


MessagePosté le: 28/03/16 10:07    Sujet du message: Citer

Oui on peut dire ça, à une distance à parcourir fixée, plus a est grand et plus le projectile montera haut. En fait a représente l'angle de lancer initial comme vu sur ce schema :
Secret:



On voit également r sur le schéma, r est la distance que le projectile parcourt et dans ton cas il aura pour formule r = vitesse*t (t c'est le temps)

Ca donnerait un truc comme ça pour actualiser la position :
Jass:

local real d = speed*TIMEOUT
// On augmente la distance dist de d à chaque tick
set this.dist = this.dist + d
// On actualise x et y
set this.x = this.x + d*Cos(angle)
set this.y = this.y + d*Sin(angle)
// On actualise z en fonction de la distance dist
set this.z = ((tz - oz)/(D*D) - tan(a)/D) * this.dist*this.dist + tan(a) * this.dist + oz


TIMEOUT est la durée entre deux timers,
dist correspond à r, il est initialement à 0 (au lancer du projectile),
angle est l'orientation de la trajectoire,
D est la distance totale à parcourir (la distance entre le point de lancer et d'arrivée)

Si tu souhaites avoir la trajectoire paramétrée par la hauteur maximale du projectile plutôt que par son angle de lancer c'est tout à fait possible aussi, cela demandera de changer un peu la formule.
_________________
Croâh ?
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Ectelion
Membre reconnu


Inscrit le: 12 Nov 2011
Messages: 1062
Sujets: 107
Spécialité en worldedit: Inactif(Enfin presque)
Médailles: 1 (En savoir plus...)
Créateur d'unité (Quantité : 1)

MessagePosté le: 28/03/16 11:45    Sujet du message: Citer

Sujet passé en Résolu.
_________________
Inactif(Enfn presque)
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Ayane
Bot administrateur


Inscrit le: 17 Sep 2007
Messages: 2009
Sujets: 49

Médailles: 2 (En savoir plus...)
Rédacteur de tuto #1 (Quantité : 1) Ayane (Quantité : 1)

MessagePosté le: 28/03/16 13:32    Sujet du message: Citer

L'implémentation sous Unity:
Code:

public class RGFProjectile : MonoBehaviour
{
    public float LaunchAngle = Mathf.PI / 4;
    public Transform Caster;
    private Vector3 Target;
    public float Speed = 1.0f;
    private Vector3 Origin;

    // Use this for initialization
    void Start()
    {
        Origin = (Caster != null) ? Caster.position : transform.position;
        Target = Origin + Vector3.right * 10;
    }

    // Update is called once per frame
    void Update()
    {
        if (transform.position != Target)
        {
            var offset = Target - Origin;
            var launchAngleTangent = Mathf.Tan(LaunchAngle);
            var squareTotalDistance = Vector2.SqrMagnitude(offset);
            var deltaDistance = Speed * Time.deltaTime;
            var position2D = Vector2.MoveTowards(transform.position, Target, deltaDistance);
            var squareDistance2D = (position2D - (Vector2)Origin).sqrMagnitude;

            var z = (offset.z / squareTotalDistance - launchAngleTangent / Mathf.Sqrt(squareTotalDistance)) * squareDistance2D + launchAngleTangent * Mathf.Sqrt(squareDistance2D) + Origin.z;

            transform.position = new Vector3(position2D.x, position2D.y, z);
        }
        else
        {
            // Loop
            transform.position = Origin;
            Start();
        }
    }
}



Pour l'interpolation je parle notamment d'interpoler le résultat de sin(a) avant d'appliquer le multiplicateur de distance.
z = D * Interpolation.cubic.easeOut(sin(a))
_________________


Dernière édition par Ayane le 28/03/16 14:02; édité 1 fois
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé MSN Messenger
 rgf
Membre reconnu


Inscrit le: 09 Mar 2009
Messages: 1154
Sujets: 54
Spécialité en worldedit: Croâ ?


MessagePosté le: 28/03/16 13:50    Sujet du message: Citer

Pourquoi écris-tu une implémentation sous Unity ? Quitte à l'implémenter pourquoi ne pas directement l'implémenter en Jass ?
_________________
Croâh ?
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Ayane
Bot administrateur


Inscrit le: 17 Sep 2007
Messages: 2009
Sujets: 49

Médailles: 2 (En savoir plus...)
Ayane (Quantité : 1) Rédacteur de tuto #1 (Quantité : 1)

MessagePosté le: 28/03/16 14:03    Sujet du message: Citer

Parce que c'est plus facile de tester les algorithmes sous Unity 3D.
_________________
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé MSN Messenger
Montrer les messages depuis:   
Poster un nouveau sujet   Répondre au sujet    Worldedit Index du Forum -> Aide sur les déclencheurs Toutes les heures sont au format GMT + 1 Heure
Page 1 sur 1
La question posée dans ce topic a été résolue !

 
Sauter vers:  
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


Powered by phpBB © 2001, 2005 phpBB Group
Traduction par : phpBB-fr.com