mercredi 22 décembre 2010

38 - Preloader

Un preloader, c'est un écran de chargement qui apparait au début d'une animation Flash et qui aide l'utilisateur à patienter en attendant qu'elle soit prête à être jouée ; le pourcentage de données chargées est généralement indiqué, et une petite animation sympa peut être intégrée pour rendre l'attente plus agréable.

J'ai donc programmé aujourd'hui le preloader de mon jeu ; il consiste en une ligne horizontale blanche qui balaie l'écran :
  • Si le pourcentage de données chargées est nul, la ligne est située tout en haut de l'écran ;
  • Une image est située au centre de l'écran ; lors de son passage, la ligne altère l'apparence de l'image et lui donne un aspect pixélisé ;
  • Lorsque le chargement est à 100%, la ligne se trouve tout en bas de l'écran ; néanmoins elle continue à descendre et disparait de l'écran, et quelques dixièmes de secondes plus tard un fondu au noir nous fait passer du preloader à l'écran titre.
J'ai imposé une durée minimale à l'animation du preloader : Ainsi, même si le chargement est rapide, la ligne ne peut pas descendre de plus de 2 pixels par frame (1/25 de seconde).




J'envisage de soumettre mon jeu au site Newgrounds ; à cet effet, j'ai créé une version alternative du preloader :

avant le passage de la ligne / après le passage de la ligne

dimanche 19 décembre 2010

37 - Menu Clic Droit

Les cinématiques de fin sont enfin timées convenablement ; j'ai donc pu enchainer sur le menu clic droit.

Quand on effectue un clic droit sur un fichier Flash standard, on a accès à de nombreuses options : lire, zoomer, en avant, rembobiner...
Le problème, c'est que si un joueur clique sur "en avant", il accède à la scène suivante, ce qui peut engendrer de nombreux bugs et/ou tricheries :

Dans mon jeu, les scènes "playerSelect", "donjon" et "ending" se suivent dans cet ordre.
  • si on clique sur "en avant" alors qu'on est à l'écran de sélection du personnage, on se retrouve dans le donjon sans avoir chargé les stats du Héros ;
  • si on clique sur "en avant" alors qu'on est dans le donjon, on accède directement à la cinématique de fin.
Pour éviter ces désagréments, il faut modifier le menu clic droit en supprimant les commandes de base ; on peut aussi ajouter ses propres commandes personnalisées.

var MENUPERSO = new ContextMenu();// création de la variable "menu contextuel personnalisé"
MENUPERSO.hideBuiltInItems();// suppression des commandes usuelles (lire, rembobiner, zoomer... )
var commande1 = new ContextMenuItem("Reset", reset); // la commande "Reset" appelle la fonction "reset" définie plus bas
var commande2 = new ContextMenuItem("Version " add _global.version, version);
MENUPERSO.customItems.push(commande1); // on ajoute la commande1 au menu
MENUPERSO.customItems.push(commande2);
function reset() { // cette fonction permet de retourner à l'écran titre
maxdepth = 2000;
for (i=0; i<=maxdepth; i++) { removeMovieClip(_root.getInstanceAtDepth(i));
// on efface tous les clips issus des scènes précédentes pour avoir un écran propre
}
gotoSceneAndPlay("preloader", 1);
// on retourne à la première scène du jeu
}
function version() {
// si la variable _global.version a pour valeur "1.00", alors la commande du menu aura pour nom "Version 1.00"
// le numéro de la version est indiqué à titre informatif : cliquer dessus n'a aucun effet
}
_root.menu = MENUPERSO;

Ce qui nous donne ceci :

Prochaine étape : Création du Preloader !

jeudi 16 décembre 2010

36 - Cinématiques de Fin

Je n'ai pas beaucoup avancé ces 2 dernières semaines ; néanmoins les 3 cinématiques de fin sont presque prêtes, il faut juste que je retravaille encore un peu le timing (je veux que les scènes ne soient pas trop longues, mais que le joueur ait quand même le temps de lire les textes et de regarder les images).

Après la cinématique de fin, le staff roll défile et présente "l'équipe de programmation" (c'est à dire... moi !), les logiciels utilisés, et la liste des personnages du jeu (le Héros, les PNJ, les ennemis).

Un indice est donné après le staff roll afin d'aider le joueur à débloquer les autres fins.

mardi 30 novembre 2010

35 - Améliorations Diverses

Aujourd'hui, outre la correction du bug découvert hier, je me suis occupé d'améliorer divers détails, comme par exemple empêcher l'utilisation d'objets de soin si les PV ou les PM sont déjà au maximum.

J'ai aussi travaillé sur un des secrets du jeu : Un mystérieux trésor bien caché mais au contenu surpuissant...

lundi 29 novembre 2010

34 - Load Game, New Game

Maintenant que j'ai un écran titre avec un menu opérationnel, il est possible de choisir entre "Load Game" (charger une partie) et "New Game" (nouvelle partie) ; dans le second cas, si le joueur sélectionne un fichier non vierge, un pop-up lui demandera s'il souhaite effacer le fichier (c'est-à-dire remettre les stats du personnage associé à zéro) ou s'il préfère charger la partie sans l'effacer (comme s'il avait choisi "Load Game").


À part ça, je viens de débusquer un bug : À chaque fois que le Héros trouve un équipement et gagne un Niveau lors d'une ouverture de coffre, s'il décide d'équiper l'objet, ses stats restent inchangées. Je corrigerai ça demain...

dimanche 28 novembre 2010

33 - Écran Titre

Pour l'écran titre de mon jeu, je me suis inspiré de celui de The Legend of Zelda sur NES : Ainsi, après quelques secondes, le titre cède sa place à un résumé de l'histoire et dévoile quelques éléments du jeu (la liste des items pour Zelda, un rapide tutoriel avec description des sorts et des objets pour Math & Magic).







lundi 22 novembre 2010

32 - Le Sort "Bomb"

Le sort "Bomb" (Bombe) fait partie des rares capacités pouvant être utilisées aussi bien en combat que lors de l'exploration :
  • En combat, ce sort inflige d'importants dégâts magiques non élémentaires ;
  • Dans le donjon, ce sort permet de détruire des éléments du décor afin de créer de nouveaux passages.
C'est pour cette raison que la sélection des objets s'effectue à la souris et non au clavier : Après avoir cliqué sur le parchemin du sort "Bomb", il suffit de cliquer sur les briques que l'on souhaite détruire (à condition bien sûr d'avoir suffisamment de PM ! )...

Outre le sort "Bomb", j'ai aussi permis l'utilisation hors combat du sort "Whirlwind" (Tourbillon) et de la Clé du Temps ; cette dernière permet de retourner à l'entrée du Donjon et de récupérer tous ses PV et PM.


