Obligement - L'Amiga au maximum

Vendredi 23 mai 2025 - 16:24  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

Actualité (récente)
Actualité (archive)
Comparatifs
Dossiers
Entrevues
Matériel (tests)
Matériel (bidouilles)
Points de vue
En pratique
Programmation
Reportages
Quizz
Tests de jeux
Tests de logiciels
Tests de compilations
Trucs et astuces
Articles divers

Articles in English


Réseaux sociaux

Suivez-nous sur X




Liste des jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z,
ALL


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Galeries

Menu des galeries

BD d'Amiga Spécial
Caricatures Dudai
Caricatures Jet d'ail
Diagrammes de Jay Miner
Images insolites
Fin de jeux (de A à E)
Fin de Jeux (de F à O)
Fin de jeux (de P à Z)
Galerie de Mike Dafunk
Logos d'Obligement
Pubs pour matériels
Systèmes d'exploitation
Trombinoscope Alchimie 7
Vidéos


Téléchargement

Documents
Jeux
Logiciels
Magazines
Divers


Liens

Associations
Jeux
Logiciels
Matériel
Magazines et médias
Pages personnelles
Réparateurs
Revendeurs
Scène démo
Sites de téléchargement
Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec


A Propos

A propos d'Obligement

A Propos


Contact

David Brunet

Courriel

 


Dossier : Les défilements sur Amiga
(Article écrit par Andrew Braybrook et extrait de uridiumauthor.blogspot.com - décembre 2017)


Introduction

Selon les possibilités de votre matériel informatique, il existe plusieurs façons d'afficher un jeu à défilement. Auparavant, nous devions évaluer chaque machine pour laquelle nous écrivions, puis concevoir nos jeux en fonction de ses avantages. Tout cela ne fonctionne plus, bien sûr, lorsqu'il s'agit de convertir un jeu d'une machine à l'autre.

Les éléments à prendre en compte sont les suivants :
  1. Avons-nous des modes caractères définissables par l'utilisateur ?
  2. Avons-nous des modes bitmap ?
  3. Disposons-nous d'un défilement fluide dans le matériel ?
  4. Avons-nous plus d'un plan ?
  5. Disposons-nous de sprites matériels ?
  6. Avons-nous suffisamment de temps processeur pour reconstruire tout ce qui se trouve à l'écran tous les cinquantièmes de seconde ?
  7. Peut-on démarrer la mémoire de l'écran à n'importe quelle adresse de la mémoire vidéo ?
  8. Peut-on redémarrer l'affichage de l'écran à partir d'une autre adresse pendant l'affichage ?
L'apprentissage en 8 bits

Chez Graftgold, comme nous avons commencé avec des machines 8 bits et que nous n'avions que les jeux d'arcade comme exemple d'un monde meilleur, tout le monde a suivi le même processus d'apprentissage. Pour arriver à l'Amiga, nous avons d'abord dû passer par un certain nombre d'autres machines.

Voici les réponses aux questions ci-dessus pour chacun de ces ordinateurs :

Dragon 32
  1. Non, les jeux de caractères sont fixés dans la mémoire morte.
  2. Oui : deux sélections de quatre couleurs et deux sélections de deux couleurs.
  3. Non.
  4. Non.
  5. Non.
  6. Non.
  7. Non, uniquement sur la frontière 1 ko.
  8. Non.
Les chances d'obtenir un jeu à défilement fluide : malheureusement nulles.

ZX Spectrum 48K
  1. Non, seulement des bitmaps.
  2. Oui : 256x192 (8 ko) avec couleur par blocs de 8x8.
  3. Non.
  4. Non.
  5. Non.
  6. Non.
  7. Non.
  8. Non.
Les chances d'un jeu à défilement fluide : pas à 50 images par seconde. En utilisant beaucoup de graphismes pré-tournés en mémoire, il est à peu près possible d'obtenir un jeu à 25 images par seconde, si l'on est très intelligent - voir Dominic Robinson.

Commodore 64
  1. Oui.
  2. Oui : 320x200 en deux couleurs ou 160x200 en quatre couleurs (8 ko) avec couleur en blocs 8x8.
  3. Oui.
  4. Non.
  5. Oui, huit.
  6. Oui.
  7. Non, seulement sur la frontière 1 ko.
  8. Non, mais nous pouvons changer le jeu de caractères, pour les panneaux de score et autres.
Le fait d'avoir des caractères définissables par l'utilisateur signifie que nous pouvons afficher 32 pixels multicolores à l'écran en une seule fois en changeant un octet, ce qui permet de gagner beaucoup de temps. En modifiant le graphique actuel, nous pouvons changer toutes les occurrences du caractère à l'écran en une seule fois, ce qui est très puissant.

