Forums Développement Multimédia

Aller au contenu

[AS3] Drag un object sur un rail complexe

drag drop CODE Actionscript

62 réponses à ce sujet

#46 lilive

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2993 messages

Posté 21 December 2012 - 10:51 AM

Tiens le revoilà :)

As-tu essayé des choses pour accélérer?

#47 Galacta

    Etudiant Ingénieur

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 689 messages

Posté 22 December 2012 - 11:03 AM

Salut,

Il y a moyen d'optimiser encore la chose normalement.

L'idée est de créer un Vecteur mono dimension avec les données du BItmapData, on peut donc fixer la longueur du vecteur, donc gain de perfs sur l'accès en mémoire, pour récupérer le point (x,y) dans un tableau 2D ramené à 1D, on peut utiliser la formule index = (y*width) + x.

Autre amélioration, l'accès au Vecteur est plus rapide qu'un BitmapData.getPixel(x,y), je m'explique :
Le runtime utilise des pointeurs de fonction, et des pointeurs sur variables pour représenter nos objets. Donc en gros un appel à monBitmapData.getPixel(x, y) entraîne => récupération de l'adresse de monBitmapData => récupération de l'adresse de la fonction getPixel en mémoire => Accès au premier index du tableau de pixels => décalage en mémoire (x,y) => renvoie de la valeur.

Avec un vecteur on a => récupération de l'adresse du premier élément en mémoire => décalage en mémoire de (y*width)+x => renvoie de la valeur.
J'pense qu'on peut diviser par deux les temps d'accès lecture/ecriture/test en utilisant un vecteur.

Vous me permettez de reprendre un de vos code pour essayer avec ?
Morgan

PS : J'ai fait 2/3 test =>

Vecteur 1D => 15ms sur ma machine en accès (x,y)
BitmapData.getPixel(x,y) => 37ms sur ma machine too

Si c'est sur mobile, il y a moyen que les perfs soient encore plus à l'avantage d'un vecteur.

Word hard, play hard.

#48 Urban angel

    Ceinture Verte

  • Members
  • PipPipPipPip
  • 50 messages

Posté 22 December 2012 - 18:24 PM

Oui bien sur!
Le code appartient à Lilive en fait, voir ancien posts,
Mais je n'ai pas tenté de le modifier ni améliorer ...
La différence entre le simulateur ( ou ça tourne à 60fps)
Et le vrai sur IOS est tellement débile que je me dit qu'il doit y avoir
Un truc tellement évident (de à ne pas faire) que ça me saute pas aux yeux.

J'ai optimise le reste du jeu (et continue encore) mais cette partie la...
Je ne comprend pas... Et cette boucle while, n'y aurait il pas moyen d'écrire ca autrement ?

#49 Urban angel

    Ceinture Verte

  • Members
  • PipPipPipPip
  • 50 messages

Posté 22 December 2012 - 19:15 PM

Aussi j'utilise les intersections pour passer d'une courbe à l'autre,
Afin d'avoir des blocs complexes crées avec plusieurs éléments qui sentrelassent.
Je ne sais pas si le vecteur va garder ça possible?

#50 Galacta

    Etudiant Ingénieur

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 689 messages

Posté 22 December 2012 - 22:11 PM

Tu check les intersections à partir de coordonnées ? Ou autre chose ?
Word hard, play hard.

#51 Urban angel

    Ceinture Verte

  • Members
  • PipPipPipPip
  • 50 messages

Posté 22 December 2012 - 22:17 PM

Alors je check rien du tout, j'utilise la code "tel quel", celui de Lilive,
et j'utilise le fait que l'on que ti une courbe recroise une autre ligne, on peut passer à celle là.
voilà tout :)
cela vient du get pixel je pense...

En gros j'ai, par exemple, un chemin, qui resemble à ça :
---<>--
du coup, je dessine les "<" et les ">" en dessiant la partie du haut, puis je reviens sur mes pas, et repart vers le bas,
pour dessiner la suite. ce qui me permet d'avoir des formes complexe en n'ayant qu'une seule ligne.
:)

#52 Urban angel

    Ceinture Verte

  • Members
  • PipPipPipPip
  • 50 messages

Posté 25 December 2012 - 20:42 PM

Bon, c'est bizarre hein, mais en virant les checkError, ça va plus vite de 10-15%
c'est pas la folie, c'est bcp bcp trop lent encore... mais y a du progrès.
Mais Galacta, tu as pu tester un truc? (entre 2 verres de champagne et du foie gras?) :)

#53 Galacta

    Etudiant Ingénieur

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 689 messages

Posté 25 December 2012 - 22:24 PM

Salut,

