Nous voyons des lignes utilisées dans beaucoup de scénarios. Les courbes sont également utilisées, bien que peut-être moins fréquemment - mais cela ne nuit pas à leur importance! Dans ce didacticiel, nous examinerons de plus près les courbes, en particulier les courbes quadratique et cubique, ainsi que certaines de leurs caractéristiques mathématiques couramment utilisées..
Jetons un coup d'œil au résultat final sur lequel nous allons travailler. Faites glisser les points rouges et voyez les gradients changer de position.
Et voici une autre démo, utilisant des courbes cubiques, sans les dégradés:
Quadratique et cubique seront présentés dans chacune de ces sections. Alors regardons d'abord l'équation des courbes. Ces équations sont écrites sous forme polynomiale, en commençant par le terme de degré le plus élevé. La première est l'équation quadratique (degré le plus élevé est 2); la seconde est l'équation cubique (le degré le plus élevé est 3).
\ [f (x) = Axe ^ 2 + Bx + C \… (eq \ 1) \]
\ [g (x) = Axe ^ 3 + Bx ^ 2 + Cx + D \… (éq \ 2) \]
Notez que A, B, C et D sont des nombres réels. Alors maintenant que nous en avons connaissance, essayons de le visualiser. Les courbes graphiques seront notre prochaine tentative.
Commençons par tracer une courbe quadratique. Je suis sûr que tous les lecteurs ont tracé la courbe quadratique en classe de mathématiques au lycée, mais pour vous rafraîchir la mémoire, je présente des graphiques ci-dessous. Ils sont placés côte à côte pour faciliter la comparaison.
La différence évidente est l'axe des y inversé sur l'espace de coordonnées Flash. Ils ont l'air simple dans l'ensemble, non? Ok, maintenant nous sommes prêts à tracer sur l'espace de coordonnées Flash.
Pour positionner les courbes quadratiques au bon endroit, nous devons comprendre les équations correspondantes. La courbe dessinée dépend réellement des coefficients de l'équation (dans le cas du quadratique, il s'agit de A, B et C).
J'ai inclus une présentation Flash ci-dessous afin que vous puissiez facilement ajuster ces coefficients et obtenir un retour immédiat..
Pour étudier les effets de coefficients individuels sur la courbe globale, je suggère de suivre les étapes ci-dessous pour expérimenter avec la présentation Flash ci-dessus..
Une autre observation intéressante est que, tout au long des deuxième et troisième étapes de ce qui précède, le point d'inflexion (c'est-à-dire le point de retournement) reste au même point sur l'axe des ordonnées..
Vous voyez rapidement qu'il est un peu difficile de positionner une courbe. L’équation utilisée n’est pas pratique si nous voulons, par exemple, localiser les coordonnées du point le plus bas d’une courbe.
Solution? Nous réécrirons l'équation sous la forme souhaitée. Découvrez l'équation suivante:
\ [f (x) = P (x + Q) ^ 2 + R \]
C'est toujours une équation quadratique, mais elle a pris une autre forme. Maintenant, nous pouvons facilement contrôler les points minimum et maximum de la courbe. Dans la précédente présentation Flash, cliquez sur le bouton "Approche 1" en haut à droite et jouez avec les nouvelles valeurs.
Voici une brève explication des rôles des coefficients:
Coefficient | Rôle |
P | Contrôler l'inclinaison de la courbe. |
Q | Contrôler le déplacement du point d'inflexion de la courbe le long de l'axe des x. |
R | Contrôler le déplacement du point d'inflexion de la courbe le long de l'axe des y. |
Néanmoins, il est toujours difficile de faire passer la courbe à travers un ensemble de points donné. Il faudrait pré-calculer rigoureusement sur papier avant de le traduire en code.
Heureusement, il existe une meilleure solution. Mais avant de passer à travers, jetons un coup d'œil à la mise en oeuvre ActionScript dès maintenant..
Voici les équations écrites sous forme de fonctions ActionScript (cochez Graphing.as
dans le téléchargement source).
fonction privée quadratic1 (x: nombre, A: nombre, B: nombre, C: nombre): nombre // y = A (x ^ 2) + B (x) + C retourne A * x * x + B * x + C fonction privée quadratique2 (x: nombre, p: nombre, q: nombre, r: nombre): nombre // y = p * (x + q) ^ 2 + r retourne p * (x + q) * ( x + Q) + R
Et voici une implémentation de la méthode de dessin utilisant Graphics.drawPath ()
. Juste une note que toutes les courbes dans cet article sont dessinées de la même manière.
D'abord les variables…
points var privés: vecteur.= nouveau vecteur. ; private var drawCommand: Vecteur. = nouveau vecteur. ;
Maintenant, les positions y, calculées sur la base des positions x et des coefficients donnés.
fonction privée redessinée (A: Number, B: Number, C: Number): void pour (var i: int = 0; i < 400; i++) var x:Number = i - 200; points[i * 2] = x * 10 + stage.stageWidth >> 1; if (isApproach1) points [i * 2 + 1] = quadratique1 (x, A, B, C) + stage.stageHauteur >> 1 sinon points [i * 2 + 1] = quadratique2 (x, A, B , C) + stage.stageHeight >> 1 if (i == 0) drawCommand [i] = 1; sinon drawCommand [i] = 2; graphics.clear (); graphics.lineStyle (1); graphics.drawPath (drawCommand, points);
(Confus au sujet de la >>
opérateur? Jetez un oeil à ce tutoriel.)
Supposons que nous ayons trois points que la courbe quadratique doit traverser; Comment formons-nous l'équation correspondante? Plus précisément, comment pouvons-nous déterminer les valeurs de coefficient de l'équation? L'algèbre linéaire vient à la rescousse. Analysons ce problème.
Nous savons que les équations du second degré prennent toujours la forme décrite dans l'équation. 1 à l'étape 1.
\ [f (x) = Axe ^ 2 + Bx + C \… (eq \ 1) \]
Étant donné que les trois coordonnées indiquées se trouvent sur la même courbe, elles doivent chacune satisfaire cette équation, avec les mêmes coefficients que l'équation de la courbe que nous recherchons. Écrivons cela sous forme d'équation.
Étant donné trois coodinates:
Remplacez ces valeurs par (équation 1). Notez que A, B, C sont des inconnus pour le moment.
\ [f (x) = Axe ^ 2 + Bx + C \… (eq \ 1) \]
Maintenant, réécrivez sous forme de matrice. Prenez note que A, B, C sont les inconnues que nous résolvons pour.
[latex]
\ begin bmatrix S_y \\ T_y \\ U_y \ end bmatrix =
\ begin bmatrix
\ left (S_x \ right) ^ 2 & \ left (S_x \ right) & 1 \\
\ left (T_x \ right) ^ 2 & \ left (T_x \ right) & 1 \\
\ left (U_x \ right) ^ 2 & \ left (U_x \ right) & 1 \ end bmatrix
\ begin bmatrix A \\ B \\ C \ end bmatrix \\
[/latex]
[latex]
\ begin bmatrix
\ left (S_x \ right) ^ 2 & \ left (S_x \ right) & 1 \\
\ left (T_x \ right) ^ 2 & \ left (T_x \ right) & 1 \\
\ left (U_x \ right) ^ 2 & \ left (U_x \ right) & 1 \ end bmatrix ^ - 1
\ begin bmatrix S_y \\ T_y \\ U_y \ end bmatrix =
\ begin bmatrix
\ left (S_x \ right) ^ 2 & \ left (S_x \ right) & 1 \\
\ left (T_x \ right) ^ 2 & \ left (T_x \ right) & 1 \\
\ left (U_x \ right) ^ 2 & \ left (U_x \ right) & 1 \ end bmatrix ^ - 1
\ begin bmatrix
\ left (S_x \ right) ^ 2 & \ left (S_x \ right) & 1 \\
\ left (T_x \ right) ^ 2 & \ left (T_x \ right) & 1 \\
\ left (U_x \ right) ^ 2 & \ left (U_x \ right) & 1 \ end bmatrix
\ begin bmatrix A \\ B \\ C \ end bmatrix \\
[/latex]
[latex]
\ begin bmatrix
\ left (S_x \ right) ^ 2 & \ left (S_x \ right) & 1 \\
\ left (T_x \ right) ^ 2 & \ left (T_x \ right) & 1 \\
\ left (U_x \ right) ^ 2 & \ left (U_x \ right) & 1 \ end bmatrix ^ - 1
\ begin bmatrix S_y \\ T_y \\ U_y \ end bmatrix
= Je
\ begin bmatrix A \\ B \\ C \ end bmatrix
\\
K ^ - 1 J = L
[/latex]
Bien sûr, nous pouvons utiliser des équations simultanées à la place, mais je préfère utiliser des matrices car c'est plus simple.. (Note de la rédaction: aussi longtemps que vous comprenez les matrices!)
Nous obtiendrons l'inverse de K et multiplierons par la matrice J pour obtenir L. Une fois que nous aurons résolu avec succès A, B, C, nous substituerons simplement l'équation quadratique. Ainsi, nous aurons une courbe quadratique qui passe par les trois points.
Comme mentionné à l'étape précédente, nous devons effectuer une inversion et une multiplication de matrice 3x3. ActionScript flash.geom.matrix
la classe ne pourra pas aider à cela. Bien sûr, nous avons le choix d'utiliser flash.geom.Matrix3D
, mais je préfère la bibliothèque Coral parce que je peux faire levier dans ces classes personnalisées et examiner ce qui se passe sous le capot. Personnellement, je trouve cela très utile lorsque vous doutez de la bonne utilisation des commandes, même après avoir lu la documentation de l'API..
Alors téléchargez et placez les fichiers Coral décompressés dans le dossier source de votre projet.
Voici un exemple du résultat. Essayez de repositionner les points rouges et de voir la courbe quadratique redessinée pour traverser les trois points..
Vous pouvez trouver le script complet dans Draw_curve.as.
Le code ActionScript suivant sert uniquement à activer les contrôles de la souris sur les petits points..
fonction publique Draw_Curve () // configuration des contrôles c1 = new Circle (0xFF0000); addChild (c1); c1.x = stage.stageWidth * 0.2; c1.y = stage.stageHeight >> 1; c2 = nouveau cercle (0xFF0000); addChild (c2); c2.x = stage.stageWidth * 0.5; c2.y = stage.stageHeight >> 1; c3 = nouveau cercle (0xFF0000); addChild (c3); c3.x = stage.stageWidth * 0.8; c3.y = stage.stageHeight >> 1; c1.addEventListener (MouseEvent.MOUSE_DOWN, déplacer); c1.addEventListener (MouseEvent.MOUSE_UP, déplacer); c2.addEventListener (MouseEvent.MOUSE_DOWN, déplacer); c2.addEventListener (MouseEvent.MOUSE_UP, déplacer); c3.addEventListener (MouseEvent.MOUSE_DOWN, déplacer); c3.addEventListener (MouseEvent.MOUSE_UP, déplacer); redraw () function privée move (e: MouseEvent): void if (e.type == "mouseDown") e.target.startDrag () e.target.addEventListener (MouseEvent.MOUSE_MOVE, mise à jour); else if (e.type == "mouseUp") e.target.stopDrag (); e.target.removeEventListener (MouseEvent.MOUSE_MOVE, mise à jour); mise à jour de fonction privée (e: MouseEvent): void redraw ();
Le noyau réside dans la redessiner
une fonction. J'ai mis en évidence les opérations matricielles et la fonction quadratique pour le processus de rafraîchissement.
fonction privée redessiner (): void K = new Matrix3d (c1.x * c1.x, c1.x, 1, 0, c2.x * c2.x, c2.x, 1, 0, c3.x * c3 .x, c3.x, 1, 0, 0, 0, 0, 1); K.invert () L = nouvelle matrice3d (c1.y, 0, 0, 0, c2.y, 0, 0, 0, c3.y, 0, 0, 0, 0, 0, 0, 0); L.append (K); graphics.clear (); points var: vecteur.= nouveau vecteur. ; var cmd: vecteur. = nouveau vecteur. ; pour (var i: int = 0; i < 200; i++) //current x var x:Number = i * 2; //f(x) = A (x^2) + B (x) + C var y:Number = L.n11* x* x + L.n21 * x + L.n31 ; points.push(x, y); if (i == 0) cmd.push(1); else cmd.push(2); graphics.lineStyle(1); graphics.drawPath(cmd, points);
Vous pouvez donc voir que la matrice K a été initialisée et inversée avant d’être ajoutée à la matrice J.
le ajouter()
function multiplie la matrice courante, J, avec la matrice d’entrée, K, placée à sa gauche. Un autre détail remarquable est que nous n'utilisons pas toutes les lignes et les colonnes des matrices K et J. Cependant, étant donné que l'inversion de matrice ne peut se produire qu'avec une matrice carrée, nous devons renseigner l'élément 4 de la 4ème ligne, 4ème colonne de K avec 1. (Il n'est pas nécessaire de le faire pour J car nous n'avons pas besoin de l'inversion de ce dernier dans notre calcul. ) Ainsi, vous pouvez voir que tous les autres éléments sont 0 sauf pour la première colonne.
Donc, c'est tout pour dessiner des courbes quadratiques. Passons aux courbes cubiques.
Encore une fois, nous aurons une petite révision de la représentation graphique de ces courbes. Découvrez l'image suivante:
Lorsque vous comparez cette courbe à celle du quadratique, vous remarquerez qu'elle est plus raide et qu'une partie de la courbe se situe en dessous de l'axe des x. Une moitié est réfléchie verticalement, comparé à un quadratique.
J'ai inclus la présentation Flash suivante pour vous permettre d'essayer les coefficients d'une équation cubique. Essayez de modifier la valeur de A de positif à négatif et observez la différence dans la courbe produite.
Voici la section importante de la mise en œuvre du graphique ci-dessus:
fonction privée redessinée (A: Number, B: Number, C: Number, D: Number): void pour (var i: int = 0; i < 400; i++) var x:Number = i - 200; points[i * 2] = x * 10 + stage.stageWidth >> 1; points [i * 2 + 1] = cubic1 (x, A, B, C, D) + stage.stageHeight >> 1 if (i == 0) drawCommand [i] = 1; sinon drawCommand [i] = 2; graphics.clear (); graphics.lineStyle (1); graphics.drawPath (drawCommand, points); fonction privée cubic1 (x: nombre, A: nombre, B: nombre, C: nombre, D: nombre): nombre // y = A (x ^ 3) + B (x ^ 2) + C (x) + D retourne A * x * x * x + B * x * x + C * x + D
Encore une fois, il est difficile de positionner la courbe cubique en fonction d'un ensemble de points qu'elle traverse. Encore une fois, nous nous référons à l'algèbre linéaire pour une alternative.
À l’étape 6, nous savons que les coefficients d’une équation quadratique peuvent être calculés sur la base de trois points donnés et que la courbe qui en est tirée traverse ces points. Une approche similaire peut être réalisée avec quatre points donnés pour obtenir une équation cubique:
Remplacez ces coordonnées par (éq 2). Notez que A, B, C, D sont des inconnus.
\ [g (x) = Axe ^ 3 + Bx ^ 2 + Cx + D \… (éq \ 2) \]
Mais maintenant nous allons traiter avec une matrice 4x4 au lieu de 3x3:
\ (
\ begin bmatrix S_y \\ T_y \\ U_y \\ V_y \ end bmatrix =
\ begin bmatrix
\ left (S_x \ right) ^ 3 & \ left (S_x \ right) ^ 2 & \ left (S_x \ right) & 1 \\
\ left (T_x \ right) ^ 3 & \ left (T_x \ right) ^ 2 & \ left (T_x \ right) & 1 \\
\ left (U_x \ right) ^ 3 & \ left (U_x \ right) ^ 2 & \ left (U_x \ right) & 1 \\
\ left (V_x \ right) ^ 3 & \ left (V_x \ right) ^ 2 & \ left (V_x \ right) & 1 \ end bmatrix
\ begin bmatrix A \\ B \\ C \\ D \ end bmatrix \\
P = QR \\
Q ^ - 1 P = Q ^ - 1 QR \\
Q ^ - 1 P = IR \\
Q ^ - 1 P = R
\)
Nous allons maintenant utiliser tous les éléments de la matrice 4x4 pour Q et de la première colonne entière pour P. Ensuite, Q est inversé et appliqué à P.
Encore une fois, nous avons configuré les contrôles de la souris pour permettre le glissement de ces points. Lorsque l'un de ces points est déplacé, le recalcul et le redessinage de la courbe se produisent constamment.
fonction publique Draw_Curve2 () // configuration des contrôles c1 = new Circle (0xFF0000); addChild (c1); c1.x = stage.stageWidth * 0.2; c1.y = stage.stageHeight >> 1; c2 = nouveau cercle (0xFF0000); addChild (c2); c2.x = stage.stageWidth * 0.4; c2.y = stage.stageHeight >> 1; c3 = nouveau cercle (0xFF0000); addChild (c3); c3.x = stage.stageWidth * 0.6; c3.y = stage.stageHeight >> 1; c4 = nouveau cercle (0xFF0000); addChild (c4); c4.x = stage.stageWidth * 0.8; c4.y = stage.stageHeight >> 1; c1.addEventListener (MouseEvent.MOUSE_DOWN, déplacer); c1.addEventListener (MouseEvent.MOUSE_UP, déplacer); c2.addEventListener (MouseEvent.MOUSE_DOWN, déplacer); c2.addEventListener (MouseEvent.MOUSE_UP, déplacer); c3.addEventListener (MouseEvent.MOUSE_DOWN, déplacer); c3.addEventListener (MouseEvent.MOUSE_UP, déplacer); c4.addEventListener (MouseEvent.MOUSE_DOWN, déplacer); c4.addEventListener (MouseEvent.MOUSE_UP, déplacer); redessiner (); fonction privée move (e: MouseEvent): void if (e.type == "mouseDown") e.target.startDrag () e.target.addEventListener (MouseEvent.MOUSE_MOVE, mise à jour); else if (e.type == "mouseUp") e.target.stopDrag (); e.target.removeEventListener (MouseEvent.MOUSE_MOVE, mise à jour); mise à jour de fonction privée (e: MouseEvent): void redraw ();
redessiner
est la fonction cruciale où tout est arrivé.
fonction privée redraw (): void var left: Matrix3d = new Matrix3d (c1.x * c1.x * c1.x, c1.x * c1.x, c1.x, 1, c2.x * c2.x * c2.x, c2.x * c2.x, c2.x, 1, c3.x * c3.x * c3.x, c3.x * c3.x, c3.x, 1, c4.x * c4. x * c4.x, c4.x * c4.x, c4.x, 1); left.invert () var right: Matrix3d = new Matrix3d (c1.y, 0, 0, 0, c2.y, 0, 0, 0, c3.y, 0, 0, 0, c4.y, 0, 0 , 0); right.append (à gauche); // f (x) = A (x ^ 3) + B (x ^ 2) + C (x) + D graphiques.clear (); points var: vecteur.= nouveau vecteur. ; var cmd: vecteur. = nouveau vecteur. ; pour (var i: int = 0; i < 200; i++) var x:Number = i * 2; var y:Number = right.n11 * x * x * x+ right.n21 * x * x+ right.n31 * x + right.n41; points.push(x, y); if (i == 0) cmd.push(1); else cmd.push(2); graphics.lineStyle(1); graphics.drawPath(cmd, points);
Enfin, regardons le produit. Cliquez et déplacez les points rouges pour voir la courbe cubique dessinée pour passer à travers tous ces points.
Nous venons de dessiner des polynômes de degré 2 et 3 (quadratiques et cubiques). D'après notre expérience, nous pouvons prédire que le calcul d'un polynôme de degré 4 (quintique) nécessitera cinq points, ce qui nécessitera une matrice de 5x5, et ainsi de suite pour les polynômes de degrés encore plus élevés..
Malheureusement, corail
et flash.geom.Matrix3D
N'autorisez que les matrices 4x4, vous devrez donc écrire votre propre classe si le besoin s'en fait sentir. Il est rarement requis dans les jeux, bien que.
Essayons d'appliquer nos connaissances pour diviser les régions sur notre scène. Cela nécessite une révision des inégalités d'équation. Regardez l'image ci-dessous.
Cette image ci-dessus montre une courbe divisant les régions en deux:
Ce n'est pas difficile à saisir ce concept. En fait, vous avez déjà expérimenté ceci à l'étape 11 en peaufinant les coefficients de la formule cubique. Imaginez, dans le système de coordonnées, qu'il existe un nombre infini de courbes, toutes différenciées par un léger changement de D:
Alors, voici l'échantillon de sortie pour la courbe quadratique. Vous pouvez essayer de déplacer le point rouge et voir les régions colorées.
Voici l'extrait de code ActionScript important. Découvrez le script complet dans Region_Curve.as
fonction privée redraw (): void var left: Matrix3d = new Matrix3d (c1.x * c1.x, c1.x, 1, 0, c2.x * c2.x, c2.x, 1, 0, c3. x * c3.x, c3.x, 1, 0, 0, 0, 0, 1); left.invert () var right: Matrix3d = new Matrix3d (c1.y, 0, 0, 0, c2.y, 0, 0, 0, c3.y, 0, 0, 0, 0, 0, 0, 0 ) right.append (à gauche); // D = A (x ^ 2) + B (x) + C pour chaque élément (var item: cercle en arrière-plan) var D: Number = right.n11 * item.x * item.x + right.n21 * item .x + right.n31; //trace(background[i].y); if (item.y> D) item.color = 0; else item.color = 0xAAAAAA;
Voici l'échantillon en ce qui concerne la courbe cubique.
Et la mise en œuvre qui va avec. Encore une fois, le script complet est dans Region_Curve2.as
// D = A + B (x) + C (x ^ 2) pour chaque (var item: cercle en arrière-plan) var D: Number = right.n11 * item.x * item.x * item.x; + right.n21 * item.x * item.x + right.n31 * item.x + right.n41 //trace(background[i].y); if (item.y> D) item.color = 0; else item.color = 0xAAAAAA;
Que diriez-vous de quelques ajustements pour changer la couleur sur différentes courbes? Encore une fois, cliquez avec la souris sur les points rouges et observez les changements de dégradé à l'écran..
Voici l'extrait de code ActionScript important extrait de Region_Curve3.as
. Tout d'abord, nous souhaitons connaître le décalage maximal et minimal par rapport à la courbe d'origine..
var max: nombre = 0; var min: nombre = 0; var Ds: vecteur.= nouveau vecteur. ; // D = A (x ^ 2) + B (x) + C pour chaque élément (var item: cercle en arrière-plan) var D: Number = right.n11 * item.x * item.x + right.n21 * item .x + right.n31; var offset: Number = item.y - D; Ds.push (offset); if (item.y> D && offset> max) max = offset; sinon si (item.y < D && offset < min) min = offset;
Une fois cela fait, nous l'appliquerons à la coloration des points individuels.
// variations de couleur en fonction du décalage var color: Nombre pour (var i: int = 0; i < background.length; i++) if (Ds[i] > 0) color = Ds [i] / max * 255 // calcul de la couleur à insérer dans l'arrière-plan [i] .color = color<<16 | color<<8 | color; //define a grayscale else if (Ds[i] < 0) color = Ds[i] / min * 255; background[i].color = color<<16; //define a gradient of red
Alors que tout pour le dessin des courbes. Ensuite, trouver les racines d’une courbe quadratique et cubique. Merci d'avoir lu. Partagez si vous voyez des applications de la vie réelle qui tire parti de ce tutoriel.