Les chances d'obtenir un jeu à défilement rapide : excellentes. Le défilement rapide est possible parce que nous avons le temps de reconstruire tout l'arrière-plan à chaque image et de contrôler les sprites. Nous pouvons aussi, de manière plus économique, faire défiler lentement et construire un nouveau tampon sur, disons, huit images, et passer à une nouvelle zone d'écran de 1 ko en fonction des besoins.

Atari ST
  1. Non, seulement des bitmaps.
  2. Oui : 320x200 en 16 couleurs (32 ko).
  3. Non, pas avant le STE.
  4. Non.
  5. Non.
  6. Pas vraiment.
  7. Non, les limites sont restreintes.
  8. Non.
Les chances d'obtenir un jeu à défilement fluide : juste assez de temps processeur si vous pré-tournez les graphismes dans toutes les positions possibles et si vous réduisez éventuellement le nombre de plans/couleurs et l'espace de jeu en ajoutant un grand panneau de contrôle.

J'ai réalisé un prototype de Paradroid 90 avec un arrière-plan en quatre couleurs défilant dans toutes les directions, mais nous avons opté pour une version en 16 couleurs avec uniquement un défilement vertical parce que nous avons estimé qu'un nombre inférieur de couleurs serait inacceptable.

Commodore Amiga A500/A600/A1000
  1. Non, seulement des bitmaps.
  2. Oui : 320x200 ou suraffichage jusqu'à 64 couleurs (48 ko ou plus).
  3. Oui.
  4. Oui, deux, si nous limitons chacun à huit couleurs.
  5. Oui, quatre sprites de 16 couleurs et de 16 pixels de large sur tout l'écran.
  6. A peu près.
  7. Oui, sur n'importe quelle frontière de deux octets.
  8. Oui.
J'ai réalisé le prototype d'Uridium 2 avec un mode double plan. Nous avions un avant-plan de sept couleurs et un arrière-plan parallaxe de trois couleurs défilant en dessous. C'était assez efficace en soi, mais avec seulement sept couleurs pour l'arrière-plan principal et les objets qui s'y trouvaient, il allait être très difficile de les distinguer. Nous aurions pu utiliser les sprites matériels du Manta pour le faire ressortir, mais nous devions aussi faire ressortir les murs, les vaisseaux ennemis et les balles. Nous avons donc décidé d'utiliser des graphismes 32 couleurs pour l'arrière-plan.

Le jeu de composants AGA de l'A1200 a poussé les plans plus loin, permettant deux plans de 16 couleurs chacun, ou un plan avec jusqu'à 256 couleurs à partir d'une palette de 16,8 millions de couleurs, et 2 Mo de mémoire. On m'a dit qu'il avait de meilleurs sprites matériels, mais je ne me souviens pas comment cela fonctionnait.

Dans un monde idéal

Ce que nous voulions vraiment, c'était ce que les bornes d'arcade avaient. Avant qu'elles n'aient des capacités d'agrandissement et de rotation des sprites, et donc de la 3D, il semblerait qu'elles avaient deux ou trois plans, des caractères de 8x8 pixels qu'elles pouvaient refléter individuellement en X ou Y, de très nombreux sprites qui pouvaient aller entre ou au-dessus des plans, avec une réflexion en X ou Y, et dans un certain nombre de palettes de couleurs différentes. Il est clair qu'elles avaient aussi un défilement fluide en X et Y. Je pense que Taito avait cela dans la borne Flying Shark de 1987, par exemple.

Un PC moderne

J'ai pensé qu'il serait intéressant de comparer aussi un PC moderne, dont les capacités ne sont pas différentes de celles d'une console moderne.

Azumi, le PC
  1. Non, seulement des bitmaps.
  2. Oui : 800x600 jusqu'à 1920x1200 en 16 millions de couleurs (8 Mo).
  3. Non.
  4. C'est possible logiciellement avec des couches.
  5. Non.
  6. Oui.
  7. Contrôlé par le système d'exploitation, donc non.
  8. Non.
Alors que nous avons commencé par des "Non" et qu'ils sont devenus des "Oui" au fur et à mesure que les ordinateurs domestiques s'amélioraient, soudainement, lorsque l'Amiga a été submergé par les consoles et les PC, les "Oui" sont redevenus des "Non", à une exception près : le processeur central et les unités de traitement graphique ont maintenant assez de temps pour reconstruire l'écran à partir de zéro dans une image de 60e de seconde en raison des capacités en multifil d'exécution de chacun. Vous pouvez trouver deux, quatre ou même six coeurs de processeur, et 50, 100 ou même 1500 unités de traitement graphique dans votre PC. Chaque pixel rendu peut effectuer son propre calcul d'éclairage sur une puce graphique. Il s'agit d'une avancée impressionnante, qui n'a toutefois pas simplifié la tâche des programmeurs, ni celle des graphistes.

Quelques informations de base