Pour finir, un peu de teasing sur un des secrets du jeu :

Où se trouve ce coffre ? Comment y accéder ? Que contient-il ?

jeudi 18 novembre 2010

31 - Nouveau Comportement des Ennemis, Utilisation des Objets Hors Combat

J'ai apporté quelques modifications au comportement des ennemis par rapport à ce que j'avais dit dans mon billet n°26 ; la plus importante est que, si un ennemi n'a pas assez de PM pour utiliser son attaque spéciale, il saute son tour.

Pourquoi un tel changement ? Parce qu'il existe certains ennemis qui infligent des dégâts physiques importants et des dégâts magiques faibles ; dans l'ancienne version, lorsque ces ennemis étaient à cours de PM, ils effectuaient systématiquement des attaques physiques, ce qui les rendait encore plus dangereux !
J'ai donc modifié tout ça afin que les Joueurs qui baseraient leur stratégie sur l'usure des PM de leur adversaire aient toujours l'avantage, quelles que soient les stats de l'ennemi.


J'ai aussi bossé aujourd'hui sur l'utilisation des objets hors combat.
Alors que tout le reste du jeu se joue au clavier, ce point précis nécessite l'utilisation de la souris : Pour utiliser un objet, il suffit de cliquer deux fois sur son icone.
Afin d'éviter les attaques d'ennemis lors de la sélection de l'objet, le jeu se met automatiquement en pause si le joueur clique sur une icone (il est aussi possible de mettre le jeu en Pause avec la touche Entrée AVANT de passer au maniement à la souris).

Actuellement seuls les objets de soin (viandes, potions) et le sort "Heal" sont utilisables ; le screen ci-dessus met en avant l'augmentation des PM du Héros et la diminution de son nombre de potions +15 suite à l'utilisation de l'une d'elles.

Il y a une bonne raison qui m'a poussé à opter pour une sélection des objets à la souris (et non à l'aide d'un curseur contrôlé par les flèches du clavier, comme c'est le cas dans le reste du jeu) ; je vous révèlerai ça une prochaine fois...

mardi 16 novembre 2010

30 - Cinématiques (suite)

Aujourd'hui j'ai amélioré la cinématique de Game Over en ajoutant quelques effets : Quand le Héros est à terre, la Clé du Temps apparait et le renvoie à l'étage 0 ; le Héros est alors pris d'un sentiment de déjà vu...

J'ai aussi intégré une cinématique rare mettant en scène le Marchand ; cette cinématique ne se déclenche qu'une fois sur 10, et à condition que le Héros ait au moins 500 pièces d'or.