A mon avis, y a un soucis avec le typage des variables dans les classes Bezier etc. Utiliser des Number lorsqu'ils sont nécessaires d'accord, mais sinon c'est un gouffre de perf ! Surtout s'ils sont converti avec un outils vers un autre langage.

Essaye avec ça les fichiers que je te joins, j'ai essayé de mieux typer les variables pour gagner en performances. ( Surtout si le mobile n'a pas FPU ).

Tiens moi au courant !

Fichier(s) joint(s)

  • Fichier joint  geom.zip   14.15 Ko   44 téléchargement(s)

Word hard, play hard.

#54 Urban angel

    Ceinture Verte

  • Members
  • PipPipPipPip
  • 50 messages

Posté 26 December 2012 - 20:07 PM

alors j'ai testé, ça à amélioré trèèèèès légèrement, mais faut vraiment être attentif pour s'en rendre compte... rien de dingue.

D'ailleurs, je te remet la version du fichier Path (avec tes améliorations)
avec les fonctions RemoveFirst et Last pieces,
qui permettent d'ajouter à la fin et de supprimer la première pièces du chemin :)

Fichier(s) joint(s)

  • Fichier joint  Path.as   17.35 Ko   38 téléchargement(s)


#55 Galacta

    Etudiant Ingénieur

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 689 messages

Posté 26 December 2012 - 22:52 PM

J'ai refait deux trois modifs, avec des cast en moins et des Number en moins toujours, j'ai pas testé si ça compile oupas, normalement pas de raison :P

Fichier(s) joint(s)

  • Fichier joint  Path.as   16.79 Ko   38 téléchargement(s)

Word hard, play hard.

#56 Urban angel

    Ceinture Verte

  • Members
  • PipPipPipPip
  • 50 messages

Posté 26 December 2012 - 23:21 PM

Merci pour ce travail acharné, ça compile nickel,
par contre en terme de performance... rien de changé,
je reste donc bien persuadé que le problème vient bien de quelque part, une fonction appelée qui fait tout ramer...
un truc bien incompatible(qui fait bien ramer) avec IOS.
je teste sur iPhone4S, iPad4 et ça rame bien fort...
je suis perplexe...
sans mon jeu et juste en perf brute sur une forme simple ça rame déjà...
je n'ai aucun moyen de faire un VRAI debug, pour savoir quelle fonction/appel/cast fait ramer autant,
il s'agit à coup sur d'un truc super précis.
car tes optimisations devraient deja faire la différence et cela ne change presque rien... il s'agit ptt simplement
du systeme SVG???
deja lu/vu ça sur un forum?

#57 lilive

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2993 messages

Posté 27 December 2012 - 19:15 PM

Dans la boucle qui parcours le path en faisant un _path.getPoint(l), tu pourrais essayer d'enlever l'appel à cette fonction:

_path.getPoint(l) renvoie le point du path à la longueur l, et l augmente de deux pixels à chaque tour de la boucle.
Donc tu pourrais parcourir le path une première fois par pas de 2 pixels et stocker ces points dans un array, ou encore mieux un vector
Puis dans la boucle du drag, plutôt que d'appeler _path.getPoint, tu utiliserais les points du vector.

#58 Urban angel

    Ceinture Verte

  • Members
  • PipPipPipPip
  • 50 messages

Posté 28 December 2012 - 01:16 AM

Pfiou ce code me donne le tourni... y a tellement de boucle dans tous les sens...
le getIndexAt() est appelé dans le getPoint(), etc...

je ne saisi pas le fonctionnement du SVG, et tout le toutim de ce code en fait...
du coup ça me bloque pour comprendre ce qui se passe
je l'utilise parce que tu me l'a gentiment fourni, et je m'en sert sans problème, mais là c'est au dessus de mes force de le comprendre :/
je suis pourtant pas le dernier des abruti, et tu as bien documenté ton code... niarf

Quand au Vector, j'ai lu des trucs dessus, mais pas encore pratiqué, car il ne faut pas de vide dedans, etc...

PS : il est pas augmenté de 2 pixel, mais réduit de 2 pixel, (cf dans la fonction Move: l-=2 )
PS : j'ai reviré les Showerror, pour gagner un peu dans els boucles aussi.

Et petite question débile du matin, les appels de la fonction getPoint()
sachant qu'il y a une fonction getPoint() différente dans CHAQUE fichier du dossier geom,
comment il sait laquelle choisir? car elles sont toute différente...
moi je regarde celle du fichier Path, mais comme on inclue tout le dossier geom, elles sont toutes au même niveau non?

Fichier(s) joint(s)

  • Fichier joint  Path.as   16.84 Ko   43 téléchargement(s)