Autrefois, nos écrans d'ordinateur avaient des bords. Aujourd'hui, l'affichage est conçu pour s'adapter exactement à l'écran, il n'y a pas de bordure. Vous pensez peut-être que c'est mieux, qui a besoin d'une bordure ? Eh bien, nous avions l'habitude de trouver les bordures extrêmement utiles. Nous pouvions assembler nos programmes en mode débogage, c'est-à-dire que nous pouvions sélectivement insérer ou supprimer des lignes de code, afin de donner une couleur différente à la bordure à la fin de chaque routine importante.

Nous avons utilisé des interruptions synchronisées avec l'affichage de l'image pour contrôler la vitesse du jeu et donner une certaine stabilité aux couleurs des bordures : elles commençaient toujours à afficher des couleurs au même stade de l'écran, et vous pouviez faire en sorte que la routine de défilement soit d'une seule couleur, la restauration de l'écran d'une seule couleur, les mises à jour d'objets d'une seule couleur et les traceurs d'une seule couleur. De cette manière, vous obtiendrez une cascade de couleurs cohérentes sur les côtés et vous pourrez voir, par exemple, que la mise à jour de tous les objets peut prendre quelques blocs de caractères vers le bas, que les traceurs peuvent en prendre cinq, et ainsi de suite. Si une routine mettait la moitié du bord de l'écran en une seule couleur, vous saviez qu'elle aurait besoin d'être maîtrisée. De plus, en cas de plantage, vous vous retrouviez avec la couleur du bord de l'écran définie par la dernière routine qu'elle n'avait pas terminée.

Nous aurions de nombreux commutateurs de compilateur dans un fichier d'en-tête de premier niveau afin de pouvoir contrôler différentes configurations. L'un d'entre eux était :

No             equ 0
Yes            equ 1
MonitorDisplay equ No   ; Display CPU usage. Final build: No

Nous avions une macro assembleur appelée "Flash", à laquelle vous pouviez passer une valeur de couleur, ou en fait n'importe quelle source assembleur valide telle qu'un registre, une valeur immédiate ou une variable :

Flash  Macro
    If MonitorDisplay=Yes
    move.w \1,COLOR00
    EndC
 EndM

En réglant "MonitorDisplay" sur "Yes", la macro assemblera l'instruction supplémentaire pour définir la couleur de la bordure. Si elle est réglée sur "No", elle n'assemblera rien, ce qui évite toute perte de temps. Pour utiliser la macro, vous pouvez avoir un morceau de code comme celui-ci :

Flash  #$0500               ; Red
  bsr    WipeRadar
  Flash  #$0050               ; Green
  jsr    SpriteHandler
  Flash  #$0055               ; Cyan
  jsr    RestoreBack
  bsr    CharAnimateControl
  Flash  #$0005               ; Blue
  jsr    PlotSchedule
  bsr    BuildCopperList
  move.l ColourPalette\w,a0
  move.w (a0),d0
  Flash  d0

La dernière utilisation de Flash donne à la bordure la couleur qu'elle était censée avoir, généralement le noir. Les couleurs ne doivent pas être trop vives, sinon le moniteur commence à déformer la largeur des lignes, ce qui rend l'écran difficile à lire. Notez que la couleur zéro de l'Amiga est à la fois la bordure et la couleur de l'écran.

Les puces graphiques devaient lire la mémoire d'affichage de l'écran, ajouter les données des sprites au mélange, et envoyer les couleurs résultantes directement à la sortie vidéo pour que le moniteur les affiche, le tout dans une synchronisation exacte pour montrer une image. En bas de l'écran, l'affichage est terminé et se repose pendant que la trame traverse la couleur de la bordure inférieure avant de revenir en haut de l'écran. Elle affiche ensuite d'autres couleurs de bordure jusqu'à ce que l'affichage suivant commence. Le temps pendant lequel la puce graphique n'affiche pas de données s'appelle l'intervalle de "vide vertical" ou "temps mort vertical", alias "VBlank". Lorsque la trame revient en haut de l'écran, on parle de "retour en arrière".

L'Amiga était assez flexible : nous pouvions définir le nombre de lignes que nous voulions afficher sur l'écran, où elles commençaient et où elles finissaient, et nous pouvions également définir les positions des bords gauche et droit. Il existait des directives et des normes, et nous nous en sommes tenus à celles-ci. En règle générale, un écran PAL dispose de 312 lignes d'affichage verticales possibles, et nous en avons utilisé 256, à raison de 50 images par seconde. Un écran NTSC a 262 lignes, nous avions donc moins de lignes verticales disponibles et nous devions travailler à 60 images par seconde. C'est le dispositif d'affichage qui menait la danse. Aujourd'hui, la carte graphique du PC a tendance à dire à l'écran ce qu'elle va obtenir, et la plupart des écrans de PC fonctionnent à 60 images par seconde. Certaines cartes sont équipées d'un système G-Sync qui permet de varier la fréquence des images, l'écran attendant que la routine d'affichage lui indique qu'un nouvel écran est disponible. Votre fréquence d'images devient flexible et, comme l'écran n'est pas construit par des électrons frappant un écran phosphorescent, l'écran LED ou LCD conserve simplement le dernier jeu de pixels de couleur qui lui a été envoyé jusqu'à ce qu'il en reçoive de nouveaux. Oui, vous avez besoin d'un moniteur G-Sync, d'une carte graphique et d'un jeu pour faire cela.