(sur le screen ci-dessus, on voit que le Héros possède moins de 500 pièces d'or ; c'est tout simplement parce que j'ai désactivé cette condition lors de mes tests)

lundi 15 novembre 2010

29 - Cinématique de début

Il est temps d'en dire un peu plus sur l'histoire du jeu (une histoire qui tient sur un ticket de métro, comme c'était le cas à l'époque des 8-bits)...

Flipp, le Héros du jeu, se rend dans le Donjon de Norenberc afin d'y trouver un artefact légendaire qui lui permettra de vaincre le Prince Gabriil (le gros méchant qui menace le Royaume) ; à sa grande surprise, le Donjon s'avère plus petit que prévu : Une pièce unique, avec au fond un coffre à trésor...

Mais ça ne pouvait évidemment pas être aussi simple : Le contenu du coffre est totalement différent de ce que Flipp espérait, et le Donjon bien plus vaste que tout ce qu'il aurait pu imaginer...

dimanche 14 novembre 2010

28 - Étages particuliers : le Premier, le Dernier

Le premier et le dernier étage sont un peu différents des autres en terme de structure : leur tracé ne correspond pas au Score, il n'y a pas d'ennemis, et ils contiennent un trésor spécial qui déclenche une cinématique lorsqu'on le ramasse.

Voici une petite preview de l'ultime étage du jeu :

Qu'y a-t-il tout à gauche de l'écran ? Ça sera à vous de le découvrir...

jeudi 11 novembre 2010

27 - Game Over

Eh oui, ce sont des choses qui arrivent, maintenant que les ennemis sont capables d'infliger des dégâts au Héros...

mardi 9 novembre 2010

26 - Attaque des Ennemis

Comme prévu, la création des animations des attaques des ennemis a été très rapide ; j'ai donc pu enchainer sur la création du comportement des ennemis.

À l'exception des plus faibles, chaque ennemi possède 2 attaques : Une attaque physique et une attaque spéciale qui consomme des points de magie (PM).
Ces attaques spéciales appartiennent à une des trois catégories suivantes :
  • Attaque magique élémentaire (liée à l'élément de l'ennemi) ;
  • Attaque physique puissante (inflige plus de dégâts que l'attaque physique de base, mais consomme des PM) ;
  • Attaque magique non élémentaire qui inflige des dégâts importants (seul le Boss final peut utiliser cette technique).
À l'origine je voulais que le choix de ces attaques soit soumis au hasard ; ainsi, un ennemi spécialisé dans les attaques magiques aurait par exemple eu 75% de chances d'utiliser un sort et seulement 25% de chances d'effectuer une attaque physique.
Mais j'ai finalement décidé de rendre le comportement des ennemis plus prévisible : Ils utilisent en alternance leurs deux attaques, et s'ils n'ont pas assez de PM pour utiliser une attaque spéciale, ils utilisent l'attaque physique à la place ; ce parti-pris permettra aux joueurs d'élaborer des stratégies sans risquer que ces dernières ne soient réduites à néant par un élément aléatoire.

Donc ça y est, les ennemis peuvent frapper le Héros, et ils n'y vont pas de main morte ! Je vais donc devoir équilibrer un peu leurs stats, surtout en début d'aventure (car à ce moment-là les joueurs n'ont accès qu'à un nombre limité de capacités).

dimanche 7 novembre 2010

25 - Effets et Animations des Capacités du Héros : FIN !

Ça y est, j'ai fini de programmer et animer les capacités du Héros ! Enfin !

Prochaine étape : Faire la même chose pour les ennemis.
Heureusement, ça ne devrait pas être bien long, vu que la plupart de leurs capacités seront des copier-coller de celles du Héros...

Voici des screens des 2 dernières capacités du Héros, "Elemental Change" et "Item" :

Les Flux de Mana sont représentés par des sinusoïdes traversant l'écran.

Le Héros peut utiliser des objets de soin en combat.

jeudi 4 novembre 2010

24 - Effets et Animations des Capacités : Morph

J'ai aujourd'hui travaillé sur une nouvelle capacité appelée "Morph" qui permet de transformer les ennemis : Ces derniers voient leur niveau descendre à 1, leur nombre d'XP descendre à 0, et se retrouvent affublés d'une apparence mignonne et/ou ridicule.

Un sort amusant, certes, mais qui possède un réel intérêt : Une fois l'ennemi vaincu, si le Score est inchangé, alors le Héros n'est pas téléporté et peut continuer l'exploration de l'étage actuel.


Il ne me reste désormais plus que deux capacités à programmer et animer : "Elemental Change" et "Item". Je les ai volontairement gardées pour la fin, car elles proposent toutes deux au joueur d'effectuer un choix à l'aide du clavier : "Elemental Change" permet de choisir un Flux de Mana afin de changer d'Élément, tandis qu'"Item" permet d'utiliser un objet pour regagner des PV ou des PM.

jeudi 28 octobre 2010

23 - Effets et Animations des Capacités (suite)

Je ne blogue plus trop ces derniers jours, mais rassurez-vous : Le projet avance bien.

J'ai par exemple créé aujourd'hui la capacité "Black Hole 3" ; cette dernière a pour effet de diviser par 2 (en arrondissant en dessous) toutes les stats du Héros et de l'ennemi qui sont des multiples de 3.

J'ai par la même occasion créé les capacités "Black Hole 4" et "Black Hole 5" qui marchent sur le même principe et utilisent la même animation : La journée a donc été productive, avec 3 capacités créées en moins de 2 heures !

Allez, je tiens le bon bout...

mardi 19 octobre 2010

22 - Effets et Animations des Capacités, Affichage des Dégâts

Je suis actuellement en train de programmer les effets des différentes capacités : Certaines font perdre des PV aux ennemis, mais d'autres permettent de modifier les stats des personnages (de manière positive ou négative suivant les cas). Ça me fait près d'une vingtaine de capacités à programmer, heureusement certaines reposent sur un modèle similaire, ce qui me fera gagner du temps...

Parallèlement à ça, je travaille aussi sur les animations de ces capacités ; bien qu'elles se résument à des effets visuels relativement simples, elles nécessitent malgré tout la création de nombreux éléments graphiques, ce qui va donc m'occuper encore quelques jours...

Bref, beaucoup de boulot, mais ça avance : J'ai entre autres mis au point aujourd'hui l'affichage des dégâts.
J'avais une idée bien précise de l'aspect des nombres, je voulais qu'ils soient composés de multiples carrés, et j'ai donc effectué une recherche de typos sur Dafont en espérant en trouver une qui corresponde à ce que j'avais en tête : Mon dévolu s'est finalement jeté sur Looksky Font par Espen Morten Kvalheim. Voici ce que ça donne :


samedi 16 octobre 2010

21 - Ordre des Actions en Combat, Écran de Victoire

Une fois que le joueur a sélectionné la capacité qu'il souhaite utiliser lors de ce tour de combat, on détermine qui va agir en premier.
En règle générale, si la stat Vitesse du Héros est supérieure ou égale à celle de l'ennemi, c'est le Héros qui agit en premier ; néanmoins, l'utilisation de certaines capacités a pour conséquence de faire jouer le Héros avant ou après l'ennemi, quelles que soient leurs Vitesses.

Une fois que le Héros et son adversaire ont effectué leur action du tour, un nouveau tour démarre : Les deux personnages récupèrent une quantité de MP égale à leur Niveau, puis la fenêtre de sélection des capacités s'affiche à nouveau.

Si le nombre de PV de l'un des personnages descend en dessous de 0, le combat s'arrête.


À l'heure actuelle seule la capacité "Attack" est utilisable : L'ennemi subit un nombre de dégâts égal à la valeur de la stat Attaque du Héros moins la valeur de la stat Défense de l'ennemi (si le résultat de cette soustraction est inférieur ou égal à 0, le nombre de dégâts est fixé à 1).

Le Héros est donc en mesure de diminuer les PV de l'ennemi, qui pour l'instant se contente simplement de sauter son tour (je m'occuperai des capacités des ennemis plus tard, quand toutes les capacités du Héros auront été programmées). Une fois les PV de l'ennemi descendus à 0, l'écran de victoire s'affiche :


En fin de combat, le Héros gagne des points d'expérience (XP) et des Pièces d'Or :
  • Le gain de Pièces d'Or dépend du niveau de l'ennemi et est tiré au sort entre deux valeurs seuil.
  • L'XP de l'ennemi s'ajoute au score du Héros ; Si ce score dépasse un certain seuil, le niveau du Héros augmente et il apprend un nouveau sort.

mercredi 13 octobre 2010

20 - Affichage et Sélection des Icones de Capacités

J'ai finalement réussi à régler les problèmes de la dernière fois, et j'ai donc pu un peu avancer sur la programmation du mode "Combat"...

Math & Magic est un RPG dont les combats se déroulent au tour par tour ; au début de chaque tour, une fenêtre représentant les icones des différentes capacités utilisables s'affiche.
Ces icones sont toutes blanches, à l'exception de la capacité sélectionnée qui apparait en couleur ; une simple pression sur une des 4 touches de direction permet de déplacer la sélection.
Le nom de la capacité sélectionnée ainsi que son coût en PM (s'il y en a un) sont affichés en dessous de cette fenêtre.


dimanche 10 octobre 2010

19 - Contretemps

Hier, après avoir mis au point l'affichage des différentes icones d'actions utilisables en combat, j'ai eu droit à ce charmant message d'erreur.
Il semblerait que mon code soit trop long et que je sois obligé de le découper en sous-fonctions, car il existe visiblement une taille limite 32k que doit respecter chaque section de code.

En fait mon jeu peut très bien tourner dans le lecteur Flash malgré ce souci, c'est juste que tant que j'ai ce message d'erreur je n'ai pas accès à la fenêtre de débogage (qui est quand même bien pratique pour vérifier l'évolution de mes variables et traquer les bugs).

Me voilà donc parti pour créer des tas de sous-fonctions à coups de copier-coller (avec au passage le risque de générer d'autres erreurs, en particulier à cause des variables locales que je vais sûrement devoir transformer en variables globales).


[edit] : Après quelques tests, il s'avère que le terme "section de code" ne désigne pas uniquement les instructions entre deux accolades (au sein d'une function ou d'un onFrame event), mais aussi l'ensemble des instructions au sein de ma scène "donjon" ; donc même si je découpe mes fonctions en sous-fonctions, du moment qu'elle sont toujours définies dans la scène "donjon", elles sont prises en compte et continuent à me faire dépasser la limite de 32k !
Mais j'ai trouvé la parade : Définir mes fonctions dans des Movie Clips ! Même si ces Clips sont présents dans la scène "donjon", leur code n'est pas considéré comme faisant partie du code de la scène.
Bref, j'en suis au même point : Copier-coller des portions de code ailleurs... -_-

vendredi 8 octobre 2010

18 - Initialisation des Stats des Ennemis

Comme je le disais la dernière fois, les stats des ennemis sont tirées au sort entre 2 valeurs prédéfinies. Mais pour certains ennemis les choses ne sont pas aussi simples...

Ainsi, la stat Magie de l'un des monstres du jeu est comprise entre 66 et 99 ET doit être un multiple de 3.
Un autre monstre donne un nombre d'XP compris entre 1 et 25 003 ET ce nombre se termine forcément par 0, 1, 2 ou 3.

La raison pour laquelle j'impose de telles contraintes aux stats des ennemis est intimement liée à la manière dont ces derniers peuvent être vaincus...

Bref, j'ai été confronté à de nombreux cas particuliers, et cela m'a réclamé un peu plus de temps que de simplement déterminer des valeurs maximales et minimales... Mais ça y est, le bestiaire est prêt !

samedi 2 octobre 2010

17 - Affichage du Pop-up de Combat

Lorsque le Héros entre en contact avec un ennemi, le jeu passe en mode "Combat" : Une fenêtre pop-up représentant le lieu du combat se superpose à l'écran d'exploration, et on affiche dessus les deux combattants ; les stats de l'ennemi sont elles aussi affichées et remplacent l'inventaire du Héros (en bas à droite).
Mais avant d'afficher ces stats, il me faut les déterminer : En fonction du type de l'ennemi, je fixe une valeur minimale et maximale pour chaque stat, puis je tire au sort un nombre dans cet intervalle.

À titre d'exemple, voici les stats du premier monstre du jeu, le Goblin :
  • Points de Vie : entre 7 et 12 ;
  • Points de Magie : entre 5 et 10 ;
  • Attaque : entre 13 et 17 ;
  • Défense : 1 ;
  • Magie : entre 3 et 7 ;
  • Vitesse : 6.
Voici ci-dessous deux exemples mettant en scène des Héros différents, des monstres différents et un décor différent :


(pour info, le nombre indiqué en bas à droite du monstre représente l'XP, c'est-à-dire l'expérience gagnée en fin de combat ; je n'en dirai pas plus pour l'instant, mais les actions du Héros peuvent fortement influencer cette valeur... )

lundi 27 septembre 2010

16 - Inventaire du Marchand - Achat d'Objets

Une fois que le marchand a fini son bavardage, il dévoile au Héros la liste des objets qu'il met en vente.
Le marchand propose un objet de chaque type : Une armure, un bandeau, une épée, un bouclier, un anneau, une paire de bottes, un morceau de viande, une potion, et un parchemin permettant d'apprendre un sort optionnel.

La puissance de chacun des équipements est tirée au sort entre deux valeurs ; cette fourchette de valeurs dépend de l'étage actuel, comme c'était le cas pour les trésors, mis à part qu'ici le maximum possède une valeur moindre : Ainsi une Épée trouvée dans un trésor à l'étage -18 donnera entre +12 et +22 Attaque, alorsqu'une Épée vendue par un marchand à ce même étage donnera seulement entre +12 et +16 Attaque.
En outre, si la puissance tirée au sort n'est multiple ni de 3, ni de 4, ni de 5, alors elle est diminuée de 1 jusqu'à ce qu'elle soit multiple d'au moins un de ces trois nombres.

La nature des deux objets de soin est déterminée par tirage au sort de la même manière que lorsqu'on les trouve dans des bourses : En fonction de l'étage, le pourcentage d'obtention de chaque type d'objet est différent (par exemple à l'étage -56 il y a 80% de chances de trouver une Viande+50 et 20% de chances de trouver une Viande+200).

Le parchemin de sort, pour finir, est lié lui aussi à l'étage actuel : Entre les étages 10 et 99 le marchand proposera le sort "Provoke" (provoquer), entre les étages 100 et 999 il proposera le sort "EnemHeal" (soin ennemi), etc.

Une fois la nature des objets vendus déterminée, il faut définir leur prix de vente. Pour les objets de type consommable et parchemin, ce prix est fixe ; en revanche pour les équipements, je dois prendre en compte le prix de revente de l'ancien équipement :
  • Pour les armures, le prix de vente est égal au bonus de PV ;
  • Pour les bandeaux, le prix de vente est égal au bonus de PM x 12 ;
  • Pour les autres pièces d'équipement, le prix de vente est égal au bonus de stat x 10 ;
  • Le marchand rachète le vieil équipement du Héros 1/4 de son prix de vente (arrondi en dessous).
Le prix de vente réel est donc égal au prix de vente moins le prix de rachat du vieil équipement ; ce prix ne peut pas être inférieur à 1 pièce d'or (si c'est le cas, je lui impose de prendre la valeur 1).

Exemple : Le marchand vend une armure +112 PV (prix de vente : 112 pièces d'or) ; Le Héros porte une armure +98 PV (prix neuf : 97 pièces d'or, prix de revente : 24 pièces d'or) ; le prix annoncé par le marchand ne sera donc pas 112 mais 112-24=88 pièces d'or.


Maintenant que je connais l'inventaire du marchand, je dois le communiquer au joueur ; pour ce faire j'ai créé un Clip appelé "cadre_shop" qui rassemble les diverses icones des objets vendus et possède plusieurs textes dynamiques (pour afficher les stats et les prix des objets vendus). Les objets susceptibles d'intéresser le Héros ont leur prix indiqué en bleu, les objets ayant des stats inférieures aux stats actuelles ont leur prix indiqué en rouge.

Je retire certains objets de la vente :
  • Les objets qui sont identiques à ceux déjà équipés par le Héros ;
  • Les objets de soin que le Héros possède déjà en 9 exemplaires ;
  • Les parchemins de sorts que le Héros a déjà appris.
Ces objets sont recouverts par un Clip portant la mention "Sold Out" et leur achat est impossible.


L'étape suivante consiste à permettre au joueur de sélectionner un objet et de l'acheter : J'ai créé un Clip représentant le curseur de sélection (4 triangles roses qui clignotent) et j'ai fait en sorte qu'on puisse le faire se déplacer d'une icone à une autre par simple pression sur une des 4 directions ; un fois l'objet choisi, une pression sur la touche "Entrée" permet de valider l'achat (à condition que le Héros possède suffisamment d'argent) : l'inventaire est alors modifié en conséquence, une sauvegarde automatique est effectuée, et l'affichage des objets vendus est actualisé (ajout d'étiquettes Sold Out si nécessaire).


Une fois la création du marchand terminée, j'ai procédé à quelques réglages afin que les joueurs ne deviennent pas trop riches trop rapidement : J'ai ainsi divisé par 2 les sommes trouvées dans les trésors, et grandement augmenté le prix des objets de soin. Mais il se peut que je modifie une nouvelle fois ces valeurs (dans un sens ou dans l'autre) une fois les combats contre les monstres implémentés...

samedi 25 septembre 2010

15 - Dialogue avec un PNJ

En dehors des trésors et des ennemis, il existe autre chose que le Héros peut trouver dans le Donjon : Des PNJ (Personnages Non Joueurs).

À l'origine je pensais utiliser différents types de PNJ :
  • Des marchands auprès de qui le Héros peut améliorer son équipement et s'approvisionner en objets de soin ;
  • Des vieux sages qui donnent des conseils quant à la bonne utilisation des différents sorts ;
  • Des aventuriers qui donnent des conseils sur la façon de battre les monstres.
Mais après réflexion, j'ai décidé de tout regrouper en un seul et même PNJ : Le marchand.


Quand le Héros entre en contact avec un marchand, il y a d'abord une phase de dialogue avant que le joueur ait accès à la liste des objets vendus ; pour chaque environnement du jeu, il existe 3 dialogues différents : En général il y a un message concernant le sort qui vient d'être appris lors du dernier Level Up, un message concernant le sort qui peut être acheté auprès du marchand, et le troisième concerne l'aventure au sens large (textes d'ambiance renforçant le background, mécaniques du jeu). Un tirage au sort détermine quel texte sera affiché.

Comme le marchand ne peut pas être rencontré dans la première zone, cela fait donc 18 textes au total, que j'avais rédigé un jour avant de me lancer dans la programmation ; je les ai donc intégré au jeu, en tenant compte des limitations de la fenêtre de texte : Celle-ci affiche en effet 6 lignes de 20 caractères, soit 120 caractères en tout (moins qu'un tweet !).

Il m'a donc fallu découper ces textes sur plusieurs pages, et reformuler certaines phrases pour qu'elles rentrent dans la fenêtre ; j'ai aussi mis certains mots-clé en avant en utilisant mes 2 variables "bleu" et "blanc". Au final, il y a donc pas mal de différences entre les textes d'origine et ceux qui seront visibles au cours du jeu.

jeudi 23 septembre 2010

14 - Level Up après ouverture d'un coffre

Comme je l'ai dit dans mon billet précédent, le score du Héros augmente de 1 chaque fois qu'il s'empare du trésor situé à l'extrême gauche de l'étage.
Si le score du Héros dépasse un certain seuil, son niveau augmente et il apprend un nouveau sort :

mardi 21 septembre 2010

13 - Sauvegarde Automatique - Changement d'Étage

Souvenez-vous : Il y a quelques semaines, lorsque je me suis lancé dans la programmation de ce jeu, ma première action a consisté à mettre au point les fichiers de sauvegarde.
Maintenant que les stats et l'inventaire du Héros peuvent être modifiés grâce aux trésors, il est temps que je mette à profit l'existence de ces fichiers afin de garder une trace de toutes ces modifications.
J'ai donc créé une fonction "autoSave" qui est appelée à chaque fois que le Héros ramasse un trésor et qui garde en mémoire la majorité des variables du jeu (stats, inventaire, High Score... ).

Je me suis ensuite occupé du changement d'étage : Quand le Héros s'empare du contenu du coffre situé à l'extrême gauche de l'étage, son score augmente de 1 et il est téléporté à l'entrée de l'étage suivant ; si son nouveau score est supérieur au High Score, je met ce dernier à jour et effectue une sauvegarde automatique.

lundi 20 septembre 2010

12 - Fenêtres de Textes - Modification de l'Inventaire - Choix

Une fois que le contenu du trésor a été tiré au sort, il faut transmettre cette information au joueur ; pour ce faire, j'utilise une fenêtre de texte au design une fois de plus rétro (texte blanc sur fond noir, cadre blanc pixelisé). À l'intérieur du Clip "fenêtre de texte" se trouve un objet "Texte dynamique", c'est à dire un texte que je peux modifier en fonction du message que je souhaite afficher.

Au moment d'effectuer mes recherches graphiques, j'ai opté pour une typo pixelisée appelée "Small Fonts" ; le problème c'est que cette typo est au format .fon, alors que SWISH Max utilise le format .ttf : J'ai donc dû chercher une typo TrueType qui, une fois l'option "police pixelisée" activée, ressemblerait suffisamment à "Small Fonts". Et fort heureusement parmi toutes les polices installées sur mon ordi il y en a une qui répond à ce critère : "Franklin Gothic Medium". La seule différence notable est la présence d'une barre sous le 1.

J'ai donc utilisé cette typo pour l'affichage des stats. Et je comptais bien l'utiliser aussi pour afficher les divers messages du jeu, sauf que...


Il est possible d'intégrer des balises HTML au sein d'un objet "texte dynamique" en activant l'option adéquate. Cela permet de modifier l'apparence de certains éléments du texte (mots en gras, en italique, soulignés, changement de taille ou de couleur), et de mettre ainsi certains mots en avant.
Il se trouve que j'ai justement envie que, lorsque le joueur reçoit le message "Vous avez trouvé une Épée +50 ATT, voulez-vous l'équiper ?", l'expression "Épée +50 ATT" ne soit pas écrite en blanc mais en bleu.

Le changement de couleur se fait à l'aide de la balise <font color ="#B0BCF9"></font>, sauf que je ne peux pas utiliser de guillemets tels quels car ils servent à marquer le début et la fin d'une chaîne de caractères ; je suis donc obligé d'utiliser le code ASCII du caractère guillemet à la place : chr(34).

message = "Le début est en blanc <font color=" add chr(34) add "#B0BCF9" add chr(34) add ">puis en bleu</font> et de nouveau en blanc !";
monTexteDynamique.text = message;

edit : suite à une remarque judicieuse de Fitz (voir les commentaires), j'ai découvert une autre façon d'intégrer des guillemets à ma chaîne sans pour autant passer par le code ASCII : Il me suffit juste de marquer le début et la fin de la chaîne avec des apostrophes et non des guillemets !
Le code ci-dessus aurait en fait pu être remplacé par :
message = 'Le début est en blanc <font color="#B0BCF9">puis en bleu</font> et de nouveau en blanc !';
monTexteDynamique.text = message;


Pour me simplifier la vie, je me suis créé une variable "bleu" et une variable "blanc" qui me permettent de changer de couleur facilement ; la variable "bleu" correspond en fait à la balise d'ouverture <font color ="#B0BCF9"> tandis que la variable "blanc" correspond à la balise de fermeture </font> :

bleu = "<font color=" add chr(34) add "#B0BCF9" add chr(34) add ">";
blanc = "</font>";
message = "Le début est en blanc " add bleu add "puis en bleu" add blanc add " et de nouveau en blanc !";
monTexteDynamique.text = message;

Le problème, c'est que l'activation des balises HTML a pour conséquence la désactivation de l'option "typo pixelisée" : Mon texte est certes multicolore, mais devient par la même occasion tout lisse !

J'ai donc dû me mettre en quête d'une typo qui soit pixelisée d'origine afin de pouvoir utiliser les balises HTML sans risque de lissage. Et mon choix s'est porté sur Apple ][ (une typo gratuite créée par Ivan Rood), même si l'espacement entre les caractères est plus important ; j'apprécie le fait que chaque caractère occupe un espace de taille identique, ça fait encore plus "vieux jeu 8-bits".

J'ai donc ma fenêtre de texte et ma typo, il me suffit juste d'afficher tout ça au moment adéquat et de modifier mon texte dynamique en fonction du message que je souhaite afficher ; cela donne à peu près ceci :

Une simple pression sur "Entrée" ferme la fenêtre de texte et permet au jeu de reprendre son cours.

Évidemment ce n'est pas tout de dire qu'une Potion+30 a été trouvée : Il faut aussi que l'inventaire soit modifié en conséquence, et que l'affichage soit actualisé pour témoigner de cette modification (ce qui est le cas sur le screen ci-dessus).


Pour les objets que le Héros peut équiper, les choses sont légèrement différentes : Le joueur a le choix entre équiper l'objet trouvé et jeter l'ancien, ou garder l'ancien et jeter le nouveau.
Ce choix s'effectue via un curseur qui se déplace lorsqu'on appuie sur les touches "Gauche" ou "Droite" et qui sélectionne deux cadres ("Yes" et "No") ; par défaut le curseur pointe sur la réponse qui privilégie le bonus de stat le plus important : Si le Héros ramasse une Épée +10 alors qu'il a une Épée +30, c'est la réponse "No" qui sera sélectionnée dès le départ.

Dans l'exemple de la capture d'écran ci-dessus, si le joueur appuie sur "Entrée", la stat "Attaque" (représentée par l'icone Épée) passera de 8 à 9 et l'Épée +8 sera jetée : Le coût en pièces d'or de cette Épée jetée sera ajoutée au "Junk" (l'icone Poubelle en haut à droite du cadre ITEMS) ; le Héros pourra par la suite convertir son Junk en pièces d'or s'il rencontre un marchand qui lui rachète ses objets inutiles.

samedi 18 septembre 2010

11 - Contenu des Trésors

Le contenu des trésors est différent selon qu'il s'agit d'une bourse ou d'un coffre :
  • Bourse : 50% de chances d'obtenir un équipement de puissance faible, 20% de chances de trouver une petite somme d'argent, 30% de chances de trouver un objet de soin (viande ou potion) ;
  • Coffre en bois : 75% de chances d'obtenir un équipement de puissance moyenne, 25% de chances de trouver une grosse somme d'argent ;
  • Coffre en métal rouge et or : 100% de chances d'obtenir un équipement de puissance supérieure.
À partir de ces pourcentages j'ai créé plusieurs variables de type "tableau": À chaque fois que le Héros entre en contact avec un trésor, on tire au sort une case du tableau correspondant afin de déterminer le contenu du trésor.

Exemple : La variable _global.contenuBourse est un tableau à 100 cases : 50 cases ont pour contenu la chaîne de caractères "Equipment", 20 cases ont pour contenu "Gold" et les 30 dernières ont pour contenu "Item". Si le Héros ramasse une bourse, je tire un nombre entre 1 et 100 * et je regarde le contenu de la case portant ce numéro.
( * : En réalité la première case d'une variable de type Array (tableau) a pour indice 0 ; en toute rigueur ce n'est donc pas un nombre entre 1 et 100 qui est tiré, mais un nombre entre 0 et 99. )

Si le trésor est de type "Equipment", il faut effectuer un nouveau tirage au sort afin de déterminer la nature de l'équipement (Épée, Armure, Bottes... ).
Le taux d'obtention de chaque type d'équipement est lié à l'élément de départ du Héros ; ainsi le Fire Knight (Chevalier de Feu) aura 24% de chances de trouver une Épée, 16% de chances de trouver un Anneau, 10% de trouver un Bouclier, etc.
Ces pourcentages sont eux aussi mis sous forme de tableau à 100 cases.

Une fois la nature du trésor déterminée, un dernier tirage au sort permet d'en déterminer la puissance ; ce tirage au sort s'effectue entre 2 valeurs, liées à l'étage où se trouve le Héros : Une Épée trouvée à l'étage -18 donnera entre +12 et +22 Attaque, tandis qu'une Épée trouvée à l'étage -180910 donnera entre +63 et +79 Attaque.

vendredi 17 septembre 2010

10 - Génération des Trésors

Au moment de la génération du Donjon, un trésor peut être créé dans chacune des salles qui composent l'étage.
Il y a forcément un coffre dans la salle la plus à gauche de l'étage (probabilité de 100%) ; en revanche dans la salle suivante la probabilité d'apparition d'un trésor est nulle.
Pour les autres salles, la probabilité d'apparition d'un trésor est liée à la position de la salle : Plus on s'approche du bord droit de l'écran, plus cette probabilité est faible (50% au mieux, 25% au minimum).
En fonction de ces diverses probabilités, je détermine pour chacune des salles si oui ou non un trésor va être généré. Si c'est le cas, je fais la liste des positions potentielles en fonction du type de salle (exactement comme je l'ai fait pour les monstres, en pensant à exclure la position du Héros de la liste) et j'en tire une au sort.

L'apparence du trésor est liée à sa position : Le trésor situé à l'extrême gauche est représenté par un coffre en bois, les trésors des autres salles sont représentés par des bourses ; l'apparence du trésor détermine la qualité des objets que l'on peut trouver dedans (les objets trouvés dans des coffres en bois sont plus puissants que ceux trouvés dans des bourses). Il parait même qu'il existe des coffres en métal rouges renfermant des objets prodigieux...

De plus, à chaque fois qu'un étage est généré, il y a une chance sur 3 pour qu'une des bourses de l'étage soit remplacée par un marchand.

Dans le cercle rouge : Le coffre en bois situé à l'extrême gauche de l'étage.
Dans les cercles verts : Des bourses.
Dans le cercle jaune : Un marchand (qui a remplacé une des bourses après tirage au sort).

Normalement je m'occuperai du contenu des trésors demain ; en attendant, j'ai ajouté un mode "pause" à mon jeu : Une simple pression sur la touche "Entrée" interrompt le mouvement des personnages (Héros et monstres), et une seconde pression permet au jeu de reprendre son cours.

jeudi 16 septembre 2010

09 - Déplacement des Ennemis

Avant de m'occuper du déplacement des ennemis, j'ai dû régler un dernier détail ; j'ai en effet oublié de tenir compte de la possibilité que les ennemis soient générés sur la même tile que le Héros, une situation que je veux bien sûr éviter.

J'ai donc modifié mon code : Au moment de faire la liste des positions potentielles, je vérifie d'abord que chacune des positions est différente de celle du Héros ; si c'est le cas je l'ajoute à la liste, dans le cas contraire je l'ignore.

function comparePosTestHero(ar, test){
/*
cette fonction compare la position "test" avec la position du Héros ; si ces deux positions sont différentes, la position "test" est ajoutée à la liste des potentielles ("ar")
*/
if (_global.positionHeros[0] !== test[0] || _global.positionHeros[1] !== test[1]){
ar.push(test);
}
return (ar);
}

Cette fonction me servira aussi plus tard lorsque je m'occuperai de la génération des trésors...

Une fois ce détail réglé, j'ai donc pu programmer le déplacement des ennemis ; à chaque ennemi est associé une série de variables :
  • "ligne" et "colonne" permettent de déterminer la position de l'ennemi ;
  • "vitesse" représente la vitesse de déplacement de l'ennemi (16/12 pour "lent", 16/8 pour "normal", 16/6 pour "rapide") ;
  • "déplacement" représente le nombre de pixels à parcourir avant d'atteindre la position suivante (nombre entre 0 et 16) ;
  • "direction" représente la direction de déplacement (1 bas, 2 gauche, 3 haut, 4 droite) ; sa valeur initiale est fixée à -20.
À chaque frame, on vérifie la variable "déplacement" : Si elle est négative, elle augmente de 1 (cela permet donc d'immobiliser les ennemis pendant 20 frames, soit 0,8 seconde, afin que le Héros ne se fasse pas sauter dessus dès son arrivée dans l'étage) ; si elle est supérieure ou égale à 0, on vérifie les 4 tiles autour du monstre : chaque direction pointant vers une tile de type "dalle" est ajoutée à la liste des directions potentielles, sauf s'il s'agit de la direction d'où vient l'ennemi.

Exemple :
1 : Le monstre a le choix entre 3 directions : "gauche", "haut" et "droite". La direction "bas" est impossible à cause de la brique.
2 : Parmi les 3 directions possibles, c'est la direction "haut" qui a été tirée au sort ; le monstre parcourt donc 16 pixels vers le haut, puis on détermine le déplacement suivant. Seule la direction "haut" est possible (la direction "bas"est retirée de la liste des directions potentielles pour empêcher le monstre de revenir sur ses pas).
3 : Le monstre a le choix entre "gauche" et "haut" ("droite" est impossible à cause de la brique, "bas" est retiré de la liste pour empêcher le monstre de revenir sur ses pas).

Si le monstre se retrouve dans une impasse (la liste des directions potentielles est vide), alors seulement il a le droit de revenir sur ses pas.

dimanche 12 septembre 2010

08 - Tests de Collision

Maintenant que j'ai placé mes monstres, la prochaine étape devrait en toute logique consister à les faire se déplacer dans le Donjon.
Néanmoins j'ai décidé aujourd'hui de profiter de leur immobilité pour m'occuper de tout autre chose : les tests de collision.

Un test de collision, c'est ce qui permet de savoir que deux sprites de mon choix sont entrés en contact ; c'est une donnée importante, car à chaque fois que le Héros entre en contact avec un ennemi, la phase d'exploration est remplacée par une phase de combat.

Étant donné que le sprite du Héros dépasse un peu du cadre de 16 pixels de côté qui forme chaque tile, je m'attendais à avoir quelques soucis lors des tests de collision :

Sur l'image ci-dessus, on voit que la coiffure du Héros touche le monstre "Goblin" alors que les deux personnages ne sont pas sur la même tile. Comme je n'ai pas envie qu'une telle situation ne débouche sur un combat, je dois donc faire en sorte que le test de collision soit négatif (même si à l'image les deux sprites sont en contact).

Finalement la méthode à utiliser s'est avérée bien plus simple que prévue ; j'ai juste placé le code suivant dans le Clip du monstre :

onSelfEvent (enterFrame) {
if (_root.hero.isNearThis(0)) {
trace ("collision avec " add identiteClip);
}
}

"isNearThis" vérifie la collision non pas avec les sprites en entier mais seulement avec un point précis de chaque sprite (le point "central", qui est en fait situé en haut à gauche de la tile). La collision est détectée si la distance entre ces deux points est inférieure ou égale à une certaine valeur (que j'ai ici fixée à 0 pixel, mais qui aurait pu être n'importe quel autre nombre strictement inférieur à 16).

Bref tout marche comme prévu, je vais donc pouvoir m'occuper la prochaine fois du déplacement des ennemis...

samedi 11 septembre 2010

07 - Génération des Ennemis

Au moment de la génération du Donjon, un ennemi est créé dans chacune des salles qui composent l'étage.
Pour chaque ennemi créé, je dois déterminer deux choses : Sa position initiale et sa nature.

Chaque type de salle possède plusieurs positions initiales potentielles pour les ennemis ; par exemple dans une salle en forme de "9" les ennemis apparaitront soit en haut à gauche, soit au milieu, soit en bas à droite.
Pour déterminer la position initiale réelle de l'ennemi, j'utilise une méthode similaire à celle que j'ai utilisée pour créer les jonctions entre les salles (billet n° 04) : J'étudie chaque salle une à une, et à chaque fois je fais la liste de toutes les possibilités avant d'en tirer une au sort.

Chacun des 7 environnements graphiques du jeu propose son propre bestiaire ; ce dernier est constitué de 2 types de monstres : Un monstre commun (2 chance sur 3) et un monstre rare (1 chance sur 3).
Au moment de créer l'ennemi j'effectue donc un tirage au sort pour déterminer s'il s'agit d'un monstre commun ou rare, et en fonction de l'environnement graphique j'affiche le sprite adéquat ; tous ces sprites ont été regroupés dans un seul et même Clip, et chaque frame de ce Clip correspond à un type d'ennemi.

Contrairement au Héros qui possède 8 positions différentes (4 statiques et 4 déplacements), les ennemis n'en ont qu'une seule : En effet ces derniers sont toujours vus de face, quelle que soit la direction dans laquelle ils se déplacent ; comme ils sont constamment en mouvement, ils n'ont pas besoin de positions de repos.
Ce parti-pris minimaliste me permet de réduire considérablement le travail graphique (3 sprites à dessiner au lieu de 10, ou plus précisément 2 au lieu de 6 - certains sprites sont en effet de simples copiers-collers retournés par symétrie horizontale) tout en accentuant le côté rétro du jeu.


Sur la capture d'écran ci-dessus, on voit bien les 3 différentes positions initiales disponibles pour une salle en forme de "6" (en haut à gauche, au milieu, en bas à droite), ainsi que la rareté du monstre "Minotaur"(marron) par rapport au monstre "Demon Knight" (vert).

jeudi 9 septembre 2010

06 - Déplacement du Héros

Le déplacement du Héros fait intervenir 2 variables :
  • une variable de direction (_global.directionHeros) qui indique la direction du Héros (et permet d'afficher la bonne frame du Clip sprite_hero dont je vous parlais dans mon billet précédent).
  • une variable de déplacement (_global.deplacementHéros) qui indique le nombre de pixels à parcourir avant que le Héros n'ait fini son déplacement.
Quand le joueur appuie sur une touche de direction du clavier, si la variable de déplacement est nulle, alors on regarde si le Héros peut se déplacer dans cette direction ou s'il y a un obstacle qui l'en empêche. Si le Héros peut passer, alors la variable déplacement prend la valeur 16 (je rappelle que mes tiles sont des carrés de 16 pixels de côté, et que le Héros doit donc se déplacer de 16 pixels pour passer d'une tile à l'autre).

Pour les extraits de code ci-dessous, je ne vais considérer que le bouton BAS :

directionVerticale = Key.isDown(Key.DOWN) - Key.isDown(Key.UP);
//si on appuie sur BAS, directionVerticale a pour valeur 1
//si on appuie sur HAUT, directionVerticale a pour valeur -1
//si on appuie sur BAS et HAUT, directionVerticale a pour valeur 0
directionHorizontale = Key.isDown(Key.RIGHT) - Key.isDown(Key.LEFT);
// même principe pour GAUCHE et DROITE
if (directionVerticale == 1 && directionHorizontale ==0){
// Le joueur a seulement appuyé sur BAS
if (_global.deplacementHeros ==0){
// la pression sur cette touche n'a d'effet que si le Héros n'est pas déjà en train de se déplacer
_global.directionHeros = 1;
if (_global.donjon[_global.positionHeros[0]][_global.positionHeros[1]+1] ==1){
// la tile en bas du Héros est de type "dalle" : le déplacement a lieu
_global.deplacementHeros += 16;
_global.positionHeros[1]++;
}
}
}

Si la variable déplacement n'est pas nulle, alors à chaque frame de la timeline le Héros se déplace à une vitesse que j'ai fixée à 2 pixels par frame : il faut donc 8 frames pour que le Héros passe d'une tile à l'autre, ce qui correspond à 0,32 secondes (le jeu tourne à 25 frames par seconde).

if (_global.deplacementHeros > 0){
// le Héros de déplace
if (_global.directionHeros == 1){
// Le Héros se déplace vers le BAS
hero._y += _global.vitesseHeros;
_global.deplacementHeros -= _global.vitesseHeros;
}
hero.gotoAndStop(_global.elementActuel * 10 + _global.directionHeros + 4);
//on affiche l'animation "déplacement vers le bas"
} else {
// déplacement nul : le Héros reprend une position statique
hero.gotoAndStop(_global.elementActuel * 10 + _global.directionHeros);
}

Ça y est, j'ai donc un personnage entièrement contrôlable au clavier qui se déplace dans le donjon sans passer à travers les murs !
Prochaine étape : Ajouter des monstres dans le Donjon...

mardi 7 septembre 2010

05 - Le Sprite du Héros

Le Héros de Math & Magic peut être vu sous 4 angles différents : de face, de dos, et de profil (gauche et droit).

Lorsque le Héros se déplace, j'utilise un système d'animation à quatre temps (rudimentaire, mais totalement dans l'esprit rétro que je cherche à donner à mon jeu) ; si par exemple j'applique cette méthode au cas du Héros se déplaçant vers le bas cela donne :
  1. Le Héros est vu de face, dans sa position de repos ;
  2. Le Héros met un pied en avant ;
  3. Le Héros reprend sa position de repos (sprite identique à celui de l'étape 1) ;
  4. Le Héros met l'autre pied en avant.
Ces quatre étapes d'animation se répètent en boucle aussi longtemps que le personnage se déplace dans cette direction.


Quand le déplacement s'arrête, le Héros reprend sa position de repos.

Pour les déplacements vers la gauche ou vers la droite, cette animation est simplifiée : J'alterne juste entre "le Héros est dans sa position de repos" et "le Héros écarte les jambes" ; en effet, vu le manque volontaire de détail de mes sprites 8-bits, je peux tout à fait me permettre d'utiliser la même image pour l'étape 2 et pour l'étape 4.

Donc pour un seul personnage, il existe en tout huit représentations différentes que je vais associer à un numéro : quatre positions statiques (1: de face, 2: de profil regardant à gauche, 3: de dos, 4: de profil regardant à droite) et quatre mouvements de déplacement (5: vers le bas, 6: vers la gauche, 7: vers le haut , 8: vers la droite).
Chaque Héros est lui même associé à un numéro (1: Chevalier de Feu, 2: Chevalier de Glace, 3: Chevalier de Terre).

Je place toutes ces représentations dans un seul et même Clip (appelé "sprite_hero"), en utilisant la formule suivante :

Numéro de la frame = 10 x Numéro du Héros + Numéro de la représentation

Ainsi la frame 11 de mon Clip sprite_hero représente le Chevalier de Feu en position statique vu de face, tandis que la frame 36 représente le Chevalier de Terre se déplaçant vers la gauche.


Pour finir, une petite image pour illustrer ce que je racontais hier au sujet des positions initiales du Héros en fonction de la nature de la dernière salle :

Comme vous le voyez, si la salle la plus à droite a la forme d'un "2", le Héros commencera en bas à gauche de cette salle ; si elle a la forme d'un "9", il commencera plus haut et tout à droite de la salle.


Ah, et un dernier mot sur le sprite du Héros :
Pour accentuer le côté rétro, je me suis limité à une palette de 4 couleurs pour chaque sprite et j'ai opté pour une résolution plus grossière : Alors que les sprites des dalles et des briques ont une dimension de 16 pixels de côté, les sprites des personnages semblent eux mesurer à peu près 8 pixels de côté (chaque "pixel" du Héros est en réalité un groupe de 4 pixels). Je dis "à peu près", car je me suis permis quelques dépassements (ne serait-ce qu'à cause de la coiffure).