Apprenez les bases du fonctionnement de FlashPunk - une bibliothèque étonnante pour vous faire gagner du temps et vous aider à créer le jeu parfait!
Jetons un coup d'œil au résultat final sur lequel nous allons travailler:
Utilisez les touches fléchées pour déplacer votre personnage (le gars bleu). Le gars rouge / brun est un PNJ; la zone rouge ombrée est une zone de danger et la zone verte est un bouton. Vous apprendrez comment créer tout cela dans ce tutoriel..
FlashPunk est une bibliothèque ActionScript 3 créée pour le développement de jeux Flash. Fondamentalement, il fait tout le travail difficile pour vous et vous permet de vous concentrer entièrement sur le développement de votre jeu, plutôt que sur le moteur qui le sous-tend. La meilleure chose à ce sujet est que vous n’avez pas besoin de Flash Pro: vous pouvez tout faire avec un éditeur de code gratuit comme FlashDevelop. Sans parler de la rapidité avec laquelle il faut dessiner des choses à l’écran, car il utilise le blitting!
Ce tutoriel passera en revue toutes les bases de FlashPunk. Après l'avoir suivi, vous serez prêt à faire un jeu simple avec cette incroyable bibliothèque!
Commencez par télécharger la dernière version de FlashPunk depuis le site officiel (ce tutoriel utilise la version du 30 août 2011). Placez le dossier "net", avec tout son contenu, dans votre dossier "src".
FlashPunk a une classe appelée Moteur
. Cette classe est ce qui commence tout dans la bibliothèque. Pensez-y comme Principale
classe, mais avec un code spécial pour alimenter toutes les classes de FlashPunk. Pour utiliser le Moteur
classe, nous allons modifier le Principale
classe un peu.
package import net.flashpunk.Engine; [Frame (factoryClass = "Preloader")] classe publique Main étend le moteur fonction publique Main (): void
Maintenant, notre classe s'étend Moteur
. Dans Principale
Le constructeur de, nous devons faire un appel à la Moteur
constructeur: c'est ce qui définit les informations importantes sur le jeu: largeur, hauteur, débit d'image et si le moteur doit fonctionner à un débit fixe ou non.
fonction publique Main (): void super (550, 400, 30, false);
Il y a une fonction qui peut (et doit être) remplacée par la Moteur
classe: la init ()
une fonction. Il ne fonctionnera qu'une fois et initialisera tout pour que le jeu fonctionne.
écraser la fonction publique init (): void trace ("Le jeu a commencé!");
Je suis presque sûr que tout le monde veut mettre quelque chose à l'écran et voir ce moteur fonctionner! Pour cette raison, les prochaines étapes couvriront les bases des éléments de FlashPunk, en ajoutant de la profondeur au fur et à mesure de l'avancement du didacticiel..
Dans FlashPunk, il existe des éléments appelés Des mondes
et Entités
. Ce sont les éléments principaux de la bibliothèque et vous les utiliserez du début à la fin de votre partie..
Les mondes ressemblent beaucoup à ce qu'on appelle communément un "écran". Tout dans votre jeu se produira dans un monde: le menu principal est un monde qui vous donnera accès au monde actuel du jeu, où vous ferez face à des ennemis et mourrez, qui vous mènera au jeu mondial, avec vos scores et statistiques sur comment vous avez fait. Plus d'informations sur les mondes seront expliquées plus tard.
Les entités sont exactement ce qu'elles semblent être; ils vivent dans un monde et y font quelque chose: un bouton est une entité; votre personnage est une entité; les ennemis et les balles sont des entités. Ce sont les choses qui donnent vie au jeu.
Dans ce cas, nous allons créer le monde du jeu (il est temps de créer le monde du menu principal plus tard, passons à l'action!) En étendant le programme de FlashPunk. Monde
classe:
package import net.flashpunk.World; classe publique GameWorld étend World fonction publique GameWorld ()
Maintenant que vous avez créé un monde, vous devez dire à FlashPunk que vous souhaitez que ce monde soit le monde actif. Faisons-le dans Main.as
:
var privé _gameWorld: GameWorld; fonction publique Main (): void super (550, 400, 30, false); _gameWorld = new GameWorld (); écrase la fonction publique init (): void trace ("Le jeu a commencé!"); FP.world = _gameWorld;
Et n'oubliez pas d'importer net.flashpunk.FP
!
Maintenant que nous avons notre monde, nous pouvons créer une entité en étendant la Entité
classe et l'ajouter à notre monde de jeu:
package import net.flashpunk.Entity; Classe publique GameEntity étend Entity fonction publique GameEntity ()
Et en GameWorld.as
:
private var _gameEntity: GameEntity; fonction publique GameWorld () _gameEntity = new GameEntity (); ajouter (_gameEntity);
Notez que si vous compilez et exécutez le jeu, l'entité n'apparaît pas à l'écran. C'est parce qu'il n'a pas encore d'image! Chaque entité peut avoir un objet graphique. Ce graphique peut être une seule image, une feuille de calcul avec des animations, des images en mosaïque - à peu près n'importe quoi.
Nous allons ajouter cette petite image à notre entité:
Le graphique d'une entité peut être consulté par le graphique
propriété. C'est comme ça qu'on va y mettre l'image! Tout d'abord, intégrez-le; alors, passez le à Image
Le constructeur de et FlashPunk se chargera de transformer cela en quelque chose de visible pour vous. Compiler et exécuter maintenant. Surprise! Notre entité est là!
package import net.flashpunk.Entity; importer net.flashpunk.graphics.Image; Classe publique GameEntity étend Entity [Embed (source = "/? /img/EntityImage.png")] private const IMAGE: Class; fonction publique GameEntity () graphic = new Image (IMAGE);
Voici ce que vous devriez obtenir:
Maintenant que nous avons notre entité à l'écran, pourquoi ne pas la faire bouger? Chaque Entité
a une fonction appelée mettre à jour()
, que vous devez remplacer pour utiliser. Cette fonction est appelée par chaque monde au début de chaque image. Si vous avez besoin de faire bouger votre entité, c'est l'endroit où vous mettez votre code!
écrasez public function update (): void x + = 10 * FP.elapsed; y + = 5 * FP.elapsed;
Et n'oubliez pas d'importer:
importer net.flashpunk.FP;
Voyez-le en action! (Actualisez la page si vous ne voyez rien ici.)
Vous avez peut-être remarqué l'utilisation de FP.elapsed
. FP.elapsed
donne la durée écoulée depuis la dernière image (en secondes), ce qui facilite grandement la création de mouvements en fonction du temps. Cependant, pour que cela fonctionne, vous devez avoir défini le quatrième paramètre sur Moteur
le constructeur de faux
. Rappelez-vous que (étape 2)? Le mettre à faux
signifie que vous voulez que FlashPunk s'exécute avec un timestep variable, alors que le régler sur vrai
fait en sorte que FlashPunk s'exécute sur un pas de temps fixe. Faire ce dernier, vous n'avez pas besoin d'utiliser FP.elapsed
. Vous saurez que chaque fois que le mettre à jour()
la fonction est appelée, un cadre est passé.
L'entité évolue dans une seule direction lors de la dernière étape. Introduction à la saisie au clavier: vous pourrez maintenant déplacer l’entité où vous le souhaitez!
FlashPunk a une classe appelée Contribution
qui prend en charge les entrées au clavier et à la souris. Dans ce tutoriel, nous n'utiliserons que la saisie au clavier pour le mouvement. C'est très facile:
outrepasser public function update (): void if (Input.check (Key.A) || Input.check (Key.LEFT)) x - = 50 * FP.elapsed; else if (Input.check (Key.D) || Input.check (Key.RIGHT)) x + = 50 * FP.elapsed; if (Input.check (Key.W) || Input.check (Key.UP)) y - = 50 * FP.elapsed; else if (Input.check (Key.S) || Input.check (Key.DOWN)) y + = 50 * FP.elapsed;
Et les déclarations d'importation:
importer net.flashpunk.utils.Input; importer net.flashpunk.utils.Key;
Input.check ()
résultats vrai
si la Clé
passé comme un argument est pressé au moment où la fonction a été appelée. Il y a d'autres fonctions très utiles, comme Input.pressed ()
, qui retourne vrai
si la touche a été enfoncée au moment de l'appel de la fonction (c'est-à-dire si la touche était en haut il y a une image et est maintenant en bas), ou Input.released ()
, qui fait exactement le contraire.
Une autre chose intéressante que le Contribution
La classe que nous permet de faire est de définir plusieurs clés sous un même nom. Par exemple, nous pourrions définir Key.UP
, Key.W
et Key.I
comme "UP"
, et seulement vérifier pour Input.check ("UP")
. De cette façon, nous pouvons améliorer notre fonction:
fonction publique GameEntity () graphic = new Image (IMAGE); Input.define ("UP", Key.W, Key.UP); Input.define ("DOWN", Key.S, Key.DOWN); Input.define ("LEFT", Key.A, Key.LEFT); Input.define ("RIGHT", Key.D, Key.RIGHT); écrasera public function update (): void if (Input.check ("LEFT"))) x - = 50 * FP.elapsed; else if (Input.check ("RIGHT")) x + = 50 * FP.elapsed; if (Input.check ("UP")) y - = 50 * FP.elapsed; else if (Input.check ("DOWN")) y + = 50 * FP.elapsed;
Et voici ce que vous devriez obtenir:
Les entités peuvent faire beaucoup plus que simplement se déplacer et avoir des images. Jetons un coup d'oeil à quelles surprises ils peuvent contenir!
Les entités ont une propriété appelée type
. Vous pouvez définir cette propriété sur la chaîne de votre choix. Cela vous permet d'organiser vos entités en groupes, ce qui s'avérera très utile dans la prochaine étape (sur les mondes). Nous pouvons, par exemple, définir le type de notre entité sur "GameEntity":
fonction publique GameEntity () graphic = new Image (IMAGE); Input.define ("UP", Key.W, Key.UP); Input.define ("DOWN", Key.S, Key.DOWN); Input.define ("LEFT", Key.A, Key.LEFT); Input.define ("RIGHT", Key.D, Key.RIGHT); type = "GameEntity";
Suite à cela, nous avons l'utile monde
la propriété et la ajoutée()
et enlevé ()
les fonctions. le monde
Cette propriété vous permet d'accéder au monde à partir du code de l'entité une fois que l'entité a été ajoutée à un monde. C'est comme le étape
propriété en commun Développement Flash; les fonctions sont comme le ADDED_TO_STAGE
et REMOVED_FROM_STAGE
les auditeurs d'événements. Voici un exemple des fonctions travaillant dans GameEntity.as
:
redéfinit la fonction publique added (): void trace ("L'entité a été ajoutée au monde!"); trace ("Entités dans le monde:" + world.count); écrase la fonction publique removed (): void trace ("L'entité a été retirée du monde!");
Il est temps d’examiner de plus près les mondes et leur fonctionnement. Tout d’abord, FlashPunk ne peut avoir qu’un seul monde à la fois, mais votre jeu peut en avoir autant que vous le souhaitez, à condition qu’un seul reste actif à chaque fois..
Les mondes ont mettre à jour()
tout comme les entités, mais leur fonction est un peu différente: il existe un code réel dans le Monde
classe. Cela signifie que vous devrez appeler super.update ()
chaque fois que vous remplacez cette fonction.
En plus des entités, les mondes peuvent aussi avoir graphique ajouté à eux. Les graphiques sont des images que vous n'avez pas besoin de mettre à jour (FlashPunk crée toujours une entité pour les ajouter au monde, de sorte que le moteur envoie toujours un appel à un mettre à jour()
une fonction). Vous pouvez les ajouter en appelant addGraphic ()
.
La chose la plus importante à propos des mondes est qu’ils ont plusieurs fonctions pour récupérer certaines entités: getType ()
, getClass ()
, Avoir tout()
, getLayer ()
et getInstance ()
. De cette façon, vous pouvez demander au monde de renvoyer un tableau de toutes les puces actuellement dans le jeu, de sorte que vous puissiez effectuer une vérification de toutes les puces pour une collision. Très pratique, je dois dire!
Regardez le code ajouté à World.as
. Nous allons également utiliser une deuxième image:
[Embed (source = "/? /Img/EntityImage2.png")] private const IMAGE: Class; fonction publique GameWorld () _gameEntity = new GameEntity (); ajouter (_gameEntity); addGraphic (nouvelle image (IMAGE), 0, 50, 50); écrase la fonction publique update (): void super.update (); var entityArray: Array = []; getType ("GameEntity", entityArray); pour chaque (var entité: Entity dans entityArray) entity.x = entity.x> 550? 550: entity.x; entity.y = entity.y> 400? 400: entity.y;
Et n'oubliez pas d'importer net.flashpunk.graphics.Image
!
Dans ce code, le addGraphic ()
appel de fonction ajoute un autre graphique similaire à _gameEntity
Le graphique - Pensez-y comme à un PNJ! - au monde dans la position (50, 50). Les lignes 23 à 31 montrent un exemple de récupération des entités d’un type particulier: nous appelons getType ()
obtenir uniquement des entités du type "GameEntity" (actuellement une seule entité). Après cela, nous parcourons toutes les entités extraites et les empêchons de dépasser les frontières droite et inférieure. (Ainsi, l'entité peut se déplacer en dehors de l'écran, mais pas loin.) Simple, n'est-ce pas??
Temps pour quelque chose de plus intéressant! FlashPunk prend en charge des animations de toutes sortes. Tout ce que vous avez à faire est, au lieu de créer une instance de Image
, créer une instance de Carte de l'esprit
. Cette classe reçoit une feuille de sprite et vous permet de mapper des cadres et de créer des liens vers des animations..
Dans notre classe d'entité, intégrez ce spritemap:
Ensuite, créez une instance de Carte de l'esprit
et passez le spritesheet en tant que paramètre au constructeur. Après cela, il suffit d'appeler le ajouter()
et jouer()
les fonctions!
[Embed (source = "/? /Img/EntitySheet.png")] private const SHEET: Class; private var _timeInterval: Number; fonction publique GameEntity () graphic = new Spritemap (SHEET, 40, 20, onAnimationEnd); Spritemap (graphic) .add ("Arrêté", [0]); Spritemap (graphique) .add ("Clignotant", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 24); Input.define ("UP", Key.W, Key.UP); Input.define ("DOWN", Key.S, Key.DOWN); Input.define ("LEFT", Key.A, Key.LEFT); Input.define ("RIGHT", Key.D, Key.RIGHT); type = "GameEntity"; Spritemap (graphic) .play ("Clignotant"); fonction privée onAnimationEnd (): void Spritemap (graphic) .play ("Stopped"); _timeInterval = 0; écrase la fonction publique update (): void _timeInterval + = FP.elapsed; if (_timeInterval> = 3) Spritemap (graphic) .play ("Clignotant"); if (Input.check ("LEFT")) x - = 50 * FP.elapsed; else if (Input.check ("RIGHT")) x + = 50 * FP.elapsed; if (Input.check ("UP")) y - = 50 * FP.elapsed; else if (Input.check ("DOWN")) y + = 50 * FP.elapsed;
Le constructeur de Carte de l'esprit
(ligne 19) prend quatre arguments: une source pour obtenir un graphique, la largeur et la hauteur de chaque image de la feuille de sprites et une fonction de rappel à appeler à la fin de l’animation (facultatif). Dans GameEntity
Le constructeur de, nous créons le Carte de l'esprit
et définir deux animations: "Stopped", qui ne contient que la première image et tourne à 0 fps (arrêté!) et "Blinking", qui contient toutes les images et tourne à 24 images par seconde.
Le reste du code est là pour jouer l'animation "Blinking" toutes les trois secondes.
Jetez un coup d'œil à notre entité qui clignote:
Lorsque tout fonctionne bien, il est temps d'introduire une autre fonctionnalité: la détection de collision. FlashPunk possède un excellent système de détection des collisions: tout ce que nous avons à faire est de définir des hitbox pour nos entités et de demander au monde de vérifier les collisions. Pour cela, nous allons créer une autre entité appelée Boîte
qui contiendra le graphique suivant:
package import net.flashpunk.Entity; importer net.flashpunk.graphics.Image; Classe publique Box Box Entity [Embed (source = "/? /img/BoxImage.png")] private const IMAGE: Class; fonction publique Box () graphic = new Image (IMAGE); setHitbox (60, 60);
Et à l'intérieur GameWorld.as
:
var_box privé: Box; fonction publique GameWorld () _gameEntity = new GameEntity (); _box = new Box (); ajouter (_gameEntity); ajouter (_box); _box.x = 200; _box.y = 150; addGraphic (nouvelle image (IMAGE), 0, 50, 50);
le setHitbox ()
function définit un rectangle qui agira comme une zone de résultats pour l'entité. Les deux premiers paramètres sont la largeur et la hauteur de la boîte. Les deux paramètres suivants (facultatif) sont les coordonnées d'origine (x et y) du rectangle. Faire la même chose pour GameEntity
:
fonction publique GameEntity () graphic = new Spritemap (SHEET, 40, 20, onAnimationEnd); Spritemap (graphic) .add ("Arrêté", [0]); Spritemap (graphique) .add ("Clignotant", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 24); Input.define ("UP", Key.W, Key.UP); Input.define ("DOWN", Key.S, Key.DOWN); Input.define ("LEFT", Key.A, Key.LEFT); Input.define ("RIGHT", Key.D, Key.RIGHT); type = "GameEntity"; Spritemap (graphic) .play ("Clignotant"); setHitbox (40, 20);
Maintenant que notre entité et la boîte de dialogue sont configurées avec des hitbox, nous devons vérifier les collisions dans la classe mondiale:
écraser la fonction publique update (): void super.update (); var entityArray: Array = []; getType ("GameEntity", entityArray); pour chaque (var entité: Entity dans entityArray) entity.x = entity.x> 550? 550: entity.x; entity.y = entity.y> 400? 400: entity.y; if (_gameEntity.collideWith (_box, _gameEntity.x, _gameEntity.y)) trace ("Collision!");
le entrer en collision avec()
fonction vérifie la collision avec l'entité passée en argument, plaçant pratiquement la première entité (dans ce cas, _gameEntity
) dans la position spécifiée par les deuxième et troisième arguments.
Une fois la collision détectée, il doit y avoir une réponse. Nous ne changerons que la position de l'entité en mouvement:
écraser la fonction publique update (): void super.update (); var entityArray: Array = []; getType ("GameEntity", entityArray); pour chaque (var entité: Entity dans entityArray) entity.x = entity.x> 550? 550: entity.x; entity.y = entity.y> 400? 400: entity.y; if (_gameEntity.collideWith (_box, _gameEntity.x, _gameEntity.y)) _gameEntity.x = _gameEntity.y = 0;
Regardez l'exemple. Essayez de déplacer l'entité dans la boîte.
FlashPunk n'a pas de boutons par défaut. Presque tous les jeux ont besoin de boutons, nous allons donc créer une Bouton
classe. Tout d’abord, un bouton a trois états (comme vous le savez peut-être grâce au développement courant de Flash): "Up", "Over" et "Down". Ce spritesheet illustre que:
Et maintenant commençons le cours:
package import net.flashpunk.Entity; importer net.flashpunk.graphics.Spritemap; Classe publique Button extension Entity protected var _map: Spritemap; Fonction publique Bouton (x: nombre = 0, y: nombre = 0) super (x, y); fonction publique setSpritemap (asset: *, frameW: uint, frameH: uint): void _map = new Spritemap (asset, frameW, frameH); _map.add ("Up", [0]); _map.add ("Over", [1]); _map.add ("Down", [2]); graphique = _map; setHitbox (frameW, frameH); écraser la fonction publique render (): void super.render ();
le setSpritemap ()
function définit un spritemap pour le bouton et définit des "animations" pour le bouton. Toujours, l'image doit avoir d'abord le cadre "Haut", puis le "Sur", suivi du cadre "Bas". Il y a aussi un appel à setHitbox ()
. La hitbox sera utilisée pour vérifier si la souris est ou non sur la case du bouton..
Maintenant que notre bouton affiche avec succès une image, il est temps de créer des contrôles haut, bas et bas. Nous allons le faire en créant deux attributs booléens: "over" et "clicked". Nous allons également détecter si la souris est sur la zone de résultats du bouton ou non. Ajouter ces fonctions dans Bouton.as
:
protected var _over: Boolean; protected var _clicked: Boolean; écrasez public function update (): void if (! world) return; _over = false; _clicked = false; if (collidePoint (x - world.camera.x, y - world.camera.y, Input.mouseX, Input.mouseY)) if (Input.mouseDown) mouseDown (); else mouseOver (); fonction protégée mouseOver (): void _over = true; fonction protégée mouseDown (): void _clicked = true; écraser la fonction publique render (): void if (_clicked) _map.play ("Down"); else if (_over) _map.play ("Over"); else _map.play ("Up"); super.render ();
Et n'oubliez pas d'importer net.flashpunk.utils.Input
.
Suivre la logique dans mettre à jour()
: tout d’abord, les deux attributs (_cliqué
et _plus de
) sont mis à false. Après cela, nous vérifions si la souris est au-dessus du bouton. Si ce n'est pas le cas, les attributs resteront faux et le bouton sera dans l'état "Up". Si la souris est terminée, nous vérifions si le bouton de la souris est actuellement enfoncé. Si cela est vrai, le bouton est dans l'état "Down" et _cliqué
est défini sur true; s'il est faux, le bouton est dans l'état "Over" et le bouton _plus de
attribut est défini sur true. Ces attributs définiront le cadre dans lequel le spritemap doit aller..
Ce bouton sera inutile si vous ne pouvez pas détecter quand l'utilisateur a cliqué dessus. Modifions un peu la classe afin de prendre en charge les fonctions de rappel:
protected var _callback: Fonction; var_argument protected: *; fonction publique Bouton (rappel: fonction, argument: *, x: nombre = 0, y: nombre = 0) super (x, y); _callback = callback; _argument = argument; écrase la fonction publique update (): void if (! world) return; _over = false; _clicked = false; if (collidePoint (x - world.camera.x, y - world.camera.y, Input.mouseX, Input.mouseY)) if (Input.mouseReleased) clicked (); else if (Input.mouseDown) mouseDown (); else mouseOver (); fonction protégée a cliqué (): void if (! _argument) _callback (); else _callback (_argument);
Notre bouton est fait! Ce code vous permettra de transmettre une fonction de rappel (et éventuellement un argument) à votre bouton. Ainsi, chaque fois que l'utilisateur cliquera sur le bouton, la fonction sera appelée..
Beaucoup d'étapes et rien sur l'écran? Il est temps de mettre un bouton là-bas! C'est aussi simple que d'ajouter ce code dans GameWorld.as
:
[Incorporer (source = "/? /Img/ButtonSheet.png")] private const BUTTONSHEET: Class; private var _button: bouton; fonction publique GameWorld () _gameEntity = new GameEntity (); _box = new Box (); _button = new Button (onButtonClick, null); _button.setSpritemap (BUTTONSHEET, 50, 40); ajouter (_gameEntity); ajouter (_box); add (_button); _box.x = 200; _box.y = 150; _button.x = 400; _button.y = 200; addGraphic (nouvelle image (IMAGE), 0, 50, 50); fonction privée onButtonClick (): void FP.screen.color = Math.random () * 0xFFFFFF; trace ("Le bouton a été cliqué!");
Il ne reste plus qu’à compiler le projet et le bouton sera là!
Et maintenant, la dernière fonctionnalité de FlashPunk qui sera présentée dans ce tutoriel! le Console
est l'outil de débogage de FlashPunk: il comporte des journaux, qui ressemblent beaucoup à des traces; indique le temps nécessaire pour exécuter une étape importante du moteur; et affiche le nombre d'entités à l'écran et le FPS actuel. C'est un excellent outil à utiliser pour développer votre jeu. Pour l'activer, ajoutez simplement la ligne suivante à Main.as
:
écraser la fonction publique init (): void trace ("Le jeu a commencé!"); FP.console.enable (); FP.world = _gameWorld;
Et pour enregistrer quoi que ce soit dedans, utilisez le FP.log ()
une fonction. Par exemple, changeons cela trace()
appel:
redéfinit la fonction publique init (): void FP.console.enable (); FP.log ("Le jeu a commencé!"); FP.world = _gameWorld;
C'est à peu près ça! Vous verrez que la partie "Sortie" de la console de débogage affiche maintenant le journal. Vous pouvez aller de l'avant et changer tous les trace()
appelle dans notre code pour appeler FP.log ()
.
Et c'est notre introduction à FlashPunk, qui couvre les aspects les plus importants de cette bibliothèque étonnante: entités, mondes, images et animations; collision, boutons, saisie et mouvement. J'espère que vous aimerez cette bibliothèque autant que moi - cela facilite vraiment le travail!