Si vous tracez des objets sur un écran bitmap plutôt que d'utiliser des sprites matériels, vous devez vraiment utiliser ce que nous appelons le double tampon mémoire. En fait, nous montrons un écran au joueur sans y toucher, puis nous construisons l'écran suivant dans une deuxième zone de la mémoire, à notre guise, et lorsque c'est terminé, nous pouvons attendre la fin de la trame d'affichage avant de permuter les tampons, c'est-à-dire que nous présentons le nouvel écran au joueur et que nous pouvons commencer à travailler sur l'ancien tampon.

Il est étonnant de constater qu'il a fallu beaucoup de temps aux PC pour implémenter une synchronisation verticale correcte. Combien de fois avez-vous vu des "déchirures" d'écran où il y avait manifestement un problème sur l'écran, l'affichage étant basculé sur le tampon arrière pendant l'affichage de l'écran ? Le processeur n'avait aucun moyen de détecter quand l'affichage d'une image entière était terminé. Sur Amiga, nous pouvions configurer des interruptions pour qu'elles se déclenchent dès que la période de vide vertical commençait, ce qui nous permettait de savoir qu'il était possible de basculer les tampons de l'écran.

Vers la routine de défilement de l'Amiga

L'écran Amiga que nous avons utilisé était composé de tuiles de 16x16 pixels, pour des raisons d'efficacité et de flexibilité. Le processeur peut écrire le double de cette largeur, mais les tuiles seraient plus difficiles à travailler, et la détection des collisions serait plus granuleuse.

Comme nous ne disposons pas d'assez de temps processeur pour reconstruire un écran de 40 ko issu des tuiles 16x16 à partir desquelles l'arrière-plan est construit, et comme une bonne partie de l'écran ne change pas, nous voulons être en mesure d'utiliser les données déjà présentes. Cette approche diffère de celle des jeux plus modernes pour PC et consoles, où il y a généralement une caméra dynamique et où nous devons de toute façon recommencer chaque image depuis le début. La plupart des logiciels commerciaux ne mettent toutefois à jour que les éléments de l'écran dont ils savent qu'ils ont changé.

Nous devons être en mesure de restaurer un écran à l'identique avant de tracer les nouveaux objets sur l'arrière-plan, faute de quoi les objets laisseraient des traces. Nous pourrions soit marquer les blocs de caractères comme sales et restaurer les blocs sales en tant que caractères entiers, soit nous souvenir de l'endroit où nous avons placé les objets sur l'écran et copier uniquement la zone sous les objets qui a été perturbée. En fait, nous devions faire un peu des deux. Nous avons géré des personnages (NDTrad : caractères ?) animés, tels que les chutes d'eau dans la jungle du niveau 2 de Fire And Ice. Si nous avons mis à jour l'animation des personnages, nous devons mettre à jour toutes les instances de ces personnages sur le tampon d'écran vierge, puis copier les données sur les deux (ou trois) tampons arrière suivants pour garantir que tous les écrans affichent la même chose.

Nous avons choisi de ne pas marquer les caractères comme sales en raison du temps supplémentaire nécessaire pour déterminer les blocs à restaurer, et parce qu'un objet minuscule de quatre pixels pourrait salir quatre caractères entiers s'il se trouvait à l'endroit où ils se rencontrent. La routine de tracé doit déjà déterminer où elle va tracer sur l'écran, nous stockons donc simplement cette information dans une liste de restauration par écran.

Nous avons également utilisé des sprites matériels pour représenter certains objets. Pour ces derniers, nous pouvons ignorer les masques et copier simplement l'image dans les tampons des sprites. En outre, nous n'avons pas besoin de stocker les positions de restauration de l'arrière-plan car les données ne sont pas tracées sur l'arrière-plan réel.

L'Amiga avait un certain nombre d'opérations asynchrones en cours. Par exemple, il y avait une puce Copper. On pouvait lui donner une série d'instructions pour attendre des lignes de trame spécifiques sur l'écran et charger les registres matériels avec des valeurs. Cela permettait de définir les adresses de départ du plan de bits pour l'écran, puisque celles-ci changent à chaque image parce que nous écrivons sur deux (ou trois) écrans. Nous l'avons également utilisé pour les effets de couleur, les divisions d'écran et les images réfléchies dans l'eau. Le panneau inférieur de Fire And Ice au niveau de la ligne de flottaison a commencé à lire les données graphiques à l'envers, a légèrement modifié les couleurs et a appliqué un motif sinusoïdal à la position de défilement X sur chaque ligne.

