Suivez-nous sur X

|
|
|
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
|
|
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
|
|
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
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
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.
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 :
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 :
Le tableau de données pointé par le champ "posctldata" se décompose comme suit :
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 :
"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. */
}
|
|