Déplacement facile et fluide du clavier dans AS3 avec la classe d'entrée

Il y a beaucoup de jeux là-bas avec des mouvements saccadés et irréalistes et qui ne peuvent faire qu'une chose à votre produit: le rendre peu attrayant pour le public. Mais la fluidité des mouvements n’est pas difficile à atteindre - mettons-nous au travail!


Aperçu du résultat final

Jetons un coup d'œil au résultat final sur lequel nous allons travailler:


Étape 1: Configurer l'environnement

Ceci est un tutoriel simple, de sorte que la configuration sera aussi simple.

Créez un nouveau projet Flash ActionScript 3.0. La taille et la couleur de la scène importent peu, utilisez simplement ce avec quoi vous êtes à l'aise.

J'utilise FlashDevelop pour le codage, mais cela peut aussi être fait dans n'importe quel éditeur AS, comme Flash Pro (ou n'importe quel éditeur de texte, peut-être Notepad;)). Alors, créez un fichier de classe, assurez-vous que votre code ressemble beaucoup au mien; voir ci-dessous. J'ai appelé le mien "Mouvement". (Si vous utilisez Flash Pro, consultez ce guide pour créer un cours.)

 package import flash.display.Sprite; Classe publique Movement étend Sprite fonction publique Movement (): void 

Une fois que vous avez terminé, assurez-vous que votre classe est liée au projet Flash en tant que classe principale..


Étape 2: Créer le carré et les variables

Donc, après avoir lié la classe de mouvement à votre document, définissez les variables comme je l'ai fait ci-dessous.

 package import flash.display.Sprite; import flash.events.Event; Classe publique Movement includes Sprite // Objet qui déplacera private var square: Sprite; // La vitesse maximale private var _max: Number = 10; // Les variables qui vont être appliquées pour déplacer le carré privé var dx: Number = 0; private var dy: Number = 0; fonction publique Movement (): void // Écouter l'ajout à l'événement de scène addEventListener (Event.ADDED_TO_STAGE, init);  fonction privée init (e: Event): void removeEventListener (Event.ADDED_TO_STAGE, init); // Créer un nouveau Sprite et dessiner à l'intérieur d'un carré carré = new Sprite (); square.graphics.beginFill (0x333333); square.graphics.drawRect (0, 0, 30, 30); square.x = stage.stageWidth / 2 - square.width / 2; square.y = stage.stageHeight / 2 - square.height / 2; addChild (carré); 

C'est à peu près tout ce que nous ferons pour créer l'objet. Vous pouvez utiliser votre propre objet mais pour ce tutoriel de mouvement simple, j'ai utilisé ce carré simple.


Étape 3: Présentation de la classe Input.as

Salut les gars, c'est la classe Input.as; Input.as Class ce sont les gars dont je t'ai parlé - sois gentil avec eux! :)

Alors, en quoi consiste ce cours, vous vous demandez peut-être. Fondamentalement, il fait votre travail de manipulation de clé pour vous. Il ajoute un écouteur aux événements ENTER_FRAME - de faible priorité - et un écouteur de clé remplissant certains dictionnaires privés. En outre, il utilise une autre classe pour les codes de clé. Vous pouvez regarder à l'intérieur et voir par vous-même comment ça marche.

Remarque: La classe Input.as ne m'appartient pas. Il a été créé par Matthew Bush, qui a porté Box2D en Flash..

 // Exemple d'utilisation de la classe Input.as // Vous devez toujours l'initialiser avec le paramètre stage Input.initialize (stage); // Après l'initialisation, vous pouvez utiliser les méthodes kd (), kp () ou ku (), qui // renvoient une valeur booléenne si les conditions sont remplies. // Ces méthodes acceptent plusieurs arguments, // donc pour un événement, vous pouvez utiliser plusieurs clés. // Cela facilite grandement l'accessibilité de votre application. Voir ci-dessous, car j'utilise un seul appel pour détecter la flèche vers le haut ou W pour monter. Input.kd ("UP", "W");

Étape 4: Importer les classes