Fire And Ice
Fire And Ice

Nous disposons également de la puce Blitter, qui peut être utilisée pour copier des données de A à B, ou pour tracer des données sur l'arrière-plan (masque "ET" logique de données de A à C, puis "OU" logique des données de B à C). Puisque nous avons entrelacé nos plans de bits, à condition d'entrelacer cinq masques identiques dans nos données de tracé, nous pouvons tracer un objet avec une opération Blitter. Cela nécessite plus de données, mais signifie que vous pouvez laisser le Blitter s'occuper de l'ensemble du tracé pendant que vous travaillez sur l'objet suivant. Nous avons vérifié que le Blitter était prêt pour une nouvelle action juste avant que les données ne soient prêtes pour le Blit suivant.

Les sprites matériels sur l'Amiga ne sont pas comme ceux du C64, mais plutôt comme ceux des Atari 8 bits. Vous devez disposer tous les objets que vous voulez tracer en séquence sur l'écran et commencer à les placer dans les quatre listes, une pour chaque sprite de 16 couleurs. Chaque liste de sprites se compose d'une image, puis d'une instruction d'attente pour la ligne de trame lorsque la suivante commence. Si nous avions trop de sprites matériels sur une ligne de trame, nous devrions utiliser la routine de tracé standard du Blitter pour les sprites supplémentaires. Dans tous les cas, nous pouvons également utiliser le Blitter pour copier les données de l'image dans les listes de sprite.

Mettre de l'ordre

Il est important de faire les choses dans le bon ordre. Le bon ordre dépend du type de jeu que vous écrivez. Il y a des jeux qui défilent à une vitesse constante, comme Flying Shark, des jeux qui peuvent défiler à une vitesse constante ou s'arrêter à certains moments, comme Dragon Breed, ou des jeux où le joueur a le contrôle de l'endroit où il veut aller. Je préfère ce dernier type de jeu.

Le mouvement du joueur à partir du périphérique d'entrée est utilisé pour ajuster la vitesse du joueur, ce qui détermine la nouvelle position du joueur. La position du joueur sur la carte détermine la position du joueur sur l'écran, et selon que le joueur est bloqué au milieu ou autorisé à se déplacer dans une boîte au milieu de l'écran, la position du joueur sur l'écran détermine la nouvelle position de défilement requise. Dans les deux cas, l'écran ne défilera pas plus vite que le mouvement du joueur, que nous avons défini dans le mode de contrôle.

Nous travaillons toujours en coordonnées, la nouvelle position de défilement est déterminée par des tests simples qui maintiennent le joueur sur l'écran, et éventuellement au milieu. La vitesse de défilement réelle n'est stockée nulle part, nous avons juste une nouvelle position de défilement et une position de défilement précédente, et la routine doit faire tout ce qu'il faut pour aligner le nouvel affichage de l'écran pour le joueur, indépendamment de l'endroit où il se trouvait la dernière fois, qui peut être deux mouvements plus tard dans un système à double tampon, ou trois dans un système à triple tampon.

Défilement vertical en premier

Tout ce qui suit se réfère à Uridium 2, mais la plupart s'appliquent également à Fire And Ice. Ce dernier utilisait des graphismes en 16 couleurs, alors qu'Uridium 2 utilisait 32 couleurs sur le jeu de composants ECS, et 64 couleurs sur le jeu de composants AGA.

Afin de préserver autant que possible l'arrière-plan pendant le défilement, nous devons utiliser une astuce Amiga qui permet de redémarrer l'affichage à n'importe quel point de l'écran. L'origine étant toujours en haut à gauche, commençons par là.

Notre arrière-plan est constitué de caractères de 16x16 pixels. On pourrait tout aussi bien utiliser des caractères 32x32, ou 8x8. Notre choix s'est fait en fonction de l'efficacité et de la flexibilité du dessin. Nous avons fait Rainbow Islands en 8x8 parce que c'est ce que nous pensions que Taito utilisait, bien qu'ils avaient tendance à les arranger en blocs de 2x2 de toute façon.

Nous avions une carte de l'ensemble du niveau en mémoire pour un accès rapide. Il s'agissait simplement des codes de caractères des graphismes 16x16. Les objets devaient savoir quels caractères ils survolaient. Tous les caractères des murs et des hautes tours se trouvaient à l'une des extrémités du jeu de caractères pour permettre une coupure facile. Seules les Mantas et leurs balles entrent réellement en collision avec l'arrière-plan.

