Obligement - L'Amiga au maximum

Dimanche 21 juillet 2019 - 19:16  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Accueil
 · A Propos
 · Articles
 · Galeries
 · Glossaire
 · Liens
 · Liste jeux Amiga
 · Quizz
 · Téléchargements
 · Trucs et astuces


Articles

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

 · Articles in english
 · Articles en d'autres langues


Twitter

Suivez-nous sur Twitter




Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Logiciels
 · Jeux
 · Scène démo
 · Divers


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


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


Partenaires

Annuaire Amiga

Amedia Computer

Relec

Hit Parade


Contact

David Brunet

Courriel

 


Programmation : C - Gestion des sprites matériels
(Article écrit par Pascal Amiable et extrait d'Amiga News Tech - septembre 1991)


Notre exploration des bibliothèques graphiques de l'Amiga continue, avec ce mois-ci la gestion des sprites matériels en C. Pour illustrer le tout, nous allons réaliser un programme simple d'animation de sprites que vous pourrez à loisir modifier, ce dernier se prêtant à de nombreuses variations.

Ce programme va afficher une fenêtre et un sprite sur l'écran du Workbench, sprite qui se déplacera dans le sens inverse de celui de la souris. Ce sprite sera "accroché" à une fenêtre fixe, qu'il suffira de fermer pour terminer le programme. La démarche est très simple, il suffit :
  • D'ouvrir les bibliothèques Intuition et Graphics.
  • De créer un tableau de données correspondant au sprite que l'on veut afficher et déplacer.
  • D'ouvrir une fenêtre initialisée de telle sorte qu'elle puisse nous renvoyer les coordonnées de la souris.
  • D'allouer un sprite matériel et de le déplacer.
Après avoir défini ce qu'il y avait à faire, passons sans plus attendre à la réalisation.

Initialisation du contexte

Pour l'ouverture des bibliothèques Intuition et Graphics, c'est comme d'habitude : il vous suffira pour les explications de vous reporter aux articles précédents de cette série. Le seul point important à souligner concerne les "includes". En effet, comme nous allons travailler avec les sprites, il est nécessaire d'inclure le fichier <graphics/sprite.h>, sans lequel nous ne pourrions rien faire.

La création du tableau représentant l'image du sprite n'est pas compliquée. Toutefois et avant d'en parler, il est nécessaire de donner quelques renseignements supplémentaires sur les sprites matériels.

Les sprites

Les sprites sont des éléments graphiques à part entière qui présentent la particularité d'être indépendants de l'écran sur lequel ils évoluent. Chaque sprite peut avoir, au maximum, une largeur de 16 points (basse résolution) pour une hauteur maximale égale à celle de l'écran sur lequel il se déplace. Cette restriction à 16 points de largeur est due au fait que les sprites sont toujours affichés en basse résolution. Pour vous en persuader, il vous suffit de regarder attentivement le pointeur de souris de votre Workbench : celui-ci est bien en basse résolution alors que le Workbench est en haute résolution (640 pixels de large).

Sur l'Amiga, il est possible d'avoir au maximum huit sprites, numérotés de 0 à 7. Intuition utilise toujours le sprite numéro zéro pour représenter le pointeur de la souris, celui-ci ne pouvant jamais être inhibé (au contraire des autres). Chaque sprite peut être affiché en trois couleurs effectives, la quatrième étant transparente. Les sprites sont associés par paire : 0 et 1, 2 et 3, 4 et 5, 6 et 7. A chaque paire de sprites correspondent trois registres de couleur effectifs. Le tableau ci-dessous résume cet état de fait.

C

Comme nous l'avons vu, notre sprite mesure 16 pixels de large. A chacun de ces pixels vont être associés deux bits (quatre couleurs par sprite). Pour créer l'image de notre sprite, nous allons donc définir un tableau de données similaire à une mini-bitmap, en associant à chaque ligne du sprite, deux mots de 16 bits.

On représente cette ligne de pixels de la manière suivante :

C

En combinant verticalement (du haut vers le bas) les bits des deux mots définissant la ligne de pixels, on retrouve la couleur désirée. Dans notre exemple, les pixels numérotés 0 à 3 seront transparents (image binaire 00), 4 à 7 de la première couleur (01), 8 à 12 de la seconde couleur (10) et 12 à 15, de la troisième couleur (11). Si nous avions réservé le sprite 6, les couleurs 1, 2 et 3 seraient représentées par les registres COLOR 29, 30 et 31.

Comme vous pouvez le remarquer, la définition de l'image d'un sprite, sans être complexe, n'en est pas moins fastidieuse. Vous imaginez sans peine la somme de travail nécessaire à la réalisation d'un sprite animé, puisque pour chaque image de l'animation, il va falloir remplir de cette manière un tableau différent. Pour vous éviter cela, je vous propose d'utiliser un petit logiciel du domaine public qui effectue seul une bonne partie du travail. Il s'agit de GetSprite, qui se trouve sur la disquette Fish 161. Les heureux abonnés avec disquette le trouveront évidemment dans même le tiroir que le programme de cet article.

Création et gestion du sprite

Après la théorie, la pratique. Pour créer un sprite dans notre programme, il faut tout d'abord le déclarer sous la forme d'une structure SimpleSprite :

C

Le tableau de données pointé par le champ "posctldata" se décompose comme suit :

C

Il est à noter que les deux mots du tableau posctl gérant le contrôle de position du sprite seront initialisés par défaut à zéro et mis à jour automatiquement lors de l'utilisation des fonctions GetSprite() et MoveSprite().

Une fois cette structure initialisée correctement (Cf. exemple ci-dessous), il est désormais possible de se réserver un sprite grâce à la fonction GetSprite() dont voici la syntaxe commentée.

GetSprite(simplesprite, numero);

"simplesprite" est un pointeur sur la structure SimpleSprite que nous venons de créer. "numero" correspond au numéro du sprite matériel que l'on souhaite réserver. Si l'on indique -1, c'est le premier sprite libre qui sera choisi. Par "libre", on entend "non réservé par une autre application". Le sprite 0 n'est donc jamais disponible.

Cette fonction retourne un SHORT correspondant au numéro du sprite alloué, ou -1 si l'allocation a échoué. Le sprite ainsi créé, nous pouvons maintenant le déplacer. La fonction MoveSprite() se charge de positionner le sprite aux coordonnées spécifiées. Sa syntaxe est la suivante :

MoveSprite(viewport, sprite, x, Y);

"viewport" est un pointeur sur le ViewPort de l'écran sur lequel le sprite évolue. "sprite" est un pointeur sur le sprite à déplacer. "x" et "y" représentent ses nouvelles coordonnées.

Le programme terminé, il est nécessaire de libérer le sprite pour d'autres applications, à l'aide de la fonction FreeSprite() dont la syntaxe est des plus simples puisqu'il suffit de lui passer le numéro du sprite à libérer :

FreeSprite(numero);

"numero" étant de type SHORT.

Enfin, la dernière fonction que nous allons voir s'appelle ChangeSprite(). Bien que non utilisée dans notre exemple, elle pourra vous être utile puisqu'elle permet de modifier l'image du sprite. Sa syntaxe est :

ChangeSprite(viewport, sprite, data_sprite);

"viewport" est un pointeur sur le ViewPort de l'écran associé au sprite. "sprite" est un pointeur sur le sprite à modifier. "data_sprite" est un pointeur sur la structure userdata contenant la nouvelle image du sprite.

Voilà pour les sprites. Je ne puis que vous conseiller d'examiner attentivement le programme ci-dessous si le moindre doute subsiste dans votre esprit. Le système d'animation graphique de l'Amiga peut sembler plutôt compliqué à priori, mais avec un peu de pratique, on se rend vite compte à quel point il est puissant. Nous verrons le mois prochain une autre facette de ce système : les BOB.

/* --------------------------------------------------------------------- */
/*                                                                       */
/*      Programme de gestion d'un sprite sous workbench                  */
/*                                                                       */
/*      Exemple de programmation des sprites sous Intuition & Graphics   */
/*             - Sprites                                                 */
/*             - Gestion de la souris                                    */
/*             - Création de structures Image                            */
/*                                        P. AMIABLE 1991                */
/*                                                                       */
/* --------------------------------------------------------------------- */

   /* -----------------------------------------------------------------*/
   /*                                                                  */
   /*     Quelques includes utiles......                               */
   /*                                                                  */
   /* -----------------------------------------------------------------*/

#include <exec/types.h>
#include <intuition/intuition.h>
#include <stdio.h>
#include <graphics/sprite.h>

   /* -----------------------------------------------------------------*/
   /*                                                                  */
   /*     Les defines maintenants.....                                 */
   /*                                                                  */
   /* -----------------------------------------------------------------*/

#define INTUITION_REV 0L /* Version d'Intuition (la dernière) */
#define GFX_REV       0L /* Version de Graphics (la dernière) */
#define ROUGE   0xf,0x0,0x0
#define VERT 0x0,0xf,0x0
#define BLEU  0x0,0x0,0xf
#define LARGEUR 640 /* mettre 640 en hi-res et 320 en lo-res */
#define HAUTEUR 256 /* mettre 256 en non entrelacé PAL (200 en NTSC) le double 512 (400) en entrelacé */


   /* -----------------------------------------------------------------*/
   /*                                                                  */
   /*    Déclaration des données pour le sprite.                       */
   /*                                                                  */
   /* -----------------------------------------------------------------*/

UWORD chip sprite[36]=     /* donnée nécessaire à décrire l'image du sprite */
{
  0x0000, 0x0000,

   0x0000,0x3000, 
   0x0000,0x7800,
   0x0000,0xcc00,
   0x0000,0xcc00,
   0x0000,0xcc00,
   0x0460,0xfc60,
   0x067e,0xfe00,
   0x077e,0xcf00,
   0x07f8,0xcfe0,
   0x06f8,0xcee0,
   0x0678,0xce60,
   0x0678,0x0660,
   0x0678,0x0660,
   0x0018,0x0000,
   0x0000,0x0000,
   0x0000,0x0000,

  0x0000, 0x0000
};

struct SimpleSprite pointeur1 =
{
  sprite,         /* pointeur sur les données image du sprite. */
  16,             /* hauteur , la largeur est fixée à 16 pixels par défaut */
  0, 0,           /* position en x, y à l'écran. */
  -1,             /* numéro du sprite , il est initialisé lors de l'appel à GetSprite()
                  /* on l'initialise à -1 pour le moment */
};

   /* -----------------------------------------------------------------*/
   /*                                                                  */
   /*     Définition des variables externes                            */
   /*                                                                  */
   /* -----------------------------------------------------------------*/


/* Declararation des fonctions définies dans le programme */

void main();
void referme();
void init();
void cree_sprite();

struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;

struct Window *fenetre = NULL;

struct NewWindow nouvfenetre =
{
   0,            /* LeftEdge    position en x de la fenêtre */
   0,            /* TopEdge     position en y de la fenêtre */
  150,           /* Width       150 pixels de large */
  15,            /* Height      15 pixels de hauts */
  0,             /* DetailPen   Le texte doit être écrit dans la couleur 0 */
  1,             /* BlockPen    les blocks doivent être dans la couleur 1 */
  CLOSEWINDOW|   /* IDCMPFlags  la fenêtre renvoie un message si l'utilisateur */
  MOUSEMOVE,     /*             a sélectionné le gadget de fermeture ou */
                 /*             si il a déplacé la souris */         
  SMART_REFRESH| /* Flags       Le rafraicissement écran est réalisé par Intuition */
  WINDOWCLOSE|   /*             Gadget de fermeture */
  WINDOWDEPTH|   /*             Gadget de profondeur */
  ACTIVATE|      /*             La fenêtre est active lorsqu'elle est sélectionnée */
  REPORTMOUSE,   /*             Suivi de la souris */
  NULL,          /* FirstGadget Pas de gadgets personnels */
  NULL,          /* CheckMark   Pas de Checkmark particulière */        
  "SPRITE",      /* Title       Titre de la fenêtre  */
  NULL,          /* Screen      Pas d'écran particulier, juste le workbench */
  NULL,          /* BitMap      pas de Bimpa personnelle */
  150,           /* MinWidth    La fenêtre ne peut être plus petite que 150x15 */
  15,            /* MinHeight   ni plus grande que 150x15, bref elle */
  150,           /* MaxWidth    reste comme elle est */
  15,            /* MaxHeight */
  WBENCHSCREEN   /* Type        On accroche la fenêtre au Workbench */ 
};

struct  RastPort *rastport = NULL;
struct ViewPort *viewport  = NULL;


   /* -----------------------------------------------------------------*/
   /*            Programme principal                                   */
   /* -----------------------------------------------------------------*/

void main()
  {

  struct IntuiMessage *message;
  long GetMsg();
  ULONG classemessage;
  int fin = 0;
  void init(),ouvrefenetre(),referme();
  int xmouse,ymouse;
  WORD xsprite1,ysprite1;

  init();
  ouvrefenetre();
  cree_sprite(); 
    while(!fin) /* boucle tant que le gadget de fermeture n'est pas actif */ 
      {
       Wait(1L << fenetre->UserPort->mp_SigBit); /* attente d'un signal */
       while(message=(struct IntuiMessage *)GetMsg(fenetre->UserPort)) /* ce sont des messages */ 
         {
          classemessage = message->Class; /* on recupere la classe */
          switch(classemessage) {

            case CLOSEWINDOW: /* on a fermer la fenêtre */
              fin = 1;
              break;

            case MOUSEMOVE: /* on deplace la souris */
              xmouse = message->MouseX;
              ymouse = message->MouseY;

              /* on déplace le sprite en sens inverse */

              xsprite1 = LARGEUR - 32 - xmouse;
              ysprite1 = HAUTEUR - 32 - ymouse;
              
              MoveSprite( viewport, &pointeur1, xsprite1, ysprite1 );

              WaitTOF(); /* Attente de trame afin de voir le sprite correctement */
              break;

            default: break;
          }
          ReplyMsg((struct Message *)message); /* libere le message */
        }
     }
   referme(); /* au revoir */
}
   

   /* -----------------------------------------------------------------*/
   /*     Init() Ouvre la bibliothèque                                 */
   /* -----------------------------------------------------------------*/

 void init()
  {
   char *OpenLibrary();

   IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",INTUITION_REV);
   if(!IntuitionBase)
      {
       exit(FALSE);
      }
   GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",GFX_REV);
   if(!GfxBase)
      {
       referme(); 
       exit(FALSE);
      }
   }
 

   /* -----------------------------------------------------------------*/
   /*     ouvrefenetre() ouvre la fenetre et les gadgets               */
   /* -----------------------------------------------------------------*/

 void ouvrefenetre()
  {
    void referme();

   if(!(fenetre=(struct Window*)OpenWindow(&nouvfenetre)))
     {
      referme();
      exit(FALSE);
     }        

   rastport = fenetre->RPort; /* rastport nécessaire pour tracer */
   viewport = (struct ViewPort *)ViewPortAddress(fenetre); /* viewport nécessaire pour la gestion des couleurs */
}



   /* -----------------------------------------------------------------*/
   /*     Cette fonction referme la fenetre et les bibliothèques       */
   /* -----------------------------------------------------------------*/

void referme()
 {
  if( pointeur1.num != -1 )
    FreeSprite( pointeur1.num );

  if(fenetre)       CloseWindow(fenetre);
  if(IntuitionBase) CloseLibrary(IntuitionBase);
  if(GfxBase) CloseLibrary(IntuitionBase);
 }


   /* -----------------------------------------------------------------*/
   /*     Cree_Sprite() crée le deuxième sprite                        */
   /* -----------------------------------------------------------------*/

void cree_sprite()

  {
 
 /* Première étape on initialise les registres 21,22,23 qui correspondent à la couleur du sprite */

  SetRGB4( viewport, 21, ROUGE ); /* C.F le define plus haut */
  SetRGB4( viewport, 22, VERT ); 
  SetRGB4( viewport, 23, BLEU ); 

  if( GetSprite( &pointeur1, 2 ) != 2 )
    referme(); /* Le sprite numéro deux est indisponible, on sort. */

  }



[Retour en haut] / [Retour aux articles] [Article précédent] / [Article suivant]