#59 lilive

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2993 messages

Posté 28 December 2012 - 11:29 AM

Voir le messagelilive, le 27 December 2012 - 19:15 PM, dit :

Dans la boucle qui parcours le path en faisant un _path.getPoint(l)
Ceci n'est pas dans les classes du Path, mais dans le code principal de gestion du drag:

// Boucle pour parcourir tout le chemin, par pas de 2 pixels
while (l <= length) {

        p = _path.getPoint(l);   // Trouver le point positionné à la longueur l sur le chemin
        dist = p.subtract(mousePos).length;  // Calculer la distance entre ce point et le pointeur de la souris

        // voir si ce point est plus proche de la souris que le point précédemment testé,
        // et si ce point n'est pas plus éloigné de la position précédente du curseur de plus de 20 pixels
        if ((bestMatchDist == -1 || dist < bestMatchDist) && p.subtract(currentPos).length < 20) {
         // Dans ce cas c'est un bon candidat pour être la prochaine position du curseur
                bestMatch = p;
                bestMatchDist = dist;
        }

        l += 2;

}
 

Et je dis que tu pourrais remplacer la ligne
p = _path.getPoint(l);
par
p = pointsDuPath[i];
à condition que tu remplisses d'abord le tableau (ou vector) pointsDuPath dans une première boucle.






Voir le messageUrban angel, le 28 December 2012 - 01:16 AM, dit :

Pfiou ce code me donne le tourni... y a tellement de boucle dans tous les sens...
le getIndexAt() est appelé dans le getPoint(), etc...
je ne saisi pas le fonctionnement du SVG, et tout le toutim de ce code en fait...
du coup ça me bloque pour comprendre ce qui se passe
je l'utilise parce que tu me l'a gentiment fourni, et je m'en sert sans problème, mais là c'est au dessus de mes force de le comprendre :/
Oui ça ne m'étonne pas que ça puisse être dur de rentrer dedans. Mais comme tu dois l'avoir compris maintenant, ce n'est pas ce que je te suggère.

J'en profite aussi pour te rappeler que depuis le début je m'interroge sur la pertinence de choisir mon code ;) . Celui de Nataly me semblait bien, plus facilement abordable, et moins couteux en calculs.


Quand aux Vector, ils se manipulent dans bien des cas comme des Array, ce n'est pas bien difficile. Et il faut y songer dès qu'on a des besoins d'optimiser: http://forums.mediab...eralites/vector

#60 Urban angel

    Ceinture Verte

  • Members
  • PipPipPipPip
  • 50 messages

Posté 28 December 2012 - 12:53 PM

Alors en rajoutant un simple break, des la détection du BestMatch, le code semble être bcp plus fluide...
j'ai aussi viré tous les code des boucles qui annoncent des errors...
j'ai aussi poussé le pas de 4 pixels...

Mais j'ai surtout triché en limitant le nombre de boucles dans une fouchette de 300pixel.
grace a une valeur : lsave.

et là, pour le coup, c'est extremement fluide, car ça ne regarde plus tout depuis la fin du Path,
juste depuis le dernier point valable + 200.


var lsave:int = 100;

function onTouchMove(event:TouchEvent) {
var thelength:int = _path.length;        // La longueur du chemin
var l:int = lsave + 200;
if ( l > thelength ){ l = thelength }
trace("length " + thelength )// Va varier entre 0 et length dans la boucle
mousePos = new Point(event.stageX, event.stageY);

// Position du pointeur de la souris
currentPos = new Point(MovieClip(parent).TheSlider.x, MovieClip(parent).TheSlider.y); // Position actuelle du curseur
var p:Point;              // Point placé à la longueur l sur le chemin
var dist:Number;                 // Distance entre p et le pointeur de la souris
var bestMatch:Point;        // Meilleure position trouvée sur le chemin       
var bestMatchDist:Number = -1;    // distance entre bestMatch et le pointeur de la souris

// Boucle pour parcourir tout le chemin, par pas de 2 pixels
//var start : int = getTimer();
while (l> 0) {
 
  p = _path.getPoint(l);         // Trouver le point positionné à la longueur l sur le chemin
  dist = p.subtract(mousePos).length;  // Calculer la distance entre ce point et le pointeur de la souris
  // voir si ce point est plus proche de la souris que le point précédemment testé,
  // et si ce point n'est pas plus éloigné de la position précédente du curseur de plus de 20 pixels
  if ((bestMatchDist == -1 || dist < bestMatchDist) && dist < 20) {
   // Dans ce cas c'est un bon candidat pour être la prochaine position du curseur
   bestMatch = p;
   bestMatchDist = dist;
   lsave = l;
   trace("nb L " + l)
   break;
  }
  l-=4;
}
//trace(getTimer() - start, "ms");
if (bestMatch == null) return;    // Si on n'a rien trouvé de valable au revoir

// Sinon on place le curseur sur ce point
MovieClip(parent).TheSlider.x = bestMatch.x;
MovieClip(parent).TheSlider.y = bestMatch.y;
}
 