En faisant défiler la carte vers le bas, un pixel à la fois, nous commençons les plans de bits de l'écran une ligne de données de trame plus tard. Le caractère du haut commence à reculer sous le haut de l'écran et un nouveau caractère apparaît en bas. La mémoire tampon de l'écran est plus haute (et plus large) d'un caractère que l'écran affichable. La liste Copper a un format statique et est mise à jour pendant le blanc vertical lorsqu'elle n'est pas utilisée pour l'affichage.

Lorsque nous descendons à 16 pixels, nous avons perdu une rangée entière de caractères en haut, elle n'est plus affichée. Ce que nous faisons maintenant, c'est réutiliser la ligne supérieure de l'écran, qui n'est plus visible, avec les graphismes de la nouvelle ligne qui est sur le point d'arriver au bas de l'écran. Tout d'abord, nous configurons les graphismes dans le tampon de restauration vierge en copiant les graphismes des personnages, un par un. Ensuite, nous pouvons copier l'ensemble du rectangle d'une rangée de profondeur sur 20 caractères de largeur de la mémoire tampon vierge vers la zone de mémoire tampon arrière. Nous devons ensuite traiter tous les personnages animés et restaurer toutes les zones couvertes par des objets qui seront déplacés. L'affichage à l'écran aura été déplacé deux (ou trois) fois depuis son dernier affichage, de sorte qu'il est possible qu'une petite zone de restauration inutile soit effectuée en raison de l'ajout d'un nouveau bloc, ce qui est minime et acceptable.

Je viens de me rappeler que certains éléments d'arrière-plan non mobiles, réalisés avec des objets tracés, pouvaient être dessinés sans pixels transparents et être tracés à l'écran sans enregistrer la position de restauration car nous savons qu'ils seront retracés à la prochaine image. Les écoutilles et les petites tourelles d'artillerie répondent à ces critères. Chaque sauvegarde est utile. Ces objets sont généralement bien alignés avec les caractères/octets, ce qui nous permet d'appeler le traceur optimisé qui sait qu'il n'a pas à déplacer le graphisme latéralement pour le mettre en place. Les fruits cachés de Rainbow Islands en sont un exemple. Tant que l'image finale de l'animation correspond à ce qui était sur l'arrière-plan au départ, nous pouvons désactiver l'animation à la fin et gagner du temps sur le tracé.

Nous avons maintenant un écran d'arrière-plan avec une séparation vers le haut, dont nous devons tenir compte. Au fur et à mesure que l'écran défile vers le bas, la séparation se déplace vers le haut depuis le bas à la même vitesse, et nous devons indiquer au Copper de redémarrer l'affichage des plans de bits en haut de la mémoire de l'écran. Nous devons également vérifier la présence de cette division lorsque nous traçons des objets à travers la division, puisque nous devons tracer la partie supérieure de l'objet dans une zone de la mémoire tampon de l'écran, et la partie inférieure dans une autre. Il en résulte également deux entrées dans le tampon de restauration.

Au fur et à mesure que l'écran défile vers le bas, la ligne de partage se déplace vers le haut de l'écran jusqu'à ce qu'elle atteigne le sommet, puis revient vers le bas. On pourrait comparer le tampon mémoire de l'écran à un tonneau roulant. Nous y avons même fait référence dans le code.

Si l'écran défile vers le haut, la séparation se déplace vers le bas et nous devons restaurer les rectangles de caractères en haut de l'écran plutôt qu'en bas. Nous avons créé une routine pour chacune d'entre elles, car elles doivent être rapides, bien qu'elles fassent toutes les deux le même travail, même si elles sont basées sur des positions différentes. La routine est plus rapide si elle n'a pas à répondre à deux situations ou plus. Prenez la décision le plus tôt possible, et bien qu'il faille plus de place pour programmer deux routines presque identiques, l'économie de quelques cycles vous permet de consacrer plus de temps à d'autres choses.

Défilement horizontal en second

C'est la partie la plus intelligente. Nous ne l'avions pas calculé nous-mêmes, mais nous avons discuté au téléphone avec l'équipe de Factor 5 : Holger Schmidt, Thomas Engel et Julian Eggebrecht. Ils avaient déjà programmé Turrican 2 et nous avions vu ce qu'ils avaient réalisé. Ils nous ont expliqué comment faire défiler l'écran latéralement en utilisant une technique similaire à celle utilisée ci-dessus, et tout ce que nous avions à faire était d'allouer quelques octets supplémentaires à la fin de notre tampon mémoire, autant que nous voulions pour faire défiler une rangée de pixels latéralement d'un côté à l'autre de la carte, en fait, disons 20x2x10 octets, c'est-à-dire 400 octets par tampon, ce qui n'est pas beaucoup du tout.