Alors maintenant que vous connaissez la classe Input.as, nous allons l'importer dans notre classe de mouvement et l'initialiser..

 package import flash.display.Sprite; import flash.events.Event; importation d'entrée; Classe publique Movement includes Sprite // Objet qui déplacera private var square: Sprite; // La vitesse maximale private var _max: Number = 10; // Les variables qui vont être appliquées pour déplacer le carré privé var dx: Number = 0; private var dy: Number = 0; fonction publique Movement (): void // Écouter l'ajout à l'événement de scène addEventListener (Event.ADDED_TO_STAGE, init);  fonction privée init (e: Event): void removeEventListener (Event.ADDED_TO_STAGE, init); // Créer un nouveau Sprite et dessiner à l'intérieur d'un carré carré = new Sprite (); square.graphics.beginFill (0x333333); square.graphics.drawRect (0, 0, 30, 30); square.x = stage.stageWidth / 2 - square.width / 2; square.y = stage.stageHeight / 2 - square.height / 2; addChild (carré); // Initialise la classe Input.as avec le gestionnaire sur la scène Input.initialize (stage); // Ajouter la boucle d'actualisation addEventListener (Event.ENTER_FRAME, refresh);  rafraîchissement de la fonction privée (e: Event): void 

Étape 5: Gestion des entrées de clé

J'utilise une boucle basée sur ENTER_FRAME pour détecter les entrées de clé; ci-dessous est le rafraîchir() méthode qui est la fonction de gestionnaire pour cet événement.

 rafraîchissement des fonctions privées (e: Event): void // Gestionnaire de clés if (Input.kd ("A", "LEFT")) // Déplacer à gauche if (Input.kd ("D", "RIGHT ")) // Déplacez le curseur vers la droite if (! Input.kd (" A "," GAUCHE "," D "," DROIT ")) // S'il n'y a aucune pression gauche / droite if (Entrée .kd ("W", "UP")) // Move up if (Input.kd ("S", "DOWN")) // Move down if (! Input.kd ("W", "UP", "S", "DOWN")) // S'il n'y a pas d'action haut / bas

Étape 6: Explication des calculs - Gestion de la vitesse

C'est assez simple. Détecter si l'une des touches est enfoncée, puis agir en conséquence.

J'utilise beaucoup l'opérateur ternaire: valeur = condition? vrai faux;
Ceci est essentiellement une instruction if condensée en une seule ligne.

J'utilise cette méthode pour chaque détection de clé: si la valeur est supérieure à _max puis le mettre égal à _max; sinon, incrémentez ou décrémentez cette valeur particulière, selon le cas. De cette façon, il reste dans certaines limites. Simple, droit?

Ci-dessous, vous pouvez étudier les conditions:

 Fonction privée d'actualisation (e: Event): void // Gestionnaire de clés if (Input.kd ("A", "LEFT"))) // Déplacement vers la gauche dx = dx < 0.5 - _max ? _max * -1 : dx - 0.5;  if (Input.kd("D", "RIGHT"))  //Move to the right dx = dx > _max - 0.5? _max: dx + 0,5;  if (! Input.kd ("A", "GAUCHE", "D", "DROIT")) // S'il n'y a pas de gauche / droite enfoncée si (dx> 0.5) dx = dx < 0.5 ? 0 : dx - 0.5;  else  dx = dx > -0,5? 0: dx + 0,5;  if (Input.kd ("W", "UP")) // Monter dy = dy < 0.5 - _max ? _max * -1 : dy - 0.5;  if (Input.kd("S", "DOWN"))  //Move down dy = dy > _max - 0.5? _max: dy + 0,5;  if (! Input.kd ("W", "UP", "S", "DOWN")) // S'il n'y a pas d'action haut / bas si (dy> 0.5) dy = dy < 0.5 ? 0 : dy - 0.5;  else  dy = dy > -0,5? 0: dy + 0,5;  // Après tout cela, appliquez-les à l'objet square.x + = dx; square.y + = dy; 

