SUPER 68
I) Introduction
1) Description générale
Le héros du jeu se déplace sur un plateau en deux dimensions, en quête de clefs. Son but est de toutes les collecter, mais de nombreux obstacles entravent sa quête : hormis les murs qui lui barrent la route et les pièges qui le guettent, des fantômes passe-murailles le poursuivent! Heureusement, il a trois vies, et il peut se remettre des coups qui lui sont portés en absorbant des fioles de vie qui sont disséminées sur le plateau.
2) Description détaillée
a) Description du plateau de jeu
Les cases du plateau sont représentées en mémoire par un tableau d'octets. La valeur de chaque octet indique ce qui se trouve sur une case donnée. La matrice initiale, de 20 lignes par 80 colonnes (rangées par lignes), est donnée.
Les informations contenues dans une case (= un octet) sont organisées de la façon suivante :
b7 |
b6 |
b5 |
b4 |
b3 |
b2 |
b1 |
b0 |
M |
P |
V |
C |
B |
F |
F |
H |
Mur : indique la présence d'un mur sur cette case (si le bit est à 1),
Piège : indique la présence d'un piège
Vie : indique la présence d'une fiole de vie
Clef : indique la présence d'une clef,
Fantôme : champ réservé à la description d'un fantôme
00 : pas de fantôme dans cette case
01 : un fantôme est présent, sa prochaine action sera un déplacement
10 : un fantôme est présent, sa prochaine action sera une attente
11 : un fantôme est présent, ses deux prochaines actions seront des attentes
Héros : indique la présence du héros
Bonus : indique un bonus choisi par le concepteur
Remarque :
On ne peut pas avoir de fiole, de piège, ni de clef dans les murs. On ne peut pas non plus avoir de fiole, de piège, ou de clef confondus sur une même case.
b) Déplacement du héros
Le héros se déplace sur le plateau décrit précédemment. Il ne peut pas sauter de cases, ni traverser de mur. Il peut se déplacer uniquement dans quatre directions (haut, bas, gauche, droite), et d'une seule case par tour. Ses déplacements sont initiés par le joueur en pressant les touches du clavier par test d'état (le choix des touches à utiliser est laissé à l'appréciation des concepteurs).
c) Les clefs
La quête du héros consiste à ramasser toutes les clefs disséminées sur le plateau. Pour prendre une clef, le héros doit se trouver sur la même case que celle-ci; une fois cette clef prise, elle disparaît du monde. L'ordre dans lequel cette collecte est effectuée n'a pas d'importance. Si toutes les clefs sont ramassées, le jeu se termine par la victoire du héros.
d) La vie
Au début de la partie, le héros possède trois vies.
Il perdre des vies de deux manières :
- Premièrement, si par mégarde il marche sur un piège, il perd un point de vie.
Le piège ne disparaît pas.
- Deuxièmement, si le héros se trouve sur la même case qu'un fantôme, celui-ci l'attaque et lui fait perdre un point de vie. Les fantômes étant déjà mort, il ne peuvent être tués ni éliminés. Par conséquent, après la rencontre avec notre héros le fantôme reste présent sur sa case.
Heureusement, le héros peut regagner un point de vie en allant sur case contenant une fiole. Bien entendu, une fois bue (ce qui se fait automatiquement lorsqu'on se trouve sur la case), la fiole disparaît. Il faut cependant remarquer que le héros ne peut avoir que trois vies au plus.
Afin de rendre le nombre de vies visible pour l'utilisateur, nous utiliserons les diodes IA2 et IB2. Si le héros possède ses trois vies alors les deux diodes sont allumées, s'il en possède encore deux alors une seule diode est allumée et s'il ne lui reste plus qu'une vie alors les deux diodes sont éteintes.
e) Le temps
Le temps presse! Le héros doit récupérer toutes les clefs avant que le temps de jeu imparti ne soit écoulé. La visualisation du temps restant se fait grâce aux huit diodes : elles sont toutes allumées au début de la partie, et s'éteignent progressivement. Lorsqu'elles sont toutes éteintes, le temps est écoulé et le jeu se termine.
La gestion du temps dans le jeu est réalisée grâce aux timers, qui marquent le passage des tours de jeu. Le héros ne peut pas se déplacer plus d'une fois par tour; le plateau est mis à jour à chaque tour.
On doit avoir la possibilité de suspendre le jeu et de le reprendre à tout moment (gestion par interruption°. La pause (ou la sortie de pause) est déclenchée via le bouton poussoir IB1.
De plus, on a différents niveaux de jeu. Le niveau de jeu est lu sur les 8 interrupteurs à bascule au début de la partie. Plus le niveau est élevé, plus les tours de jeu sont rapides. Le nombre de niveaux et la façon dont ils sont codés sont laissés à l'initiative des concepteurs.
f) Les fantômes
Le héros est confronté à plusieurs fantômes qui, en plus d'être immortels essaient volontairement de le tuer!
Les fantômes se déplacent de case en case comme le héros, mais ils sont plus lents : ils ne se déplacent ou n'effectuent d'action que tous les deux tours de jeu. N'étant pas faits de chair et de sang, ils ont la possibilité de passer à travers les murs (ainsi qu'à travers tous les obstacles : pièges, fioles, clefs). Quand un fantôme traverse un mur, il est ralenti : sa prochaine action sera une attente et ne pourra se déplacer qu'à l'action suivante. Il n'est pas ralenti par les autres obstacles.
Comme nous venons de le voir, les fantômes peuvent se trouver sur la même case que notre héros; dans ce cas, ils l'attaquent et lui prennent une vie. Une fois cette attaque effectuée, les fantômes doivent se reposer et perdent donc leurs deux actions suivantes, soient 4 tours de jeu.
Les fantômes se dirigent toujours, autant que possible, vers le héros. Il est important de noter que deux fantômes ne peuvent pas se trouver sur la même case.
II) Vue d’ensemble
################################################################################
# $#
# $ # ##### # # ##### ##### ##### #### #### ############# #
# ####### # # # # @ # # # @ # # # @ # # #
# ##### # # ##### ### ##### ##### #### ## # # #
# ######### # # $ # # # # # # @ # # @ # # # # #
# # ##### #### # ##### # # #### #### # # # #
# # ####### # # #
# # #% # # # ## #
# # #### # # ##### o $ ########### #
# # # ##### # # # $ # ## #
# ######### # # ####### ######## ## # ## ## #
# ### # # # # # ######## ## % ## #
# ###### ####### # # # # ## ## #
# # # # # ######## ######### # ## #
# ++++ # # # ##### # # ## #
# +$ + # ##### #& # # ## #
# + + # $ ##### ### # # ## $ #
# # # $ + #
################################################################################
# : mur
+ : piège
% : vie
$ : clef
@ : fantôme
o : héros
& : sablier
III) Solutions retenues
- Le déplacement du héros s'effectue via les touches :
t : haut
g : bas
f : gauche
h : droite
- Le nombre de vies du héros est affiché en binaire à l'aide des deux diodes (plus logique)
00 : 0 vie
01 : 1 vie
10 : 2 vies
11 : 3 vies
- Les fantômes se déplacent vers le héros en comparant la distance les séparant sur l'axe des abscisses et des ordonnées; il se déplace en conséquence!
- Le niveau de difficulté lu sur les clefs a été implémenté comme ceci :
niveau 1 : 00000001
niveau 2 : 00000011
niveau 3 : 00000111
niveau 4 : 00001111
niveau 5 : 00011111
niveau 6 : 00111111
niveau 7 : 01111111
niveau 8 : 11111111
- Détails des niveaux de difficultés :
Niveaux |
Temps/Diode |
Temps Total |
Temps d’1 tour |
1 2 3 4 5 6 7 8 |
39 sec 36 sec 33 sec 30 sec 27 sec 24 sec 21 sec 18 sec |
5 min 12 sec 4 min 48 sec 4 min 24 sec 4 min 00 sec 3 min 36 sec 3 min 12 sec 3 min 48 sec 3 min 24 sec |
300 msec 270 msec 240 msec 210 msec 180 msec 150 msec 120 msec 090 msec |
- Ajout de couleurs dans le jeu et ce qui l'entoure.
- Ajout d'un bonus : le sablier permettant au héros de gagner du temps.
- Ajout d'un menu simple dans le jeu :
+--------------------------------------------------------------------+
| |
| Vous pouvez regler le niveau de difficulte avec les clefs. |
| niveau 1 : la clef de droite enclenchee. |
| niveau 2 : les 2 clefs de droite enclenchees. |
| etc. |
| |
| Les touches permettant de deplacer le heros sont : |
| Haut : t Gauche : f |
| Bas : g Droite : h |
| |
| Pour commencer a jouer, appuyez sur la touche espace. |
| |
+--------------------------------------------------------------------+
- Un message est affiché quand le joueur a gagné ou perdu!
"Bravo! Vous avez gagne."
"Dommage! Vous avez perdu."
"Vous n'avez plus de temps!"
ou "Vous avez perdu toutes vos vies!"
IV) Les Fichiers
mvme162_base.s : Définition générale des ressources de la carte Motorola MVME162.
ip_base.s : Définition générale des ressources liées aux cartes IP-PIA.
inicard.s : Initialisation des clefs, des diodes et des timers.
- inicard
plateau.s : Le plateau de jeu.
string.s : Gère les E/S vers l'écran.
- putChar
- LF
- CR
- getChar
- putStr
conversion.s : Gère la conversion entre entier et chaînes de caractères.
- intToStr
opdisplay.s : Fonctions utiles en rapport avec l'affichage à l'écran.
- clrDisplay
- resetCursor
- setCursor
- setColor
- showCursor
- hideCursor
draw.s : Gère l'affichage des différents éléments du plateau de jeu.
- drawEmpty
- drawGhost
- drawHero
- drawWall
- drawTrap
- drawLife
- drawKey
- drawSand
display.s : Gère l'affichage du plateau de jeu.
- lDisplay
- gDisplay
keys.s : Gère ce qui concerne les clefs.
- updateKeys
- allKeys
life.s : Gère ce qui est en rapport avec les vies.
- updateLife
- updateTrap
- allLives
times.s : Gestion du temps.
- delTime
- cyclTime
- hourglass
- IT_Game
- IT_Cycle
button.s : Gestion des boutons.
- BN_Quit
- BN_Break
heromove.s : Gère le déplacement du héros.
- moveHero
- mvUp
- mvDown
- mvRight
- mvLeft
ghost.s : Gère le déplacement des fantômes.
- gGhost
- lGhost
- ghostHero
main.s : Le programme principal.
IV) Les Fonctions
1) inicard.s
a) inicard
But : Initialiser les deux timers, les diodes, les boutons et les clefs.
E/S : rien
Algo : Remettre à zéro les deux compteurs,
définir les modes des compteurs,
mettre à jour la table des interruptions,
mettre les diodes en sortie,
mettre les clefs en entrée, initialiser les boutons.
Utilisation :
bsr inicard
|
-4 +--------+
| @ |
0 +--------+ pile |
2) string.s
a) putChar
But : Afficher un caractère à l'écran.
E/S : Un caractère en entrée.
Algo : Récupérer le caractère,
tester si le tampon est libre,
mettre le caractère dans le buffer pour l'écrire.
Utilisation :
move.b #'A',-(A7)
bsr putChar
add.l #2,A7 |
-10 +--------+
| D0 |
-6 +--------+ | @ | -2 +--------+ | e | <- caractère 0 +--------+ pile |
b) LF
But : Remplir la ligne courante de caractères espace ' '. (line feed)
E/S : Rien
Algo : Tester si le tampon est libre,
mettre dans le buffer le caractère "line feed" pour écriture.
Utilisation :
bsr LF |
-4 +--------+ | @ |
0 +--------+
pile |
c) CR
But : Aller au début de la ligne suivante. (carriage return)
E/S : Rien
Algo : Tester si le tampon est libre,
mettre dans le buffer le caractère "carriage return" pour écriture.
Utilisation :
bsr CR |
-4 +--------+
| @ | 0 +--------+ pile |
d) getChar
But : Récupérer un caractère tapé au clavier par l'utilisateur.
E/S : Le caractère lu en sortie.
Algo : Tester si un caractère a été reçu,
mettre le caractère dans la pile.
Utilisation :
suba.l #2,A7
bsr getChar
move.b (A7)+,D0 |
-6 +--------+ | @ | -2 +--------+
| s | <- caractère
+--------+
pile |
e) putStr
But : Afficher une chaîne de caractère à l'écran.
E/S : une chaîne de caractère en entrée(@).
Algo : Récupérer l'adresse de la chaîne de caractère,
tester si le caractère courant est le caractère de fin de chaîne,
empiler la valeur se trouvant à l'adresse courante,
incrémenter l'adresse (caractère suivant),
appeler la fonction putChar,
recommencer jusqu'au caractère de fin de chaîne.
Utilisation :
lea chaine,A0 move.l A0,-(A7) bsr putStr add.l #4,A7 |
-12 +--------+ | A0 | -8 +--------+ | @ | -4 +--------+ | e | <- adresse chaîne 0 +--------+ pile |
3) conversion.s
a) intToStr
But : Convertir un nombre entier en chaîne de caractère.
E/S : un nombre en entrée.
Algo : Adressage auto-incrémenté dans 'number',
récupérer le nombre (quotient),
qui est dans la pile, empiler le caractère de fin de chaîne,
diviser le quotient par 10 et récupérer le reste,
convertir le reste en code ASCII,
mettre le reste dans la pile,
vérifier si le quotient est différent de zéro,
alors recommencer,
sinon récupérer les différents chiffre du nombre dans la pile et,
les mettre dans 'number' jusqu'au caractère de fin de chaîne.
Utilisation :
move.l D0,-(A7) bsr intToStr add.l #4,A7 lea number,A0 |
-20 +--------+ | A0 | -16 +--------+ | D1 | -12 +--------+ | D0 | -8 +--------+ | @ | -4 +--------+ | e | <- nombre 0 +--------+ pile |
4) opdisplay.s
a) clrDisplay
But : Effacer l'écran.
E/S : Rien
Algo : empiler 'ESC', appeler la fonction putChar, dépiler,
empiler '[', appeler la fonction putChar, dépiler,
empiler '2', appeler la fonction putChar, dépiler,
empiler 'J', appeler la fonction putChar, dépiler.
Utilisation :
bsr clrDisplay |
-4 +--------+ | @ | 0 +--------+ pile |
b) resetCursor
But : Repositionner le curseur en haut à gauche de l'écran.
E/S : Rien
Algo : empiler 'ESC', appeler la fonction putChar, dépiler,
empiler '[', appeler la fonction putChar, dépiler,
empiler 'H', appeler la fonction putChar, dépiler.
Utilisation :
bsr resetCursor |
-4 +--------+ | @ | 0 +--------+ pile |
c) setCursor
But : Positionner le curseur à une certaine coordonnée à l'écran.
E/S : le numéro de colonne et le numéro de ligne en entrée.
Algo : empiler 'ESC', appeler la fonction putChar, dépiler,
empiler '[', appeler la fonction putChar, dépiler,
récupérer le numéro de ligne,
appeler la fonction intToStr, dépiler,
empiler la chaîne de caractère (number),
appeler la fonction putStr, dépiler,
empiler ';', appeler la fonction putChar, dépiler,
récupérer le numéro de colonne,
appeler la fonction intToStr, dépiler,
empiler la chaîne de caractère (number),
appeler la fonction putStr, dépiler,
empiler 'H', appeler la fonction putChar, dépiler.
Utilisation :
move.l #36,-(A7) move.l #7,-(A7) bsr setCursor add.l #8,A7 |
-16 +--------+ | A0 | -12 +--------+ | @ | -8 +--------+
| e | <- no ligne -4 +--------+ | e | <- no colonne 0 +--------+ pile |
d) setColor
But : Changer la couleur de fond et de texte courante.
E/S : le numéro de la couleur de texte et de fond en entrée.
Algo : empiler 'ESC', appeler la fonction putChar, dépiler,
empiler '[', appeler la fonction putChar, dépiler,
récupérer le code de la couleur de texte,
appeler la fonction intToStr, dépiler,
empiler la chaîne de caractère (number),
appeler la fonction putStr, dépiler,
empiler ';', appeler la fonction putChar, dépiler,
récupérer le code la couleur de fond,
appeler la fonction intToStr, dépiler,
empiler la chaîne de caractère (number),
appeler la fonction putStr, dépiler,
empiler 'm', appeler la fonction putChar, dépiler.
Utilisation :
move.l #34,-(A7) move.l #47,-(A7) bsr setColor add.l #8,A7 |
-16 +--------+ | A0 | -12 +--------+ | @ | -8 +--------+ | e | <- code texte -4 +--------+ | e | <- code fond 0 +--------+ pile |
e) showCursor
But : Afficher le curseur à l'écran.
E/S : Rien
Algo : empiler 'ESC', appeler la fonction putChar, dépiler,
empiler '[', appeler la fonction putChar, dépiler,
empiler '?', appeler la fonction putChar, dépiler,
empiler '2', appeler la fonction putChar, dépiler,
empiler '5', appeler la fonction putChar, dépiler,
empiler 'h', appeler la fonction putChar, dépiler.
Utilisation :
bsr showCursor |
-4 +--------+ | @ | 0 +--------+ pile |
f)hideCursor
But : Masquer le curseur de l'écran.
E/S : Rien
Algo : empiler 'ESC', appeler la fonction putChar, dépiler,
empiler '[', appeler la fonction putChar, dépiler,
empiler '?', appeler la fonction putChar, dépiler,
empiler '2', appeler la fonction putChar, dépiler,
empiler '5', appeler la fonction putChar, dépiler,
empiler 'l', appeler la fonction putChar, dépiler.
Utilisation :
bsr hideCursor |
-4 +--------+ | @ | 0 +--------+ pile |
5) draw.s
a) drawEmpty
But : Afficher une case vide à l'écran.
E/S : Rien.
Algo : Changer les couleurs courantes (texte & fond) en appelant la fonction setColor.
Afficher le caractère correspondant : ' ' en appelant la fonction putChar.
Utilisation :
bsr drawEmpty |
-4 +--------+ | @ | 0 +--------+ pile |
b) drawGhost
But : Afficher un fantôme à l'écran.
E/S : Rien.
Algo : Changer les couleurs courantes (texte & fond) en appelant la fonction setColor.
Afficher le caractère correspondant : '@' en appelant la fonction putChar.
Utilisation :
bsr drawGhost |
-4 +--------+ | @ | 0 +--------+ pile |
c) drawHero
But : Afficher le héros à l'écran.
E/S : Rien.
Algo : Changer les couleurs courantes (texte & fond) en appelant la fonction setColor.
Afficher le caractère correspondant : 'o' en appelant la fonction putChar.
Utilisation :
bsr drawHero |
-4 +--------+ | @ | 0 +--------+ pile |
d) drawWall
But : Afficher un mur à l'écran.
E/S : Rien.
Algo : Changer les couleurs courantes (texte & fond) en appelant la fonction setColor.
Afficher le caractère correspondant : '#' en appelant la fonction putChar.
Utilisation :
bsr drawWall |
-4 +--------+ | @ | 0 +--------+ pile |
e) drawTrap
But : Afficher un piège à l'écran.
E/S : Rien.
Algo : Changer les couleurs courantes (texte & fond) en appelant la fonction setColor.
Afficher le caractère correspondant : '+' en appelant la fonction putChar.
Utilisation :
bsr drawTrap |
-4 +--------+ | @ | 0 +--------+ pile |
f) drawLife
But : Afficher une fiole de vie à l'écran.
E/S : Rien.
Algo : Changer les couleurs courantes (texte & fond) en appelant la fonction setColor.
Afficher le caractère correspondant : '%' en appelant la fonction putChar.
Utilisation :
bsr drawLife |
-4 +--------+ | @ | 0 +--------+ pile |
g) drawKey
But : Afficher une clef à l'écran.
E/S : Rien.
Algo : Changer les couleurs courantes (texte & fond) en appelant la fonction setColor.
Afficher le caractère correspondant : '$' en appelant la fonction putChar.
Utilisation :
bsr drawEmpty |
-4 +--------+ | @ | 0 +--------+ pile |
h) drawSand
But : Afficher un sablier à l'écran.
E/S : Rien.
Algo : Changer les couleurs courantes (texte & fond) en appelant la fonction setColor.
Afficher le caractère correspondant : '&' en appelant la fonction putChar.
Utilisation :
bsr drawSand |
-4 +--------+ | @ | 0 +--------+ pile |
6) display.s
a) lDisplay
But : Afficher une case du plateau de jeu à l'écran.
E/S : La valeur d'une case du jeu en entrée.
Algo : Récupérer la valeur de la case qui se trouve dans la pile,
comparer cette case pour savoir si c'est une case vide, un fantôme, le héros,
un mur, un piège, une fiole de vie, une clef ou un sablier et,
appeler la fonction correspondante à la valeur de la case (drawEmpty, drawGhost,
drawHero, drawWall, drawTrap, drawLife, drawKey, drawSand)
Utilisation :
move.b (A0)+,-(A7) bsr lDisplay add.l #2,A7 |
-10 +--------+ | D0 | -6 +--------+ | @ | -2 +--------+ | e | <- case du jeu 0 +--------+ pile |
b) gDisplay
But : Afficher le plateau de jeu en entier à l'écran.
E/S : l'adresse du plateau de jeu.
Algo : Récupérer l'adresse du plateau de jeu de la pile,
pour la ligne 0 à 19 faire,
pour la colonne 0 à 79 faire,
empiler la valeur de l'@ courante,
incrémenter l'@ courante (case suivante),
appeler la fonction lDisplay,
dépiler,
incrémenter le nombre de colonnes,
fin pour,
mettre à zéro le nombre de colonnes et,
incrémenter le nombre de lignes,
appeler les fonctions LF et CR,
fin pour.
Utilisation :
lea PLATEAU,A0 move.l A0,-(A7) bsr gDisplay add.l #4,A7 |
-20 +--------+ | A0 | -16 +--------+ | D1 | -12 +--------+ | D0 | -8 +--------+ | @ | -4 +--------+ | e | <- @ plateau jeu 0 +--------+ pile |
7) key.s
a) updateKeys
But : Mettre à jour le nombre de clefs.
E/S : @ courante du plateau et données du héros en entrée.
Algo : Récupérer l'@ du plateau et des données du héros,
vérifier si dans la case courante il y a une clef,
enlever la clef du plateau de jeu,
incrémenter le nombre de clefs du héros.
Utilisation :
move.l A1,-(A7) move.l A0,-(A7) bsr updateKeys add.l #8,A7 |
-20 +--------+ | A1 | -16 +--------+ | A0 | -12 +--------+ | @ | -8 +--------+ | e | <- @ plateau jeu | e | <- @ data héros 0 +--------+ pile |
b) allKeys
But : Vérifier si lé héros a récupéré toutes les clefs.
E/S : booléen en sortie, adresse des données du héros et nombre de clefs total
du plateau de jeu en entrée.
Algo : Récupérer le nombre de clefs totatimes.sl,
récupérer l'@ des données du héros,
mettre la valeur du booléen en sortie à zéro,
si nombre de clefs du héros est égal au nombre de clefs total alors,
mettre la valeur du booléen en sortie à un.
Utilisation :
suba.l #2,A7 move.l A1,-(A7) move.b #nbkeys,-(A7) bsr allKeys add.l #6,A7 move.b (A7)+,D1 |
-20 +--------+ | A1 | -16 +--------+ | D0 | -12 +--------+ | @ | -8 +--------+ | e | <- nb total clefs -6 +--------+ | e | <- @ data héros -2 +--------+ | s | <- booléen (res) 0 +--------+ pile |
8) life.s
a) updateLife
But : Mettre à jour le nombre de fioles de vies.
E/S : @ courante du plateau et données du héros en entrée.
Algo : Récupérer l'@ du plateau et des données du héros,
vérifier si dans la case courante il y a une fiole de vie,
vérifie si le héros a moins de 3 vies,
enlever la fiole de vie du plateau de jeu,
incrémenter le nombre de vies du héros.
Utilisation :
move.l A1,-(A7) move.l A0,-(A7) bsr updateLife add.l #8,A7 |
-20 +--------+ | A1 | -16 +--------+ | A0 | -12 +--------+ | @ | -8 +--------+ | e | <- @ plateau jeu -4 +--------+ | e | <- @ data héros 0 +--------+ pile |
b) updateTrap
But : Mettre à jour le nombre de pièges.
E/S : @ courante du plateau et données du héros en entrée.
Algo : Récupérer l'@ du plateau et des données du héros,
vérifier si dans la case courante il y a une fiole de vie,
décrémenter le nombre de vies du héros.
Utilisation :
move.l A1,-(A7) move.l A0,-(A7) bsr updateTrap add.l #8,A7 |
-20 +--------+ | A1 | -16 +--------+ | A0 | -12 +--------+ | @ | -8 +--------+ | e | <- @ plateau jeu -4 +--------+ | e | <- @ data héros 0 +--------+ pile |
c) allLives
But : Vérifier si lé héros a au moins une vie et met à jour les diodes.
E/S : booléen en sortie, adresse des données du héros en entrée.
Algo : Récupérer l'@ des données du héros,
mettre la valeur du booléen en sortie à zéro,
éteindre les deux diodes,
vérifier si lé héros a trois vies,
allumer les deux diodes,
mettre le booléen à un,
vérifier si le héros a deux vies,
allumer que la diode de gauche,
mettre le booléen à un,
vérifier si le héros a une vie,
allumer que la diode de droite,
mettre le booléen à un.
Utilisation :
suba.l #2,A7 move.l A1,-(A7) bsr allLives add.l #4,A7 move.b (A7)+,D1 |
-22 +--------+ | A1 | -18 +--------+ | D1 | -14 +--------+ | D0 | -10 +--------+ | @ | -6 +--------+ | e | <- @ data héros -2 +--------+ | s | <- booléen (res) 0 +--------+ pile |
9) times.s
a) delTime
But : Calculer le temps total/diode de la partie à partir du niveau de difficulté choisi par l'utilisateur.
E/S : @ du tableau des valeurs du temps total / diode en entrée.
Algo : Récupérer l'@ du tableau des valeurs du temps total,
comparer la valeur des clefs (niveau de difficulté choisi),
récupérer la valeur correspondante au niveau de difficulté dans le
tableau des valeurs du temps total,
calculer la valeur en microsec du temps/diode,
initialise la valeur du compteur à atteindre.
Utilisation :
lea tottime,A2 move.l A2,-(A7) bsr delTime add.l #4,A7 |
-20 +--------+ | A2 | -16 +--------+ | D1 | -12 +--------+ | D0 | -8 +--------+ | @ | -4 +--------+ | e | <- @ tottime 0 +--------+ pile |
b) cyclTime
But : Calculer le temps d'un tour de jeu à partir du niveau de difficulté choisi par l'utilisateur.
E/S : @ du tableau des valeurs du temps d'un cycle de jeu en entrée.
Algo : Récupérer l'@ du tableau des valeurs du temps d'un cycle de jeu,
comparer la valeur des clefs (niveau de difficulté choisi),
récupérer la valeur correspondante au niveau de difficulté dans le
tableau des valeurs du temps d'un cycle de jeu,
calculer la valeur en microsec d'un tour de jeu,
initialise la valeur du compteur à atteindre.
Utilisation :
lea trtime,A2 move.l A2,-(A7) bsr cyclTime add.l #4,A7 |
-20 +--------+ | A2 | -16 +--------+ | D1 | -12 +--------+ | D0 | -8 +--------+ | @ | -4 +--------+ | e | <- @ trtime 0 +--------+ pile |
c) hourglass
But : Mettre à jour le nombre de sabliers.
E/S : @ courante du plateau et données du héros en entrée.
Algo : Récupérer l'@ du plateau,
vérifier si dans la case courante il y a un sablier,
enlever le sablier du plateau de jeu,
récupérer le temps qu'il reste,
ajouter le temps correspondant (une diode),
mettre à jour l'affichage des diodes,
décrémenter le nombre de vies du héros.
Utilisation :
move.l A0,-(A7) bsr hourglass add.l #4,A7 |
-20 +--------+ | A0 | -16 +--------+ | D0 | -12 +--------+ | @ | -8 +--------+ | e | <- @ plateau jeu 0 +--------+ pile |
d) IT_Game
But : Gérer le temps total d'une partie.
E/S : Rien
Algo : Récupèrer le temps qu'il reste,
éteindre une diode,
remettre le compteur à zéro.
Utilisation :
interruption |
-8 +--------+ | D0 | -4 +--------+ | @ | 0 +--------+ Pile |
e) IT_Cycle
But : Gèrer le temps d'un cycle de jeu.
E/S : Rien
Algo : - Récupérer le caractère saisi par l'utilisateur,
empiler l'adresse du plateau,
empiler l'adresse de herodata,
appeler moveHero,
dépiler,
- empiler l'adresse du plateau,
empiler l'adresse de herodata,
empiler l'adresse de dataghost,
appeler moveHero,
dépiler,
- réserver un octet,
empiler l'adresse de hérodata,
empiler le nombre de clefs total,
appeler allKeys,
dépiler,
si le héro a toutes les clefs,
effacer l'écran et afficher le message gagné à l'écran,
- empiler l'adresse de hérodata,
empiler l'adresse de dataghost,
appeler ghostHero,
dépiler,
- réserver un octet,
empiler l'adresse de hérodata,
appeler allLives,
dépiler,
si le nombre de vies est égal à zéro,
effacer l'écran et afficher le message perdu à l'écran,
- si toutes les diodes sont éteintes,
effacer l'écran et afficher le message perdu à l'écran,
- remettre le compteur à zéro.
Utilisation :
interruption |
-4 +--------+ | @ | 0 +--------+ Pile |
10) buttons.s
a) BN_Quit
But : Quitter le jeu.
E/S : Rien
Algo : Quitter la boucle infinie en mettant à un D0.
Utilisation :
interruption |
-4 +--------+ | @ | 0 +--------+ Pile |
b) BN_Break
But : Mettre le jeu en pause.
E/S : Rien
Algo : vérifier si D0 est égal à 0 alors,
arrêter les timers,
mettre la valeur 2 dans D0,
sinon vérifier si D0 est égal à 2 alors,
tester si utilisateur a appuyé sur le bouton alors,
relancer les timers,
mettre la valeur 0 dans D0,
sinon boucler.
Utilisation :
interruption |
-4 +--------+ | @ | 0 +--------+ Pile |
11) heromove.s
a) moveHero
But : Déplacer le héros.
E/S : Touche que l'utilisateur a tapée au clavier, adresse du plateau de jeu et des données du héros en
entrée.
Algo : Récupérer l'adresse du plateau de jeu,
récupérer l'adresse des données du héros,
récupérer le caractère tapé par l'utilisateur,
vérifier si l'utilisateur a appuyé sur une touche de direction,
dans ce cas appeler la fonction correspondante :
empiler plateau & herodata,
mvLeft | mvRight | mvUp | mvDown,
dépiler.
Utilisation :
move.b SUCC_BUF,-(A7) move.l A0,-(A7) bsr moveHero add.l #10,A7 |
-26 +--------+ | A1 | -22 +--------+ | A0 | -18 +--------+ | D0 | -14 +--------+ | @ | -10 +--------+ | A1 | -6 +--------+ | A0 | -2 +--------+ | e | <- caractère 0 +--------+ Pile |
b) mvUp
But : Déplacer le héros vers le haut.
E/S : L'adresse du plateau de jeu et les données du héros en entrée.
Algo : Récupérer l'adresse du héros,
récupérer l'adresse des données du héros,
mettre dans des registres les coordonnées du héros,
aller à la case au-dessus du héros (y-1)*80+x-correction[cf VI],
tester si la case est un mur,
dans ce cas ne pas avancer,
sinon empiler @ plateau & herodata et,
appeler les fonctions de mise à jour de clefs, pièges, vies et sabliers,
(updateKeys, updateTrap, updateLife, hourglass)
mettre à jour la valeur de l'adresse du plateau courante,
positionner le curseur à cette nouvelle case (setCursor),
actualiser la case courante (lDisplay),
mettre à jour les données du héros (heroy),
aller à l'adresse de la case de dessous,
effacer le héros dans la valeur de cette adresse,
positionner le curseur à cette nouvelle case (setCursor),
actualiser la case courante (lDisplay),
Utilisation :
move.l A0,-(A7) move.l A1,-(A7) bsr mvUp add.l #8,A7 |
-32 +--------+ | A1 | -28 +--------+ | A0 | -24 +--------+ | D2 | -20 +--------+ | D1 | -16 +--------+ | D0 | -12 +--------+ | @ | -8 +--------+ | e | <- @ data héros -4 +--------+ | e | <- @ plateau jeu 0 +--------+ Pile |
c) mvDown
But : Déplacer le héros vers le bas.
E/S : L'adresse du plateau de jeu et les données du héros en entrée.
Algo : Récupérer l'adresse du héros,
récupérer l'adresse des données du héros,
mettre dans des registres les coordonnées du héros,
aller à la case au-dessous du héros (y+1)*80+x-correction[cf VI],
tester si la case est un mur,
dans ce cas ne pas avancer,
sinon empiler @ plateau & herodata et,
appeler les fonctions de mise à jour de clefs, pièges, vies et sabliers,
(updateKeys, updateTrap, updateLife, hourglass)
mettre à jour la valeur de l'adresse du plateau courante,
positionner le curseur à cette nouvelle case (setCursor),
actualiser la case courante (lDisplay),
mettre à jour les données du héros (heroy),
aller à l'adresse de la case de dessus,
effacer le héros dans la valeur de cette adresse,
positionner le curseur à cette nouvelle case (setCursor),
actualiser la case courante (lDisplay),
Utilisation :
move.l A0,-(A7) move.l A1,-(A7) bsr mvDown add.l #8,A7 |
-32 +--------+ | A1 | -28 +--------+ | A0 | -24 +--------+ | D2 | -20 +--------+ | D1 | -16 +--------+ | D0 | -12 +--------+ | @ | -8 +--------+ | e | <- @ data héros -4 +--------+ | e | <- @ plateau jeu 0 +--------+ Pile |
d) mvLeft
But : Déplacer le héros vers la gauche.
E/S : L'adresse du plateau de jeu et les données du héros en entrée.
Algo : Récupérer l'adresse du héros,
récupérer l'adresse des données du héros,
mettre dans des registres les coordonnées du héros,
aller à la case de gauche du héros y*80+(x-1)-correction[cf VI],
tester si la case est un mur,
dans ce cas ne pas avancer,
sinon empiler @ plateau & herodata et,
appeler les fonctions de mise à jour de clefs, pièges, vies et sabliers,
(updateKeys, updateTrap, updateLife, hourglass)
mettre à jour la valeur de l'adresse du plateau courante,
positionner le curseur à cette nouvelle case (setCursor),
actualiser la case courante (lDisplay),
mettre à jour les données du héros (herox),
aller à l'adresse de la case de droite,
effacer le héros dans la valeur de cette adresse,
positionner le curseur à cette nouvelle case (setCursor),
actualiser la case courante (lDisplay),
Utilisation :
move.l A0,-(A7) move.l A1,-(A7) bsr mvLeft add.l #8,A7 |
-32 +--------+ | A1 | -28 +--------+ | A0 | -24 +--------+ | D2 | -20 +--------+ | D1 | -16 +--------+ | D0 | -12 +--------+ | @ | -8 +--------+ | e | <- @ data héros -4 +--------+ | e | <- @ plateau jeu 0 +--------+ Pile |
e) mvRight
But : Déplacer le héros vers la droite.
E/S : L'adresse du plateau de jeu et les données du héros en entrée.
Algo : Récupérer l'adresse du héros,
récupérer l'adresse des données du héros,
mettre dans des registres les coordonnées du héros,
aller à la case de droite du héros y*80+(x+1)-correction[cf VI],
tester si la case est un mur,
dans ce cas ne pas avancer,
sinon empiler @ plateau & herodata et,
appeler les fonctions de mise à jour de clefs, pièges, vies et sabliers,
(updateKeys, updateTrap, updateLife, hourglass)
mettre à jour la valeur de l'adresse du plateau courante,
positionner le curseur à cette nouvelle case (setCursor),
actualiser la case courante (lDisplay),
mettre à jour les données du héros (herox),
aller à l'adresse de la case de gauche,
effacer le héros dans la valeur de cette adresse,
positionner le curseur à cette nouvelle case (setCursor),
actualiser la case courante (lDisplay),
Utilisation :
move.l A0,-(A7) move.l A1,-(A7) bsr mvRight add.l #8,A7 |
-32 +--------+ | A1 | -28 +--------+ | A0 | -24 +--------+ | D2 | -20 +--------+ | D1 | -16 +--------+ | D0 | -12 +--------+ | @ | -8 +--------+ | e | <- @ data héros -4 +--------+ | e | <- @ plateau jeu 0 +--------+ Pile |
12) ghost.s
a) gGhost
But : Déplacer les 5 fantômes.
E/S : Adresse du plateau de jeu, des données du héros, des données des fantômes
en entrée.
Algo : Récupérer l'adresse du plateau de jeu dans la pile,
récupérer l'adresse des données du héros dans la pile,
récupérer l'adresse des données des fantômes dans la pile,
Pour numéro fantôme de 0 à 4 faire,
empiler l'adresse du plateau de jeu,
empiler l'adresse des données du héros,
empiler la valeur de l'adresse courante (ghosty) de dataghost,
incrémenter l'adresse des données des fantômes,
empiler la valeur de l'adresse courante (ghostx) de dataghost,
incrémenter l'adresse des données des fantômes,
appeler la fonction local ghost (lGhost),
dépiler & mettre à jour les données des fantômes à partir de la pile,
incrémenter le nombre numéro fantôme
Fin pour.
Utilisation :
move.l A0,-(A7) move.l A1,-(A7) move.l A2,-(A7) bsr gGhost add.l #12,A7 |
-32 +--------+ | A2 | -28 +--------+ | A1 | -24 +--------+ | A0 | -20 +--------+ | D0 | -16 +--------+ | @ | -12 +--------+ | e | <- @ data ghost -8 +--------+ | e | <- @ data héros -4 +--------+ | e | <- @ plateau jeu 0 +--------+ Pile |
b) lGhost
But : Déplacer un seul fantôme.
E/S : Adresse du plateau de jeu et des données du héros en entrée,
ordonnée et abscisse d'un fantôme en entrée et sortie.
Algo simplifié :
Vérifier ce que doit faire le fantôme ce tour ci : attendre ou avancer,
calculer la distance sur l'axe des x entre le fantôme et le héros,
calculer la distance sur l'axe des y entre le fantôme et le héros,
comparer ces deux distances,
déplacer le fantôme suivant l'axe où la distance est la plus grande,
déterminer si le fantôme va à droite, à gauche, en haut ou en bas,
tester si un autre fantôme se trouve déjà sur cette future case,
si c'est le cas essayer de déplacer le fantôme sur l'autre axe,
tester si la future case est un mur,
dans ce cas, le fantôme perd deux tours au lieu de un seul,
tester si dans la future case il y a le héros,
dans ce cas, le fantôme perd deux tours au lieu de un seul,
sinon le fantôme perd un seul tour,
mettre à jour la valeur de l'adresse du plateau de la case future,
positionner le curseur sur cette nouvelle case (setCursor),
actualiser cette case (lDisplay),
mettre à jour la valeur de l'adresse du plateau de l'ancienne case,
positionner le curseur sur cette ancienne case (setCursor),
actualiser cette case (lDisplay),
mettre dans la pile (sortie) les coordonnées du fantôme.
Utilisation :
move.l A0,-(A7) move.l A1,-(A7) move.b (A2)+,-(A7) move.b (A2)+,-(A7) bsr lGhost sub.l #1,A2 move.b (A7)+,(A2) sub.l #1,A2 move.b (A7)+,(A2) add.l #8,A7 |
-48 +--------+ | A1 | -44 +--------+ | A0 | -40 +--------+ | D5 | -36 +--------+ | D4 | -32 +--------+ | D3 | -28 +--------+ | D2 | -24 +--------+ | D1 | -20 +--------+ | D0 | -16 +--------+ | @ | -12 +--------+ | e | <- @ plateau jeu -8 +--------+ | e | <- @ data héros -4 +--------+ | e/s | <- Ghost y -2 +--------+ | e/s | <- Ghost x 0 +--------+ Pile |
c) ghostHero
But : Vérifier si un fantôme et le héros sont sur la même case.
E/S : Adresse des données du héros et des données des fantômes en entrée.
Algo : Récupérer l'adresse des données du héros dans la pile,
récupérer l'adresse des données des fantômes dans la pile,
Vérifier si le héros a au moins une vie,
Pour numéro fantôme de 0 à 4 faire,
Comparer l'ordonnée du héros et du fantôme,
Comparer l'abscisse du héros et du fantôme,
Enlever une vie au héros,
Fin pour.
Utilisation :
move.l A1,-(A7) move.l A2,-(A7) bsr ghostHero add.l #8,A7 |
-24 +--------+ | A2 | -20 +--------+ | A1 | -16 +--------+ | D0 | -12 +--------+ | @ | -8 +--------+ | e | <- @ data ghost -4 +--------+ | e | <- @ data héros 0 +--------+ Pile |
13) main.s
But : Gérer le "programme".
- inclure les fichiers ip_base.s et mvme162_base.s,
- masquer les interruptions,
initialiser les timers, boutons, clefs et diodes,
permettre les interruptions,
- afficher le menu du jeu,
attendre que l'utilisateur appuie sur la touche espace,
- effacer l'écran,
cacher le curseur,
charger le plateau de jeu,
charger les données du héros,
afficher le plateau de jeu,
- initialiser le temps total de la partie,
initialiser le temps d'un tour de jeu,
- charger les données des fantômes,
allumer toutes les diodes,
démarrer les timers,
- renter dans la boucle infini,
- instructions de fin de programme,
- inclure les fichiers, string.s, conversion.s, inicard.s, button.s, plateau.s,
opdisplay.s, draw.s, display.s, key.s, heromove.s, times.s, life.s, menu.s,
ghost.s,
- variables de conversions,
- variables relatives au héros,
- variables de directions pour le héros,
- variables de couleurs du texte,
- variables de couleurs de fond,
- variables relatives au temps,
- variables relatives aux fantômes.
VI) Problèmes rencontrés
- Synchronisation entre plateau dont la première case est à la coordonnée (0,0) et le curseur dont la première case est à la coordonnée (1,1)
- Les fantômes : pas de problème réel, leur déplacement étant basé sur le même système que le héros.
VII) Améliorations possibles
- Accélérer l'affichage du plateau en comparant la case précédente pour éviter de changer les couleurs si c'est le même élément que l'on veut afficher. (Ceci implique des changement dans la fonction gDisplay et dans les fonctions draw qui doivent avoir en plus un booléen en entrée pour savoir si on doit changer de couleur)
- Ajouter un système de menu (Jouer, Option, Quitter). Option peut comprendre la règle du jeu, les touches pour jouer, le nombre de vies, le plateau de jeu, le nombre de fantômes présents, ...
- D'autres plateaux de jeu ce qui impliquent l'ajout des fonctions tels que la recherche des coordonnées du héros dans jeu ainsi que celles des fantômes.
- Pour pouvoir recommencer une partie il faudrait garder en mémoire avant de commencer à jouer les coordonnées du héros, des fantômes, des clefs, des vies et des sabliers présents sur le plateau de jeu.
- L'affichage en bas de l'écran (les 4 lignes qui restent) des touches du jeu, du nombre de vies du héros, du nombre de clefs ramassées, du temps exact qui lui reste.
- Gestion du score qui est plutôt difficile parce qu'il faut être juste par exemple par rapport au temps qu'il a mis pour ramasser toutes les clefs en fonction du niveau de difficulté choisi!
ESTIENNE Sébastien
2004