Donc, en commençant en haut à gauche, nous commençons à faire défiler la carte d'un pixel vers la droite. Cette opération est réalisée à l'aide du registre X de défilement matériel. Il s'agit en fait de jeter le nombre de pixels que vous lui indiquez, de 0 à 15, avant qu'il ne commence à afficher l'image de l'écran. Nos tampons d'écran gèrent toujours un caractère de plus en largeur et en hauteur que l'écran, car dans 15 cas sur 16, cette ligne ou colonne de caractères supplémentaires est partiellement visible.

Lorsque vous atteignez 16 pixels de largeur, vous remettez la position X du défilement à 0 et ajoutez un mot (16 bits/pixels) aux pointeurs du début de l'affichage du tampon mémoire et aux pointeurs de division, pour chaque plan de bits. Vous avez maintenant redémarré votre écran d'un caractère entier vers la droite. À ce stade, nous devons construire la colonne de caractères entrant vers la droite dans notre tampon vierge, et copier le rectangle de ce tampon dans notre tampon arrière. Toutes les données que nous devons afficher sont intactes et de nouvelles données arrivent sur la droite. Vous pouvez continuer à aller vers la droite pour autant d'octets supplémentaires que nous avons ajoutés. Un déplacement de 10 écrans vers la droite ne coûte que 400 octets. L'écran entier glisse latéralement dans la mémoire tampon.

Pour revenir à gauche, il suffit de réduire le décalage dans la mémoire tampon de deux octets, soit 16 pixels, à la fois, en le synchronisant avec la position X du défilement fluide, définie par la liste Copper. Nous ajoutons ensuite des colonnes sur le côté gauche et copions les rectangles de la copie vierge vers les tampons de l'écran réel au fur et à mesure qu'ils se présentent.

Tout cela génère beaucoup de code, je ne le nie pas. Les routines du scénario, les rafraîchissements de l'arrière-plan, les animations des personnages, la liste Copper, tout doit fonctionner ensemble. Ce que nous en retirons, c'est un système efficace qui ne nous coûte pas beaucoup de temps processeur pour faire tourner l'arrière-plan, et chaque objet n'a qu'à nettoyer les octets qu'il modifie. Tous ces composants ont pris plusieurs semaines à être programmés, et encore plus de temps pour que j'arrive à m'y retrouver.

Initialisation

La façon la plus simple de configurer les écrans initiaux est de commencer l'écran à la position 1 écran sur le côté de l'endroit désiré. Nous faisons ensuite défiler l'écran jusqu'à la position que nous voulons vraiment pendant qu'il est vide, et comme aucun objet du jeu n'est actif, nous pouvons le faire rapidement, et nous n'avons pas besoin d'attendre les blancs verticaux, donc la routine de défilement tournera en boucle 20 fois si vous le faites horizontalement, ou seulement 12 fois si vous le faites verticalement. La même quantité de travail est effectuée quelle que soit la méthode choisie, car vous rafraîchissez l'ensemble de l'écran dans les deux cas.

Le démarrage de tous les objets à l'écran est généralement commandé par le mouvement de défilement, donc en appelant cela aussi, tous les objets à l'écran sont également démarrés par ce mouvement de défilement initial pour mettre en place les graphismes du jeu. Tout cela est très pratique.

Développement

Cette routine de défilement a été programmée au début du développement de Fire And Ice. Il m'a fallu deux semaines pour la terminer. Il faut commencer par un caractère et le développer. J'ai créé un ensemble de blocs de base sur lesquels j'ai dessiné des nombres afin de pouvoir voir que les bons caractères étaient affichés et que l'animation était visible. Vous pouvez utiliser l'assembleur pour mettre en place une zone de carte simple afin de ne pas avoir à écrire un éditeur de carte et un compresser/décompresser pour le moment.

Fire And Ice avait un mode test supplémentaire car il gérait les pentes. Chaque caractère avait un mot de 16 bits pour définir soit l'angle et la hauteur de la surface du sol, soit le blocage des côtés ou du plafond. En appuyant sur une touche, je pouvais passer de l'affichage des caractères réels à l'affichage d'un diagramme filaire de la surface du sol. Cela permettait de voir que le sol était continu et que la glace était lisse, et qu'il n'y avait pas de passage qui n'aurait pas dû être là. J'avais également un cercle de deux caractères bloqués tout autour de la carte pour m'assurer que les balles, les poissons et les oiseaux restaient dans la zone de jeu principale. Cela a éliminé le besoin de code supplémentaire pour tester les extrémités de la carte ainsi que les personnages bloqués.

À noter : en raison de la philosophie consistant à ne rien mettre à jour inutilement, la carte en fil de fer apparaît au fur et à mesure du défilement, sur les bords avant ou lorsque les objets se déplacent sur l'arrière-plan, ce qui confirme également le fonctionnement de la restauration.