Si vous n'êtes pas familier avec l'opérateur ternaire, prenez un morceau de papier et un stylo et écrivez-en quelques-uns au format if… else; c'est un excellent exercice pour se familiariser avec ce qui se passe.

Gardez à l'esprit que je manipule le dx et mourir variables, et définissez uniquement les valeurs x et y réelles à la fin. Cela nous aide à rendre le mouvement fluide; ce n'est pas saccadé puisque nous modifions leurs valeurs directement dans la fonction…

Allez, teste-le! Voyez comme ça bouge?


Étape 7: Traitement des collisions de limite

D'accord. Tout va bien, ça bouge avec fluidité - mais HORS du plateau! Ci-dessous, j'ai ajouté les conditions de détection de collision.

 Fonction privée d'actualisation (e: Event): void // Gestionnaire de clés if (Input.kd ("A", "LEFT"))) // Déplacement vers la gauche dx = dx < 0.5 - _max ? _max * -1 : dx - 0.5;  if (Input.kd("D", "RIGHT"))  //Move to the right dx = dx > _max - 0.5? _max: dx + 0,5;  if (! Input.kd ("A", "GAUCHE", "D", "DROIT")) // S'il n'y a pas de gauche / droite enfoncée si (dx> 0.5) dx = dx < 0.5 ? 0 : dx - 0.5;  else  dx = dx > -0,5? 0: dx + 0,5;  if (Input.kd ("W", "UP")) // Monter dy = dy < 0.5 - _max ? _max * -1 : dy - 0.5;  if (Input.kd("S", "DOWN"))  //Move down dy = dy > _max - 0.5? _max: dy + 0,5;  if (! Input.kd ("W", "UP", "S", "DOWN")) // S'il n'y a pas d'action haut / bas si (dy> 0.5) dy = dy < 0.5 ? 0 : dy - 0.5;  else  dy = dy > -0,5? 0: dy + 0,5;  // Détection de frontière if (square.x - dx < 0 || square.x + dx + square.width > stage.stageWidth) // détection d'axe x if (square.y - dy < 0 || square.y + dy + square.height > stage.stageHeight) // détection de l'axe des ordonnées // Après tout cela, appliquez-les à l'objet square.x + = dx; square.y + = dy; 

Il recherche les limites de manière plus précise en vérifiant si les bords de la place atteignent les limites (auparavant, il s'agissait simplement de vérifier le centre de la place par rapport aux limites)..

Génial. Nous devons maintenant ajouter le code pour que le carré rebondisse sur les limites. Ce que je fais pour cela est de multiplier par -1 la valeur de l'axe dx ou mourir. Mais ce n'est pas assez! Si la vitesse est assez rapide, alors le carré passera à travers les marges ou deviendra tout simplement fou. Donc, avant de multiplier, nous devons définir le x ou le y de l'objet pour qu'il soit identique à la limite qu'il rencontre..

Donc, si x objet.x = 0; puis multipliez le dx par -1.

 // Détection de marge if (square.x - dx < -dx || square.x + dx + square.width > stage.stageWidth) // détection d'axe x square.x = square.x - dx < -dx ? 0 : stage.stageWidth - square.width; dx *= -1;  if (square.y - dy < -dy || square.y + dy + square.height > stage.stageHeight) // détection d'axe des y square.y = square.y - dy < -dy ? 0 : stage.stageHeight - square.height; dy *= -1; 

Testez-le maintenant! Bouncy droit? :)

Pour le rendre encore meilleur, continuez à expérimenter différentes valeurs - par exemple, au lieu de multiplier par -1, essayez -0.7 et visualisez les résultats..


Conclusion

Vous avez donc rencontré la classe Input.as, appris à travailler avec elle et créé un joli mouvement fluide en quelques minutes à peine. Je pense que cela compte comme un bon moment!

S'il vous plaît laissez vos commentaires ci-dessous et d'autres questions, je serai heureux de répondre.

Mais si vous rencontrez un problème, vérifiez deux fois votre code, comparez-le avec le fichier source. Si vous ne pouvez pas le faire fonctionner, n'hésitez pas à poser une question..