#61 lilive

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2993 messages

Posté 28 December 2012 - 23:32 PM

Le problème avec le break c'est que tu n'obtiens pas la position sur le path la plus proche du pointeur de la souris.
Et l'idée de ne vérifier le path que sur une certaine distance est bonne, sauf si tu veux que le drag puisse reconnaitre les croisements situés au-delà de la distance que tu vérifies.

Tu ne le dis pas, mais j'ai l'impression que tu ne comprends pas l'optimisation que je proposais, alors la voici:


2 nouvelles variables

var _pathPoints:Vector.<Point>  = new Vector.<Point>();
var _numPoints:int;
 

Une fois que le Path est prêt:

// Calculer les points du Path situés tous les 2 pixels, et les stocer dans _pathPoints
_numPoints = _path.length / 2;
_pathPoints = new Vector.<Point>();
var i:int;
var p:Point;
for (i = 0; i < _numPoints; i ++) {
        p = _path.getPoint(i * 2);
        _pathPoints.push(p);
}
// Rajouter le dernier point du Path
p = _path.getPoint(_path.length);
_pathPoints.push(p);
_numPoints = _pathPoints.length;
 

Et pour finir la nouvelle boucle pour le drag

private function onMouseMove(e:MouseEvent):void {
       
        var mousePos:Point = new Point(mouseX, mouseY);  // Position du pointeur de la souris
        var currentPos:Point = new Point(_disk.x, _disk.y);  // Position actuelle du curseur
        var p:Point;  // Point placé sur le chemin
        var dist:Number;  // Distance entre p et le pointeur de la souris
        var bestMatch:Point;  // Meilleure position trouvée sur le chemin                                     
        var bestMatchDist:Number = -1;  // distance entre bestMatch et le pointeur de la souris
       
        // var startTime:int = getTimer();
        // var j:int;
        // for (j = 0; j < 100; j ++) {
               
        var i:int;
        for (i = 0; i < _numPoints; i ++) {
                p = _pathPoints[i];
                dist = p.subtract(mousePos).length;
                if ((bestMatchDist == -1 || dist < bestMatchDist) && p.subtract(currentPos).length < 20) {
                        bestMatch = p;
                        bestMatchDist = dist;
                }
        }
       
        // }
        // trace(getTimer() - startTime);
       
        if (bestMatch == null) return;                          // Si on n'a rien trouvé de valable au revoir
       
        // Sinon on place le curseur sur ce point
        _disk.x = bestMatch.x;
        _disk.y = bestMatch.y;
       
}
 

Pour tester j'avais ajouté une boucle sur la variable j, sinon ça allait trop vite sur mon PC pour être mesurable. Résultat: code 4/5 fois plus rapide.

Fichier(s) joint(s)



#62 lilive

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2993 messages

Posté 28 December 2012 - 23:45 PM

Sur PC toujours, je m'aperçois qu'il peut y avoir plusieurs MOUSE_MOVE émis entre deux rafraichissements de l'affichage. Ceci amplifie visuellement le problème de ralentissement. Donc comme idée de solution, c'est de mettre le code du drag en ENTER_FRAME plutôt qu'en MOUSE_MOVE.

Voici ce que ça donne (cette fois je n'ai pas commenté les lignes qui rajoutent la boucle inutile sur la variables j, pour voir le résultat)

Fichier(s) joint(s)



#63 Urban angel

    Ceinture Verte

  • Members
  • PipPipPipPip
  • 50 messages

Posté 29 December 2012 - 11:29 AM

Nikel, comme mon path augmente et se réduit avec les 2 fonctions Removedragpath et RemoveLastdragpath,
j'ai du créer une fonction update VectorPath a chaque ajout/destruction de bout du path.

Eh bien les optimisations vector améliorent le tout sur IOS en effet !
mais pas suffisamment pour que le framerate soit utilisable dans le jeu dan sur niveau standard.
( on va dans le 10fps, et 5 fps dans un grand path)

Du coup, je prend les nouvelles optimisation, et je rajoute ma boucle, mais a une plus grande échelle,
et le tour est joué, je me débrouillerais pour que mes besoins de croisement :)



1 utilisateur(s) li(sen)t ce sujet

0 membre(s), 1 invité(s), 0 utilisateur(s) anonyme(s)