Au début, j'ai relié la position de défilement de l'écran à l'entrée de la souris, afin de pouvoir déplacer l'écran avec la souris. Cette entrée présentait moins de limites, et je pouvais bien sûr ajouter un multiplicateur pour exagérer ou ralentir le mouvement. Cela prouverait que l'écran peut gérer n'importe quel mouvement. À ce stade précoce du développement, il n'y avait pas de jeu, ni d'autres objets à tracer sur l'écran.

Il est difficile de travailler sur une routine d'affichage à l'écran qui fonctionne entièrement sur un tampon mémoire arrière invisible. Il y a beaucoup de fois où vous ne voyez rien se passer sur votre écran parce que vous avez utilisé le mauvais pointeur, ou que vous vous êtes trompé sur un autre point. En général, il y a des preuves qui apparaissent à l'écran : un objet tracé peut s'étaler en diagonale parce que vous vous êtes trompé dans la distance jusqu'à la ligne suivante, ou bien il se termine en avance ou en retard. Je ne me souviens pas d'avoir jamais pu mettre l'écran en mode tampon unique afin de voir les choses écrites à l'écran.

Les graphismes sont également retirés de l'écran par le système de restauration, de sorte qu'il est probable que les graphismes scintillent et que vous ne soyez pas mieux loti en mode tampon mémoire unique. Il faut écrire beaucoup de code et le faire fonctionner à force de volonté et en regardant le code à la recherche d'erreurs. Nous avons commencé avec un système à double tampon mémoire et avons ajouté le troisième tampon en option par la suite. Commencez aussi simplement que possible. Nous avions déjà des routines de tracé de l'Atari ST, donc nous les avons d'abord adaptées aux bitmaps Amiga (quelques lignes faciles à changer), puis nous les avons modifiées pour générer des commandes Blitter plus tard.

Épilogue

Lorsque le jeu est le plus actif, il utilise tout le temps processeur disponible et il n'y a que peu ou pas de temps d'attente entre les trames. Le moindre dépassement dans la trame suivante entraînera le blocage de l'ensemble du processus pendant une trame et l'écran ne se déplacera pas de manière fluide pendant une trame. Naturellement, nous concevons le jeu pour qu'il fonctionne dans les limites du matériel tout en faisant en sorte qu'il se passe le plus de choses possible à l'écran. Votre jeu ne doit pas générer des méchants et des balles à tort et à travers, vous devez limiter ces éléments pour vous assurer que les dépassements ne se produisent pas.

J'ai fait référence à un troisième écran d'arrière-plan à plusieurs reprises. C'est parce que nous avons implémenté une triple mise en mémoire tampon s'il y avait de la mémoire supplémentaire disponible. Avec un système à double tampon mémoire, vous avez un écran affiché et un autre sur lequel vous travaillez. Une fois le travail terminé, vous devez attendre que la trame atteigne la fin de l'écran en cours avant de pouvoir permuter les écrans. Et si vous profitiez de ce temps d'attente pour commencer à travailler sur un troisième écran ? Vous prendriez de l'avance, ce qui vous permettrait d'absorber tout dépassement de délai si quelques balles supplémentaires étaient tirées.

Lorsqu'il y a plus de mémoire disponible sur les Amiga ECS, il s'agit de mémoire non vidéo, appelée mémoire Fast, car le code qui y est exécuté s'exécute plus rapidement que dans la mémoire vidéo, étant donné que les puces vidéo peuvent utiliser la mémoire vidéo et bloquer le processeur. Dans ce cas, nous chargerions également notre code de jeu dans la mémoire Fast, où il s'exécuterait également plus rapidement. Double victoire ! Bonus ! Sur l'A1200 AGA, nous disposons de 2 Mo de mémoire vidéo et d'un processeur plus rapide. C'est la fête !

L'utilisation d'un troisième tampon mémoire nous permet de prendre de l'avance, et permet le mode Mayhem pour les maniaques de l'A1200 qui utilisent la version non-AGA. La version AGA est en permanence en mode Mayhem. Il y a un léger inconvénient : le joueur peut regarder une trame qui s'est produite il y a deux cinquantièmes de seconde et ce qui s'est passé il y a une cinquantième de seconde est sur le point d'être affiché, alors que nous sommes déjà en train de construire la trame suivante. Personne ne pense aussi vite de toute façon, le temps de réaction est d'environ un dixième de seconde, donc on peut espérer que cela ne fasse pas une grande différence. Cela peut faire passer les effets sonores avant les images de la même manière si vous ne les mettez pas en mémoire tampon, ce à quoi nous n'avons même pas pensé !

J'ai aussi vu des références DirectX au triple tampon mémoire, donc je pense que c'est une stratégie légitime si vous avez besoin de temps en temps d'un peu de marge.


[Retour en haut] / [Retour aux articles]