– Enrichir cette rubrique avec d'autres types de plasma hard et soft.
– Pourquoi ne pas rajouter des captures d'écrans de l'effet (gif-anim ?) pour en faciliter la compréhension ?
Les plasmas sont des effets qui ont fait fureur au début des années 90 dans les démos Amiga. Logiquement, les valeureux CPCistes ont tenté de reproduire la chose sur CPC. C'est ainsi qu'avec sa “Plasma Demo”, Gozeur définissait un nouvel effet : le plasma CPC. Par la suite, tout un tas de variantes de cet effet ont été créés. Certes, ça ne ressemble guère aux plasmas Amiga, mais il n'en demeure pas moins que cet effet a marqué les esprits en son temps.
— Basé sur l'article publié dans Quasar CPC numéro 10, Demomaking, par OffseT.
Or donc, comme vous vous en doutez très certainement, nous allons ici détailler le principe du plasma : cet effet vu pour la première fois dans la Plasma Demo de papy Gozeur et que j'avais repris dans ma Glooms' Demo. En dépis des suppliques du petit blond à lunettes pour obtenir directement un programme prêt à l'usage, nous allons nous attacher à en détailler le principe, car, comme le dit l'adage : “ne mettons pas la charrue avant les boeufs !”1)
Tout d'abord, je tiens à préciser que le principe que je vais vous décrire dans cette pages est celui que j'avais utilisé dans la Glooms' Demo après une masturbation cérébrable aussi solitaire qu'intense ! Dès lors, mes neuronnes n'étant pas forcément les plus performants qui soient, et cette démo commençant sérieusement à dater (elle avait été codée durant l'été 1994), si vous trouvez mieux, n'hésitez pas enrichir cet article !
Dans tous les cas, de bon prérequis sur la structure vidéo du CPC et sur le CRTC sont nécessaires pour comprendre la mise en œuvre de cet effet.
Le plasma est un effet venant de l'Amiga ; mais celui-ci n'étant pas réalisable tel quel sur CPC2), il a dû subir des modifications. Il n'en demeure pas moins un effet très impressionnant car c'est toute la surface de l'écran qui est mise en mouvement ! Je suppose que vous avez tous dans la tête l'image d'un plasma CPC, si tel n'est pas le cas, procurez-vous “Plasma Demo” de Gozeur, “See You Soon” de Rick, “Voyage 93” de Beng!, “Madness Demo” de Gozeur ou encore ma “Glooms' Demo” dans la Power System Megademo 1995, et observez bien tout ce qui s'y passe.
Pour mieux comprendre, le plus simple est de décomposer la chose. D'abord, on constate que toutes les lignes sont identiques mais affichées à des positions horizontales différentes à chaque ligne. C'est le mouvement relatif de ces lignes qui donne l'illusion du plasma. Décomposons ces mouvements : il y a tout d'abord un mouvement de translation global (le scrolling, toutes les lignes de décalent globalement vers le droite ou la gauche de l'écran), puis il y a l'ondulation (la position relative des lignes les unes par rapport aux autres change dans le temps).
Le scrolling ne pose pas de problème particulier, par contre l'ondulation est un petit peu plus complexe. En effet, contrairement à celles qu'on rencontre par ailleurs, celle-ci est dynamique (sinon on aurait une bête ondulation de motif sans cet effet de “fluide” que donne le plasma). C'est-à-dire qu'elle n'est pas immuable d'une ligne à l'autre. Pour gérer une telle ondulation, ça n'est pas une mais deux ondulations que nous devrons gérer. Une ondulation générant la “vague” descendante (décalage vers le bas à chaque frame) et une autre la “vague” montante (même le petit blond a compris ce que ça veut dire). C'est la somme de ces deux ondulations simples qui nous permettra d'avoir notre ondulation dynamique à laquelle on ajoutera le scrolling. Le plasma est en place.
Là, vu qu'on ne peut pas gérer ce que je viens de vous décrire en soft3), il va falloir appeler les ruptures à notre secours (si vous ne savez pas ce que c'est qu'une rupture, c'est que vous n'avez pas les prérequis nécessaires, filez vite les acquérir en vous plongeant dans la rubrique consacrée au CRTC). Dès lors, deux choix s'offrent à nous : la rupture ligne-à-ligne ou la RVI. La RVI est une technique un peu lourde pour gérer un simple plasma ; une rupture ligne-à-ligne suffit amplement ! Nous n'avons en effet pas besoin de beaucoup de lignes plusqu'elles sont toutes identiques ! Je vais ici vous expliquer la gestion relative à la rupture ligne-à-ligne que vous devriez maintenant bien connaître si vous avec lu attentivement la rubrique consacrée au CRTC. Ainsi, notre plasma sera compatible avec tous les CPC sauf CRTC type 2 (pour rappel, seule la rupture “deux-lignes-à-deux-lignes” est possible sur ces CRTC ce qui dégrade significativement la qualité d'un plasma).
Bon, à partir de maintenant, vnous allons raisonner en mode 0 (2 pixels par octet) car c'est souvent dans ce mode que le plasma est le plus riche4). Le principe est simple. Il s'agit, pour chaque ligne de notre rupture, d'afficher notre ligne de plasma avec un décalage en pixels donné par la formule : “décalage montant” + “décalage descendant” + “décalage scrolling”. Le problème est qu'en hard, on ne peut gérer de tels décalages qu'au word près en utilisant l'offset ; et croyez-moi, un plasma à l'octet ne serait pas franchement beau à voir5)…
Pour résourdre ce petit problème, nous allons avoir recours à une sorte de page-flipping par ligne. Je m'explique, dans notre RAM écran adressable par la rupture ligne-à-ligne, nous allons en fait avoir notre “sprite-ligne” du plasma en quatre exemplaires, chaque sprite étant décalé d'un pixel par rapport au précédent. Ainsi, en affichant successivement nos quatre sprites, on obtient un décalage au pixel près. Et si vous savez compter, comme on est en mode 0, après un décalage de 4 pixels, on a un décalage d'un word ! Dès lors il nous suffit de décaler l'offset d'une unité et de recommencer notre flipping de sprites.
Si vous avez bien observé les plasmas, vous aurez remarqué que les vagues de gauche reviennent à droite, vous en aurez donc déduit qu'il y a un bouclage du “sprite-ligne” à gérer. Considérons un sprite de 4*x pixels de large6). Une fois que l'offset aura été incrémenté (ou décrémenté) x fois, on pourra le mettre à zéro et personne ne s'apercevra de rien… À condition que votre sprite couvre complètement la largeur de l'écran décalage maximum compris. Réfléchissez-y et vous vous apercevrez qu'il faut que votre sprite soit recopié deux fois en largeur pour couvrir le décalage et que les “Reg1 - 2*x” premiers words de celui-ci doivent de plus être recopiés à la fin pour compenser le cas où votre écran serait plus large que votre sprite (Reg1 étant la valeur du Registre 1 du CRTC, registre qui détermine la largeur visible de l'écran). Si vous n'avez pas tout compris, c'est de ma faute, je ne suis pas très clair, mais comme j'ai horreur de me répéter, je vous conseille de reprendre ce paragraphe en vous faisant des petits dessins !
Voici en résumé ce que devra faire votre programme :
Bien évidemment, pour le décalage des tables de calcul montantes et descendantes (qui contiennent donc nos ondulations montantes et descendantes), ne vous amusez pas à faire de gros LDIR
ou LDDR
bien moches… utilisez plutôt des tables auto-bouclantes dont le principe est expliqué ici ; ainsi vous n'aurez qu'à gérer un pointeur relatif par table (l'un qui monte à chaque frame et l'autre qui descend).
Ceci étant, comme vous l'avez sans doute remarqué, présentés de la sorte, les calculs à effectuer sont très lourd et esperer pouvoir les faire tels quels en assembleur pendant la rupture est pure utopie. Une optimisation des données contenues dans nos tables s'impose…
Pour soulager notre petit assembleur, je vous conseille diverses stratégies. En premier lieu, prenez un “sprite-ligne” de octets de large ; ainsi, le bouclage sera obtenu par un vulgaire AND
, bien plus simple et performant qu'un laborieux CP
! Ensuite, placez vos quatre “sprites-ligne” à des endroits stratégiques en RAM… tous les 256 octets par exemple. Dès lors, le numéro du “sprite-ligne” à afficher sera directement chargé dans les deux bits de poids fort de l'offset9) ! Et puis, pour finir, au lieu de stocker vos tables et décalage en pixels, gérer les en stockant le numéro du sprite dans un premier octet et le décalage de l'offset dans un second ; vos tables sont deux fois plus longues mais autrement plus souples à manier. Dès lors, notre algorithme va être grandement simplifié.
LD A,(IX)
ADD A,(IY)
ADD A,décalage
(partie numéro de “sprite-ligne”)Reg13=(A AND 3) OR screen
(screen contenant les bits 4 et 5 de la configuration vidéo)B=(A/4) AND 3
LD A,(IX+1)
ADD A,(IY+1)
ADD A,décalage
(partie offset)ADD A,B
AND (
-1)
Reg12=A
Attention, ce n'est qu'un algorithme, j'ai mis des commandes faisant penser à l'assembleur pour être plus concis mais c'est tout ! Le programme assembleur final ne ressemblera certainement pas à ça… et ne doit pas y ressembleur si vous voulez que ça fasse moins de 64 NOP (on peut faire beaucoup moins !).
— Cet article ne comportait pas d'exemple, il serait judicieux d'en ajouter un.