Dans cette partie, nous verrons les principes fondamentaux pour utiliser la SDL avec Java. J'utiliserai l'EDI Eclipse pour l'installation et la configuration du projet, ce n'est pas très différent avec les autres EDI, mais je n'en parlerai pas. L'installation sera vraiment pas à pas, ainsi, les personnes n'ayant jamais travaillé avec des librairies externes ne seront pas perdues :) .
Installation et préparation du projet
Voici la première étape de l'utilisation de sdljava : l'installation et la configuration. Mais avant cela, j'ai des choses à vous dire concernant cette bibliothèque car comme toutes les bibliothèques elle a des avantages, mais aussi des inconvénients. Je ne suis pas là pour vous les donner, mais je vous dirai ce que vous pourrez faire et ce que vous ne pourrez pas faire.
Pour installer cette bibliothèque, vous aurez besoin :
d'un JDK 1.4 (minimum) ;
de l'EDIEclipse ;
ou de l'EDINetbeans ;
de la bibliothèque SDL version C (Linux ou Windows).
C'est tout. :) Allez, on y va !
Le binding sdljava
Binding ?
Nous allons bientôt commencer l'installation, mais avant je voudrais vous parler de cette bibliothèque.
Comme vous le savez la librairy SDL est, à l'origine, programmée en langage C puis est compilée pour fonctionner avec ce dernier (et avec le C++). C'est là qu'intervient le mot binding. Un binding, c'est, en gros, un portage de bibliothèque d'un langage A vers un langage B. Dans binding, vous avez bind qui signifie en anglais "lier" ; c'est donc une liaison. C'est d'ailleurs pour cela qu'on aura besoin des fichiers libSDLmain.a ou SDL.dll de la bibliothèque standard C pour faire fonctionner notre application.
Citation : Wikipedia
Un binding (qui est un terme anglais désignant l'action de lier des éléments entre eux) signifie en informatique le fait de permettre l'utilisation d'une bibliothèque logicielle dans un autre langage de programmation que celui avec lequel elle a été écrite.
Nombre de bibliothèques sont écrites dans des langages proches de la machine comme le C ou le C++. Pour utiliser ces bibliothèques dans un langage de plus haut niveau, il est donc nécessaire de réaliser un binding.
La conception d'un binding peut être motivée par le fait de profiter des performances offertes par l'utilisation d'un langage bas niveau que l'on ne peut obtenir avec un langage de plus haut niveau. La réutilisation de code éprouvé peut également être une autre source de motivation.
Contenu de sdljava
La librairy sdljava contient tous les éléments de la bibliothèque originale SDL (c'est déjà pas mal :p ), mais contient aussi des extensions. En voici quelques-unes :
SDL_image : permettra de manipuler plusieurs formats d'image ;
SDL_mixer : permettra d'ajouter du son et de la musique dans nos applications ;
SDL_ttf : permettra d'écrire dans notre fenêtre ;
OpenGL : permettra d'utiliser l'accélération matérielle pour l'affichage.
Ce que vous devez savoir avant de commencer
Cette bibliothèque :
est un binding, c'est-à-dire que vous devrez distribuer les fichiers .a ou/et .dll avec votre application ;
n'existe pas en binaire pour Mac OS X, et la compilation est assez complexe (je n'y suis pas arrivé) ;
dont la version "stable" 0.9.1 date de 2005, et dont la version cvs n'a pas été modifiée depuis fin 2006.
Préparation de l'installation
Téléchargement de sdljava
Nous allons maintenant télécharger la bibliothèque pour l'utiliser avec Eclipse ou Netbeans. Vous avez deux solutions : soit vous téléchargez les binaires (donc déjà compilée), soit les sources (c'est à vous de compiler). Nous allons privilégier la première méthode si ça ne vous dérange pas. :) Rendez-vous sur la page de téléchargement de sourceforge pour récupérer la version que vous voulez (Linux ou Windows).
Pour les suicidaires : les sources. :-°
Bien sûr, nous utilisons un binding, donc comme je vous l'ai expliqué nous devons aussi avoir les fichiers libSDLmain.a ou SDL.dll de SDL version C pour utiliser sdljava.
En avant pour le site officiel de SDL !
Nous n'avons pas besoin de prendre les versions de développement, contrairement au tutoriel de M@teo21 sur le SDL en langage C ; les runtime library feront l'affaire. :) Je tiens à préciser pour les utilisateurs de Linux que le site ne propose que des paquets RPM : suivant votre distribution, il faudra donc rechercher le fichier SDL correspondant. L'idéal serait une compilation de la bibliothèque et c'est ce que nous allons voir tout de suite. Les utilisateurs de Windows peuvent passer cette étape.
Récupération du fichier libSDLmain.a sous Linux
La récupération de libSDLmain.a peut se faire de différentes manières. Par exemple, si vous avez déjà SDL d'installé sur votre machine, vous devriez pouvoir retrouver ce fichier. Mais ici, pour que tout le monde soit sur un même pied d'égalité, nous compilerons les sources de SDL puis nous récupérerons notre fichier libSDLmain.a (tout ça pour un fichier, mais ça en vaut la peine :) ).
Normalement, si vous avez déjà libsdl installé sur votre machine, vous devriez trouver libSDLmain.a dans /usr/lib
.
Téléchargez les sources de SDL ici.
Décompressez l'archive dans votre répertoire de travail par exemple.
Ouvrez un terminal, entrez dans le répertoire nouvellement décompressé et tapez :
./configure make
Vous avez votre bibliothèque compilée, mais pas installée. Vous pouvez déjà aller dans le répertoire build du répertoire SDL et vous y trouverez... un fichier nommé libSDLmain.a. :magicien:
Mettez-le de côté pour l'instant. Si vous avez déjà SDL installée, vous pouvez passer la prochaine étape. À partir de maintenant, vous n'avez plus qu'à vous mettre en super-utilisateur dans le terminal (commande su
suivie de votre mot de passe ou sudo
si vous êtes sous debian-like) et à taper make install
.
Récapitulatif des commandes
Pour distribution non debian-like (Slackware, Mandriva, Fedora, OpenSuse...) :
./configure
make
su # saisie du mot de passe
make install
Pour distribution debian-like avec sudo (Debian, Ubuntu et dérivés...) :
./configure
make
sudo make install
# saisie du mot de passe
Voilà ! SDL version C est installée sur votre système et nous avons notre fichier libSDLmain.a. :p On peut donc passer à la suite !
Le fichier SDL.dll sous Windows
Rendez-vous ici et téléchargez l'archive, puis décompressez son contenu dans un dossier que vous mettrez de côté.
Préparation de l'installation
Bien qu'on ne puisse pas vraiment parler d'installation, car nous ferons uniquement de la copie, il y a des choses à faire dans l'ordre !
Tout d'abord, vous allez décompresser l'archive de sdljava.
Vous pouvez constater qu'il y a plusieurs dossiers. Nous n'en utiliserons que deux, dont un obligatoire, et un vivement conseillé. Nous garderons donc les répertoires : lib et docs.
lib : contient le jar de sdljava ainsi que les fichiers .so ou .dll qui lui sont propres ;
docs : contient la javadoc de sdljava ; elle est réellement indispensable !
Vous pouvez donc les mettre de côté avec le fichier libSDLmain.a / SDL.dll et passer à la dernière étape. :soleil:
Création du projet avec Eclipse
Nous allons maintenant créer notre projet sous Eclipse. L'avantage est qu'Eclipse est multi plates-formes donc en utilisant la même version sous Linux ou Windows, le résultat sera exactement le même. :)
Création du projet
Lancez Eclipse comme vous en avez pris l'habitude. Ensuite, créez un nouveau projet Java, puis un nouveau package et pour finir une nouvelle classe, qui contient une méthode main
(n'oubliez pas de cocher la case public static void main(...). Pour notre exemple, j'ai créé un projet qui se nomme TutorielJavaSDL, puis un package que j'ai appelé configuration et enfin une classe installation.
Nous allons maintenant installer la lib' sdljava. Pour cela, rien de plus simple, mais je vais vous faire un petit rappel sur l'architecture d'un projet avec Eclipse.
Les projets sous Eclipse
Quand vous créez un nouveau projet, celui-ci est copié dans le workspace (espace de travail), ce dernier est placé par défaut dans $HOME/workspace
sous Linux et C:\Documents and Settings\(utilisateur)\workspace
sous Windows 2000/XP (C:\Utilisateurs\(utilisateur)\workspace
sous Vista). Si vous consultez le workspace, vous constatez qu'il y a un répertoire par projet et que ces derniers se composent eux-même de répertoires (bin & src).
En résumé dans le workspace
Il y a un répertoire qui porte le nom de votre projet. Ce dernier en contient deux autres :
bin : contient les fichiers compilés .class ;
src : contient les fichiers sources .java ;
Si on s'intéresse à un de ces répertoires, on constate qu'il contient encore un répertoire ! >_ Ce sont les packages (par défaut il n'y en a pas) et enfin dans ce répertoire (package), il y a vos sources !
Les conventions de nommage pour ce tutoriel
Installation de la bibliothèque
Cette partie est très simple : vous allez copier le dossier lib de sdljava à la racine de votre projet avec le fichier libSDLmain.a ou SDL.dll (selon votre OS). Votre racine doit ressembler à cela :
Configuration d'Eclipse
Faites un clic-droit sur votre projet puis sélectionnez Properties (Propriétés). Une fenêtre s'affiche.
Sélectionnez Java Build Path : c'est dans cette partie que nous allons indiquer à Eclipse où est sdljava (car Eclipse ne peut pas le deviner tout seul). Cliquez sur Add External JARs.
Vous devez sélectionner le fichier sdljava.jar qui se situe dans le répertoire lib de votre projet. Validez, puis cliquez sur la petite flèche noire à gauche de sdljava.jar dans la liste (voir screen).
Cliquez deux fois sur Source attachement et choisissez l'option External File... : vous devez sélectionner encore une fois sdljava.jar (qui, je le rappelle, est présent dans le dossier lib de votre projet).
Cliquez deux fois sur Native library location et choisissez l'option External Folder... : cette fois, vous devez indiquer dans quel répertoire se trouve sdljava ; c'est donc simple, il suffit d'indiquer le répertoire lib de votre projet.
Voilà ce que vous devez avoir après ces étapes :
L'installation est terminée ! Si, je vous assure. :) Nous allons exécuter un programme de test pour vérifier que tout fonctionne correctement. Si vous avez un souci avec le programme de test, recommencez l'installation : une chose vous a peut-être échappé.
Programme de test
package configuration;
import sdljava.SDLMain;
import sdljava.SDLException;
import sdljava.video.*;
public class Installation {
private SDLSurface screen = null;
public Installation() throws SDLException, InterruptedException {
SDLMain.init(SDLMain.SDL_INIT_VIDEO);
screen = SDLVideo.setVideoMode(640, 480, 32, SDLVideo.SDL_DOUBLEBUF | SDLVideo.SDL_HWSURFACE);
SDLVideo.wmSetCaption("Ma première fenêtre avec sdljava", null);
Thread.sleep(1000);
screen.freeSurface();
SDLMain.quit();
}
public static void main(String[] args) throws SDLException, InterruptedException {
new Installation();
}
}
N'essayez pas de comprendre ce code pour l'instant. Vous devez simplement voir une fenêtre s'ouvrir, puis se refermer et c'est normal ! En tout cas, toutes mes félicitations : la sdljava est opérationnelle. :) On va pouvoir passer aux choses sérieuses (enfin, on va rester simple quand même).
Dans le prochain chapitre, nous verrons comment créer des fenêtres et comment utiliser les modes vidéo...
À tout de suite ! :)
Les fenêtres et les modes vidéo
Dans la vraie vie, quand vous parlez avec une personne vous commencez par lui dire "bonjour", ensuite vous parlez avec elle et enfin vous lui dites "au revoir" puis vous partez. Eh bien avec SDL c'est le même principe ! Pour travailler avec, vous devez l'initialiser (lui dire "bonjour"), puis à partir de ce moment vous avez le droit de travailler (parler avec elle), et quand vous avez fini, vous la quittez (vous lui dites "au revoir").
Initialisation de sdljava
Initialisation
On commence par importer les classes dont nous aurons besoin pour travailler. Pour l'instant trois suffiront, mais vous verrez qu'on va vite en importer encore et encore. o_O
import sdljava.SDLException;
import sdljava.SDLMain;
import sdljava.video.SDLVideo;
La première va nous permettre de gérer les exceptions, car beaucoup de méthodes sont susceptibles de lever une exception !
La deuxième va nous permettre d'initialiser SDL et ses composants, elle contient tout un paquet de constantes, ainsi que la méthode
init(constante)
;La troisième nous permettra de créer une fenêtre (lui donner un titre, une icône, ...).
Les imports faits, nous pouvons commencer. On initialise sdljava avec la méthode statique SDLMain.init(constante)
. Cette méthode prend en paramètres une ou plusieurs constantes, qui nous serviront à activer certains modules comme la vidéo ou le son par exemple. Voici quelques constantes :
SDLMain.SDL_INIT_VIDEO
: initialise le mode vidéo ;SDLMain.SDL_INIT_AUDIO
: initialise le son ;SDLMain.SDL_INIT_JOYSTICK
: initialise la prise en charge du joystick ;SDLMain.SDL_INIT_CDROM
: initialise la prise en charge des lecteurs CD/DVD ;SDLMain.SDL_INIT_EVERYTHING
: remplace TOUTES les constantes.
On pourra par exemple initialiser la vidéo et le son de cette manière :
SDLMain.init(SDLMain.SDL_INIT_VIDEO | SDL_INIT_AUDIO);
Le symbole | aussi appelé "pipe" permet de faire la séparation entre les constantes. Vous pouvez l'utiliser plusieurs fois pour charger plusieurs composants ; bien sûr si vous n'avez qu'une chose à initialiser vous n'aurez pas besoin de ce symbole. Si vous avez besoin de travailler avec tout (CDROM, AUDIO, VIDEO, etc.) vous pouvez tout initialiser d'un coup avec SDL_INIT_EVERYTHING
, ce qui donne :
SDLMain.init(SDLMain.SDL_INIT_EVERYTHING);
Il y a encore d'autres constantes, et si cela vous intéresse (et je l'espère bien !), je vous invite à consulter la javadoc de sdljava (dossier doc vous vous souvenez ?).
Fermeture
Nous allons nous intéresser à la fermeture (le "au revoir" si vous préférez). Pour quitter SDL, c'est très simple, vous n'avez qu'à utiliser la méthode statique quit()
de la classe SDLMain
.
SDLMain.quit();
Ce code va libérer la mémoire et fermer SDL : vous ne pourrez donc plus travailler avec après cette étape.
Le programme final
Avant de vous montrer le programme final, il faut que je vous dise que les méthodes de sdljava peuvent lever des exceptions. Nous ne les traiterons pas directement au début, mais ça viendra et j'espère que vous êtes bien au point là-dessus, sinon faites un tour ici.
import sdljava.SDLException;
import sdljava.SDLMain;
import sdljava.video.SDLVideo;
public class ModeVideo {
public static void main(String[] args) throws SDLException {
// Initialisation de la SDL avec le mode video
SDLMain.init(SDLMain.SDL_INIT_VIDEO);
// Notre futur code !
// On quitte la SDL et on libère la mémoire
SDLMain.quit();
}
}
Voilà qui est fait. :) Passons à la suite, je vois que vous en mourez d'envie.
Les surfaces : introduction
Nous avons créé une fenêtre noire avec un titre. Ce n'est pas encore super, donc nous allons mettre un peu de couleurs. ^^ Et pour cela nous devons étudier les SDLSurface
!
Les surfaces avec SDL
Une surface est une forme géométrique sur laquelle on dessine des choses... Votre écran est une surface, la fenêtre que vous venez de créer est une surface (une SDLSurface
en réalité ^^ ). On peut donc conclure qu'une surface avec sdljava sera rectangulaire.
Elles vont nous servir à quoi tes SDLSurface
?
Pour faire simple, elle nous serviront à :
afficher une fenêtre ;
afficher une image ;
afficher du texte.
De plus, on pourra noter que chaque SDLSurface
aura des propriétés qui lui seront propres, comme :
la taille ;
la position ;
la couleur de fond ;
la couleur de transparence (canal Alpha) ;
et d'autres...
Utilisation d'une SDLSurface
On doit importer la classe SDLSurface
qui est dans le package sdljava.SDLVideo
, puis créer un nouvel objet de ce type comme ceci :
SDLSurface screen = null;
J'ai volontairement nommé la surface screen, car nous allons l'utiliser pour l'affichage de la fenêtre. Ce que je ne vous avais pas dit, c'est que la méthode SDLVideo.setVideoMode(...)
renvoie une SDLSurface, ce qui nous permet de travailler avec cette dernière par la suite (ajout de couleurs par exemple).
Voilà à quoi va ressembler notre nouveau code :
import sdljava.SDLException;
import sdljava.SDLMain;
import sdljava.video.SDLSurface;
import sdljava.video.SDLVideo;
public class ModeVideo {
public static void main(String[] args) throws SDLException, InterruptedException {
SDLMain.init(SDLMain.SDL_INIT_VIDEO);
/*
* Initialisation du mode vidéo
* 1 - screen est une SDLSurface qui ne fait référence à rien
* 2 - screen est maintenant la SDLSurface principale de l'écran :p
* - Elle contient les méthodes pour changer de couleur
* - Elle contient toutes les méthodes d'affichage (flippe de l'écran par exemple)
* 3 - On change le titre de la fenêtre
*/
SDLSurface screen = null;
screen = SDLVideo.setVideoMode(400, 200, 32, SDLVideo.SDL_HWSURFACE | SDLVideo.SDL_DOUBLEBUF);
SDLVideo.wmSetCaption("Ma deuxième fenêtre en java avec SDL", null);
Thread.sleep(2000);
SDLMain.quit();
}
}
Le code est suffisamment commenté, et il n'a rien de complexe.
On commence par créer une
SDLSurface
que l'on initialise ànull
;La surface
screen
fait maintenant référence à la surface de l'affichage principal.
Vous pouvez aussi initialiser le mode vidéo comme ceci :
SDLSurface screen = SDLVideo.setVideoMode(320, 240, 32, SDLVideo.SDL_HWSURFACE | SDLVideo.SDL_DOUBLEBUF);
Il nous reste un dernier point à aborder avant de nous amuser à colorier notre fenêtre : c'est la libération de la mémoire avec la méthode freeSurface()
. En effet, lorsque vous avez fini d'utiliser une surface, il faut la détruire pour libérer la mémoire. Ici, c'est la surface qui correspond à la fenêtre principale. Vous me direz sûrement : "oui, mais quand le programme arrive à l'instruction SDLMain.quit()
la mémoire est libérée !" ; eh bien c'est vrai, mais c'est une bonne habitude à prendre, surtout si vous travaillez avec une autre surface que celle de l'affichage. Nous n'avons qu'à rajouter screen.freeSurface()
juste avant SDLMain.quit()
et le tour est joué. ^^
Maintenant que ce point est éclairci, nous allons donner un peu de couleurs à cette fenêtre toute triste. ;)
Changer la couleur de fond
Nous utiliserons trois nouvelles méthodes, qui font partie de la surface screen. Les voici :
fillRect(long couleur)
;mapRGB(int rouge, int vert, int bleu)
;flip()
.
La méthode
fillRect(long couleur)
permet de changer la couleur de fond de la surface qui l'appelle. Elle prend en paramètre un nombre (long
), mais utiliser cette méthode comme cela n'est pas efficace car on ne sait pas quelle couleur correspond à quel nombre... C'est pour cela qu'on l'utilisera avec la prochaine méthode.La méthode
mapRGB(int rouge, int vert, int bleu)
renvoie un nombre de typelong
et prend en paramètres trois entiers (int
) représentatifs des couleurs : rouge, vert et bleu. L'utilisation de la méthode précédente avec celle-ci sera donc particulièrement efficace !La méthode
flip()
permet d'appliquer les changements à l'écran. Cette méthode est donc à appeler à la fin de toutes nos manipulations.
Red, Green and Blue
La méthode mapRGB()
prend en paramètres trois int
comme nous l'avons vu. Ces valeurs varient entre 0 et 255. Par exemple, si vous voulez une couleur noire, il faut mettre toutes les valeurs à 0, car quand on les mélange, cela donne du noir ; l'inverse pour le blanc, c'est-à-dire 255 partout. Essayez donc de faire vos "mix perso". ^^ Si vous ne comprenez pas, l'idéal, c'est de prendre le temps d'essayer chaque cas de figure ; vous verrez c'est vraiment tout bête à comprendre. Vous pouvez trouver une couleur avec son code RGB (red, green, blue) dans les logiciels d'édition d'images, comme The Gimp ou Paint.
Dans The Gimp, vous trouverez l'outil de couleurs dans le panneau de droite (à l'origine).
Vous voyez bien R pour Rouge, V pour Vert et B pour Bleu. C'est un bon moyen de se repérer et croyez-moi, nous aurons besoin de savoir avec quelle couleur travailler (quand on verra la transparence Alpha par exemple :-° ).
Voilà le code qui va changer la couleur de fond de votre fenêtre en... bleu !
import sdljava.SDLException;
import sdljava.SDLMain;
import sdljava.video.SDLSurface;
import sdljava.video.SDLVideo;
public class ModeVideo {
public static void main(String[] args) throws SDLException, InterruptedException {
SDLMain.init(SDLMain.SDL_INIT_VIDEO);
// Mode Video initialisé
SDLSurface screen = SDLVideo.setVideoMode(400, 200, 32, SDLVideo.SDL_HWSURFACE | SDLVideo.SDL_DOUBLEBUF);
SDLVideo.wmSetCaption("Ma Troisième fenêtre en java avec SDL =)", null);
/*
* Changement de couleur
* 1 - Une variable couleur est créée et elle fait référence à la couleur
* renvoyée par la méthode mapRGB()
* 2 - La méthode fillRect prend en paramètre la couleur que l'on vient de définir
* 3 - On fait un "flip" de l'écran | On affiche les changements
*/
long couleur = screen.mapRGB(0, 0, 255);
screen.fillRect(couleur);
screen.flip();
Thread.sleep(2000);
screen.freeSurface();
SDLMain.quit();
}
}
Et voilà le résultat :
S'il y a quelque chose qui vous échappe, prenez le temps de bien relire le tutoriel dans le calme. Sinon, vous pouvez passer à la suite.
Les modes vidéo
T'es bien gentil mais elle est où ma première fenêtre avec sdljava ?
On y arrive, ne vous en faites pas ! :p C'est d'ailleurs le but de cette partie : nous allons tout de suite passer à la création d'une fenêtre !
Pour créer une fenêtre, on utilise la classe SDLVideo
avec la méthode setVideoMode()
; pour lui donner un titre, on utilise la méthode wmSetCaption()
.
setVideoMode
SDLVideo
contient plusieurs méthodes et plusieurs constantes. Nous les étudierons au fur et à mesure.
Pour initialiser la vidéo, nous ferons comme suit :
SDLVideo.setVideoMode(640, 480, 32, Constante1 | constante2 | ....);
Je vous détaille rapidement les trois premiers paramètres, puis les constantes.
Le 1er paramètre est la largeur de l'écran en pixels ;
Le 2ème paramètre est la hauteur de l'écran en pixels ;
Le 3ème paramètre est la profondeur de l'écran (le nombre de couleurs).
Donc ici, nous sommes en 640x480 32 Bits, rien de bien compliqué à comprendre.
Les constantes
SDL_DISABLE
: cache le curseur de la souris ;SDL_DOUBLEBUF
: active le Double Buffering ;SDL_ENABLE
: affiche le curseur de la souris (actif d'origine) ;SDL_FULLSCREEN
: affiche la fenêtre en plein écran ;SDL_HWACCEL
: utilisation de l'accélération matérielle ;SDL_HWSURFACE
: les surfaces sont stockées dans la mémoire vidéo (plus rapide) ;SDL_OPENGL
: vous avez deviné non ? :) Initialisation de OpenGL ;SDL_SWSURFACE
: les surfaces sont stockées dans la mémoire système (plus lent).
Il y a encore beaucoup d'autres constantes et encore une fois... consultez la doc. :) De toute façon, si vous ne le faites pas vous n'avancerez pas. :pirate:
Généralement, on utilisera le double buffering et le hardware surface comme ceci :
SDLVideo.setVideoMode(640, 480, 32, SDLVideo.SDL_HWSURFACE | SDLVideo.SDL_DOUBLEBUF);
C'est quoi le Double Buffering ?
En voilà une question intéressante !
C'est une technique utilisée principalement dans les jeux vidéo, pour éviter les scintillements de l'écran lorsqu'on affiche des éléments sur celui-ci. En gros c'est comme si vous aviez deux écrans (on parle en réalité de deux buffers) : votre écran physique, et un autre écran virtuel. L'écran virtuel dessine une image, puis la donne à l'écran physique. Pendant ce temps l'écran virtuel va redessiner une autre image (le temps que l'écran physique affiche la 1ère image), puis quand l'écran physique aura terminé avec la 1ère image, l'écran virtuel lui donnera la deuxième et ainsi de suite. Cela évite que l'écran physique soit seul à afficher les images, car il devrait alors préparer l'image puis l'afficher, puis l'effacer, puis préparer la deuxième, pour l'afficher... Vous comprenez l'avantage de cette technique ? Bien sûr pour afficher une fenêtre ça ne sert à rien, mais quand on affichera plusieurs images qui se déplaceront, cette technique nous montrera toute sa puissance !
Si vous voulez plus d'informations sur cette technique je vous conseille d'aller faire un petit tour ici.
wmSetCaption
On va maintenant donner un titre à notre fenêtre !
SDLVideo.wmSetCaption("Ma première fenêtre SDL en Java !", null);
Ce code permet de donner un titre à la fenêtre. Le premier paramètre est une chaîne de caractères (String
) qui est le nom de la fenêtre, le deuxième paramètre est l'icône que vous voulez lui attribuer. Ici, nous ne voulons pas d'icônes, donc nous lui passons la référence null
.
Le code final
import sdljava.SDLException;
import sdljava.SDLMain;
import sdljava.video.SDLVideo;
public class ModeVideo {
public static void main(String[] args) throws SDLException, InterruptedException {
// Initialisation du mode vidéo
SDLMain.init(SDLMain.SDL_INIT_VIDEO);
/*
* Création d'une fenêtre de 320x240
*Avec une profondeur de 32 bits
* On utilise le mode Hardware Surface
*/
SDLVideo.setVideoMode(320, 240, 32, SDLVideo.SDL_HWSURFACE);
SDLVideo.wmSetCaption("Ma première fenêtre en java avec SDL", null);
// On met en pause le Thread Principal pour que vous puissiez admirer votre fenêtre
Thread.sleep(1000);
// On quitte / Libération de la mémoire
SDLMain.quit();
}
}
Et voilà, c'est fait ! Elle est pas belle la vie fenêtre ? :p
Exercice : changement de couleurs dynamique
Il le faut et c'est pour votre bien. :) Je vais vous mettre en garde maintenant : si vous ne lisez pas la doc et si vous ne pratiquez pas (ou peu), vous ne développerez pas de jeux ou d'applications qui vous rendront fiers. sdljava est une librairy simple et accessible et on programme en Java, alors profitez-en, ne vous limitez pas à ce tutoriel. :)
Le sujet : je vous demande de créer une fenêtre de la taille que vous voulez, dans laquelle nous changerons la couleur de fond 5 fois de suite.
1ère fois : le fond est noir ;
2ème fois : le fond est rouge ;
3ème fois : le fond est vert ;
4ème fois : le fond est bleu ;
5ème fois : le fond est blanc.
Après ça, le programme se termine normalement. Pour réaliser cet exercice, vous avez plusieurs solutions (structures répétitives, alternatives, ...). Le but recherché est le suivant : la fenêtre affiche un fond noir, puis au bout d'un moment (que je vous laisse choisir), la couleur change et ainsi de suite. N'oubliez pas que nos amis les Thread
sont là ! (une seul méthode de la classe Thread
suffit, et elle ne devrait pas vous être méconnue, ... enfin je l'espère :p ).
En avant la correction ! Qui, bien entendu, peut varier selon les implémentations de chacun. Ce n'est donc pas LA correction absolue, c'est UNE correction qui fonctionne.
import sdljava.SDLException;
import sdljava.SDLMain;
import sdljava.video.SDLSurface;
import sdljava.video.SDLVideo;
public class ModeVideo {
public static void main(String[] args) throws SDLException, InterruptedException {
int compteur = 0; // Variable de boucle
/* Initialisation de SDL et de la Vidéo */
SDLMain.init(SDLMain.SDL_INIT_VIDEO);
SDLSurface screen = SDLVideo.setVideoMode(400, 200, 32, SDLVideo.SDL_HWSURFACE | SDLVideo.SDL_DOUBLEBUF);
SDLVideo.wmSetCaption("Ma Quatrième fenêtre en java avec SDL =)", null);
while(compteur <= 4) {
/* On teste chaque valeur de compteur et on agit en conséquence */
switch( compteur ) {
case 0: screen.fillRect(screen.mapRGB(0, 0, 0)); // Noir
break;
case 1: screen.fillRect(screen.mapRGB(255, 0, 0)); // Rouge
break;
case 2: screen.fillRect(screen.mapRGB(0, 255, 0)); // Vert
break;
case 3: screen.fillRect(screen.mapRGB(0, 0, 255)); // Bleu
break;
case 4: screen.fillRect(screen.mapRGB(255, 255, 255)); // Blanc
break;
}
screen.flip();
Thread.sleep(1500);
compteur++;
}
SDLMain.quit();
}
}
Vous avez appris pas mal de choses, et il est peut-être temps de faire le point et de vous reposer un moment. Allez prendre un café ou une pizza (je m'en fiche :p ) et revenez quand vous serez prêts, car nous attaquons les deux derniers chapitres de base et il faut que vous soyez motivés (il n'y a rien de compliqué si ça peut vous rassurer). :lol:
Les surfaces
Résumons un peu :
Vous avez installé sdljava ;
Vous savez créer une fenêtre ;
Vous savez changer la couleur de fond de cette dernière ;
Vous savez lui ajouter un titre ;
Vous connaissez les différents modes vidéo.
Je vous ai fait une brève introduction sur les SDLSurface
et nous allons maintenant les voir de plus près (près comment monsieur ? T'inquiètes pas pour ça bonhomme :D ). Dans un premier temps, nous allons en créer une nouvelle, puis la placer où nous le voulons sur la fenêtre, puis nous en placerons plusieurs. Une fois ce mécanisme compris, vous serez prêt à lire le chapitre de cette partie 1. Allez, on est parti. :diable:
Votre première SDLSurface
En réalité, ce ne sera pas votre première SDLSurface
, puisque nous avons eu l'occasion d'en avoir un bref aperçu dans le chapitre précédent. Dans ce chapitre, nous allons utiliser plusieurs surfaces dans la fenêtre ; cela consistera au début à avoir un rectangle d'une couleur rouge par exemple dans la fenêtre, puis d'en avoir deux, trois... vous me suivez ? Nous allons aussi voir comment les positionner en fin de chapitre. Vous comprendrez aussi l'utilité de la constante SDLVideo.SDL_HWSURFACE
qui nous servira donc à utiliser la mémoire de la carte graphique plutôt que la mémoire système, ce sera bien plus rapide. ^^
Les SDLSurface
Une surface, dans notre cas, est une forme géométrique en 2 dimensions de forme rectangulaire. On peut en créer à l'aide de SDLSurface maSurface
, mais bien sûr une fois créée, il faut bien qu'elle fasse référence à quelque chose, car dans le chapitre précédent, la surface que nous avons créée faisait référence à l'écran. Ici on utilisera la méthode SDLVideo.createRGBSurface(...)
. Cette dernière prend 8 paramètres, mais ne vous en faites pas c'est très simple, les voici :
Le mode vidéo. Dans notre cas : hardware ;
La largeur de la surface ;
La hauteur de la surface ;
Le nombre de couleurs : on utilisera 32 bits comme pour la fenêtre ;
Quatre paramètres de type
long
qui correspondent aux couleurs RGBA de mask. Pour des raisons de simplicité, nous les mettrons tous à 0.
On pourra donc créer une surface comme suit :
rectangle = SDLVideo.createRGBSurface(SDLVideo.SDL_HWSURFACE, 200, 150, 32, 0, 0, 0, 0);
Ici nous initialisons notre SDLSurface
pour qu'elle soit utilisée dans la mémoire de la carte graphique, ensuite nous définissons les paramètres de largeur, de hauteur ainsi que de profondeur (nombre de couleurs). Les quatre derniers paramètres sont à 0 comme indiqué plus haut.
Le problème est qu'en écrivant juste ce code, ça ne va pas fonctionner ! Si vous touchez un peu à AWT/Swing, vous savez que quand on crée un JButton
, il faut dans un premier temps le créer, puis l'attacher à la fenêtre, puis demander à la fenêtre de s'afficher. Eh bien une surface, c'est exactement pareil ! Et pour cela, on utilise la méthode blitSurface(SDLSurface parent)
où parent
est une SDLSurface
et en l'occurrence la fenêtre principale, mais rien ne vous empêche de bliter une surface sur une autre. :p
Voici un code avec Swing pour que vous puissiez comparer :
// votre code d'initialisation
....
// On fabrique un bouton
JButton monBouton = new JButton("bonjour");
// On attache le bouton sur la zone d'affichage
getContentPane().add(monBouton);
// On affiche la fenêtre
setVisible(true);
Et le code en SDL :
// Code d'initialisation SDL, création des SDLSuface, etc...
....
// On crée un nouveau rectangle
rectangle = SDLVideo.createRGBSurface(SDLVideo.SDL_HWSURFACE, 200, 150, 32, 0, 0, 0, 0);
// On attache le rectangle sur la fenêtre (qui est une SDLSurface du doux nom de screen)
rectangle.blitSurface(screen);
// On affiche le tout ! C'est la fenêtre qui contient la surface rectangle, donc c'est elle qu'on flip
screen.flip();
Si vous rajoutez ce code comme ça, vous ne verrez rien et savez-vous pourquoi ? Vous vous souvenez de la couleur de fond d'origine de la fenêtre ? Elle est noire. ;) Et vous souvenez-vous que la fenêtre est une SDLSurface
? Vous en avez donc sûrement déduit que notre surface rectangle sera, elle aussi, noire. Pour remédier à ce problème, nous pouvons changer la couleur exactement de la même manière que pour l'écran, c'est-à-dire avec les méthodes fillRect(...)
et mapRGB(...)
.
Ce qui va nous donner quelque chose comme cela (avouez ! Vous avez senti venir l'exercice hein :D ).
import sdljava.SDLException;
import sdljava.SDLMain;
import sdljava.video.SDLSurface;
import sdljava.video.SDLVideo;
public class Surface {
public static void main(String[] args) throws SDLException, InterruptedException {
SDLSurface screen = null,
rectangle = null;
SDLMain.init(SDLMain.SDL_INIT_VIDEO);
screen = SDLVideo.setVideoMode(640, 480, 32, SDLVideo.SDL_DOUBLEBUF | SDLVideo.SDL_HWSURFACE);
SDLVideo.wmSetCaption("Les SDLSurface avec SDL en Java", null);
rectangle = SDLVideo.createRGBSurface(SDLVideo.SDL_HWSURFACE, 200, 150, 32, 0, 0, 0, 0);
rectangle.fillRect(rectangle.mapRGB(255, 0, 0));
rectangle.blitSurface(screen);
screen.flip();
Thread.sleep(2000);
rectangle.freeSurface();
screen.freeSurface();
SDLMain.quit();
}
}
Positionner une surface
Comme vous avez pu le constater, la surface que nous avons créée s'est positionnée dans le coin en haut à gauche, mais comment faire pour la positionner en plein milieu de l'écran par exemple ? Ou ailleurs même ? On utilisera une nouvelle classe : SDLRect
. Nous allons procéder par étapes comme nous en avons pris l'habitude. ^^
1. Importer la classe SDLRect
:
import sdljava.video.SDLRect;
2. Créer un objet de ce type :
SDLRect posRectangle = new SDLRect();
// Ou bien
SDLRect posRectangle = new SDLRect(int x, int y);
Vous remarquez qu'on peut initialiser notre objet de deux manières :
En utilisant un constructeur sans paramètres ;
En utilisant un constructeur avec paramètres.
Le deuxième constructeur prend en paramètres deux int
qui représentent les coordonnées en X et en Y. Dans le cas du premier constructeur, il faudra, à l'aide des méthodes setX(int x)
et setY(int y)
, fournir ces valeurs.
Voilà par exemple le code pour centrer une surface à l'écran :
// Taille de la fenêtre
int width = 640, height = 480;
// Taille de la surface rectangle
int rectX = 200, rectY = 150;
// Position du rectangle centré
SDLRect posRectangle = new SDLRect();
posRectangle.setX((width / 2) - (rectX / 2));
posRectangle.setY((height / 2 ) - (rectY / 2));
/*
* On pourrait aussi faire comme ça :)
*
* SDLRect posRectangle = new SDLRect(((width / 2) - (rectX / 2)), ((height / 2 ) - (rectY / 2)));
*/
Si vous écrivez ça, encore une fois ça ne fonctionne pas, et je sais que vous savez pourquoi. ^^ Il faut maintenant lier notre SDLSurface
rectangle avec notre SDLRect
posRectangle. On utilisera pour cela une méthode que vous connaissez (si si je vous assure), et d'ailleurs la voilà :
blitSurface(SDLSurface maSurface, SDLRect positionMaSurface);
Comme vous pouvez le voir, la méthode blitSurface peut prendre plusieurs paramètres. Je ne pense pas que vous ayez besoin de plus d'explications, voilà le code qui va centrer notre surface :
import sdljava.SDLException;
import sdljava.SDLMain;
import sdljava.video.SDLRect;
import sdljava.video.SDLSurface;
import sdljava.video.SDLVideo;
class Surface {
public static void main(String[] args) throws SDLException, InterruptedException {
// Taille de la fenêtre
int width = 640, height = 480;
// Taille de la surface rectangle
int rectX = 200, rectY = 150;
// Position du rectangle centré
SDLRect posRectangle = new SDLRect();
posRectangle.setX((width / 2) - (rectX / 2));
posRectangle.setY((height / 2 ) - (rectY / 2));
/*
* On pourrait aussi faire comme ça :)
*
* SDLRect posRectangle = new SDLRect(((width / 2) - (rectX / 2)), ((height / 2 ) - (rectY / 2)));
*/
// Initialisation SDL et Vidéo
SDLMain.init(SDLMain.SDL_INIT_VIDEO);
SDLSurface screen = SDLVideo.setVideoMode(width, height, 32, SDLVideo.SDL_DOUBLEBUF | SDLVideo.SDL_HWSURFACE);
SDLVideo.wmSetCaption("Les SDLSurface avec SDL en Java", null);
// Création d'une SDLSurface rectangle
SDLSurface rectangle = SDLVideo.createRGBSurface(SDLVideo.SDL_HWSURFACE,
rectX, rectY, 32, 0, 0, 0, 0);
// Changement de couleur en rouge
rectangle.fillRect(rectangle.mapRGB(255, 0, 0));
// On blit sur l'écran la surface rectangle avec ses coordonnées (via SDLRect)
rectangle.blitSurface(screen, posRectangle);
screen.flip();
Thread.sleep(2000);
rectangle.freeSurface();
screen.freeSurface();
SDLMain.quit();
}
}
Et voilà le travail !
Faites des tests et essayez de changer les valeurs de SDLRect
pour voir.
Gérer plusieurs surfaces
Nous allons voir très rapidement comment utiliser plusieurs SDLSurface
dans notre programme.
Nous avons déjà créé deux SDLSurface
: la SDLSurface
qui correspond à l'écran et la SDLSurface
qui correspond au rectangle. Maintenant pour en créer d'autres, c'est très simple : il faut faire pareil que pour le rectangle, c'est-à-dire :
Créer une
SDLSurface
;Positionner cette
SDLSurface
avecSDLRect
;Donner une couleur ;
Bliter cette dernière sur la surface écran.
Petit exercice
Vous allez créer un programme qui affiche 4 SDLSurface
(carrés ou rectangles comme vous voulez).
Prenez votre temps pour faire cet exercice (bien qu'il ne soit vraiment pas dur). S'il le faut, utilisez une feuille de papier et un crayon (ou un stylo c'est vous qui voyez ;) ) et dessinez ce qui doit être affiché, cela vous aidera beaucoup croyez-moi.
Allez voilà la correction, j'espère que vous avez réussi. :)
Version 1 : Les mauvaises habitudes.
import sdljava.SDLException;
import sdljava.SDLMain;
import sdljava.video.SDLRect;
import sdljava.video.SDLSurface;
import sdljava.video.SDLVideo;
class Surface {
public static void main(String[] args) throws SDLException, InterruptedException {
// Taille de la fenêtre
int width = 320, height = 240;
// Taille des surfaces
int carre1X = 60, carre1Y = 60,
carre2X = 60, carre2Y = 60,
carre3X = 60, carre3Y = 60,
carre4X = 60, carre4Y = 60;
// Position des surfaces
SDLRect posCarre1 = new SDLRect(30, 30);
SDLRect posCarre2 = new SDLRect(200, 30);
SDLRect posCarre3 = new SDLRect(30, 120);
SDLRect posCarre4 = new SDLRect(200, 120);
// Initialisation SDL et Vidéo
SDLMain.init(SDLMain.SDL_INIT_VIDEO);
SDLSurface screen = SDLVideo.setVideoMode(width, height, 32, SDLVideo.SDL_DOUBLEBUF | SDLVideo.SDL_HWSURFACE);
SDLVideo.wmSetCaption("4 SDLSurface !", null);
// Création des surfaces
SDLSurface carre1 = SDLVideo.createRGBSurface(SDLVideo.SDL_HWSURFACE, carre1X, carre1Y, 32, 0, 0, 0, 0);
SDLSurface carre2 = SDLVideo.createRGBSurface(SDLVideo.SDL_HWSURFACE, carre2X, carre2Y, 32, 0, 0, 0, 0);
SDLSurface carre3 = SDLVideo.createRGBSurface(SDLVideo.SDL_HWSURFACE, carre3X, carre3Y, 32, 0, 0, 0, 0);
SDLSurface carre4 = SDLVideo.createRGBSurface(SDLVideo.SDL_HWSURFACE, carre4X, carre4Y, 32, 0, 0, 0, 0);
// On donne des couleurs différentes à chaques surfaces
screen.fillRect(screen.mapRGB(0, 45, 78));
carre1.fillRect(carre1.mapRGB(255, 125, 135));
carre2.fillRect(carre2.mapRGB(0, 89, 32));
carre3.fillRect(carre3.mapRGB(25, 20, 65));
carre4.fillRect(carre4.mapRGB(55, 240, 12));
// On blit tout ça sur l'écran :)
carre1.blitSurface(screen, posCarre1);
carre2.blitSurface(screen, posCarre2);
carre3.blitSurface(screen, posCarre3);
carre4.blitSurface(screen, posCarre4);
// On flip et on regarde ce que ça donne ;)
screen.flip();
Thread.sleep(5000);
// On quitte
carre1.freeSurface();
carre2.freeSurface();
carre3.freeSurface();
carre4.freeSurface();
screen.freeSurface();
SDLMain.quit();
}
}
Ce code est moche, on pourrait utiliser des tableaux pour stocker les surfaces, les positions et les couleurs.
Version 2 : un code plus "propre" et plus court !
import sdljava.SDLException;
import sdljava.SDLMain;
import sdljava.video.SDLRect;
import sdljava.video.SDLSurface;
import sdljava.video.SDLVideo;
class Surface {
public static void main(String[] args) throws SDLException, InterruptedException {
// Taille de la fenêtre
int width = 320, height = 240;
/*
* Positions des surfaces
*
* Les surfaces n'ont pas la même position, on remplit donc à la main les positions
* avec les méthode setX(int x) et setY(int y)
*/
SDLRect posCarre[] = new SDLRect[4];
posCarre[0] = new SDLRect(30 , 30);
posCarre[1] = new SDLRect(200, 30);
posCarre[2] = new SDLRect(30, 120);
posCarre[3] = new SDLRect(200, 120);
// Initialisation SDL et Vidéo
SDLMain.init(SDLMain.SDL_INIT_VIDEO);
SDLSurface screen = SDLVideo.setVideoMode(width, height, 32, SDLVideo.SDL_DOUBLEBUF | SDLVideo.SDL_HWSURFACE);
SDLVideo.wmSetCaption("4 SDLSurface !", null);
// Création des surfaces
SDLSurface carre[] = new SDLSurface[4];
for (int i = 0 ; i < 4 ; i++) {
carre[i] = SDLVideo.createRGBSurface(SDLVideo.SDL_HWSURFACE, 60, 60, 32, 0, 0, 0, 0);
}
/*
* On donne des couleurs pour chaques surfaces
*
* Vue que chaque surface a des couleurs différentes, on n'utilise pas de boucle for
* On peut utiliser une boucle for pour qu'elles soient toutes de la même couleur
* ou en utilisant des variables R, G, B que l'on incrémente à chaque passage de boucle
*/
screen.fillRect(screen.mapRGB(0, 45, 78));
carre[0].fillRect(carre[0].mapRGB(255, 125, 135));
carre[1].fillRect(carre[1].mapRGB(0, 89, 32));
carre[2].fillRect(carre[2].mapRGB(25, 20, 65));
carre[3].fillRect(carre[3].mapRGB(55, 240, 12));
// On blit tout ça sur l'écran :)
for (int i = 0 ; i < 4 ; i++) {
carre[i].blitSurface(screen, posCarre[i]);
}
// On flip et on regarde ce que ça donne ;)
screen.flip();
Thread.sleep(5000);
// On quitte
for (int i = 0 ; i < 4 ; i++) {
carre[i].freeSurface();
}
screen.freeSurface();
SDLMain.quit();
}
}
Et voilà le travail !
Lisez bien les commentaires pour comprendre ce que j'ai fait. Comme vous pouvez le constater, ce code est plus clair, plus light et pourtant, il fait exactement la même chose ! L'utilisation des tableaux est très importante si vous voulez créer des jeux (que ce soit en 2D ou en 3D) car ils permettent d'avoir un code lisible et ils sont à la base de beaucoup de choses comme les sprites, les maps, etc.
Si ce que vous avez vu vous a paru compliqué, je vous conseille vivement de pratiquer et de relire cette partie. Sinon, je vous invite à passer au dernier chapitre. Un chapitre concernant les images ! Mais je ne vous en dis pas plus, à tout de suite. ^^
Les images
Nous allons maintenant nous intéresser au chargement d'images et à leur manipulation, nous verrons :
le chargement,
la couleur de transparence (canal Alpha),
comment rendre l'image transparente.
Une image n'est qu'une SDLSurface
sans couleur sur laquelle on à posé une image (je simplifie ^^ ), donc ce chapitre ne sera pas très long, mais sera riche en nouvelles connaissances !
Je ferai aussi une brève présentation des événements avec SDL, ce qui nous évitera d'avoir recours à la méthode sleep()
de la classe Thread
. Mais avant toute chose, nous devrons parler de "l'installation" de SDL_image.
Installation et configuration de SDL_image
Installation sous Linux
Amis linuxiens, nous avons du travail ! En effet par rapport à l'installation sous Windows, nous aurons quelques manipulations de plus à effectuer, mais ne vous en faites pas ce n'est pas très compliqué.
Mis à part le fichier libSDL_image.a nous aurons besoin d'autres bibliothèques qui doivent normalement être installées ; si ce n'est pas le cas, il faudra aller télécharger les sources et les installer. Vous devez donc avoir ces bibliothèques :
Regardez plus bas pour savoir si vous les avez.
Si la bibliothèque SDL ainsi que ses extensions sont déjà installées sur votre machine
Allez dans le répertoire /usr/lib
et recherchez les fichiers suivants :
libjpeg.a ;
libpng12.a ;
libSDL_image.a ;
libtiff.a ;
libz.a.
Si vous avez compilé SDL_image à la main, il est fort probable que le fichier libSDL_image.a se trouve dans /usr/local/lib
. Une fois que vous avez ces fichiers copiez-les simplement à la racine de votre répertoire de projet (à coté de libSDLmain.a).
Voila c'est fini. ^^ Profitez-en donc pour créer un nouveau dossier que vous nommerez par exemple images. Il contiendra les images que nous utiliserons dans 5 minutes. ;)
Si la bibliothèque ainsi que ses extensions ne sont pas installées sur votre machine
Allez dans le répertoire /usr/lib
et recherchez les fichiers suivants :
libjpeg.a ;
libpng12.a ;
libtiff.a ;
libz.a.
Une fois que vous les avez, copiez-les à la racine de votre répertoire projet (à coté de libSDLmain.a). On peut passer à la suite. Rendez-vous sur le site de SDL_image pour y télécharger les sources. Décompressez les sources dans un dossier approprié (personnellement j'utilise $HOME/Sources
), puis ouvrez un terminal et compilez la bibliothèque comme ceci :
Sur les distributions type Mandriva, Fedora, OpenSuse, etc.
./configure
make
su
#Entrez votre mot de passe
make install
Sur les distributions type Debian, Ubuntu, etc.
./configure
make
sudo make install
# Entrez votre mot de passe
Rendez-vous ensuite dans /usr/local/lib
et récupérez-y le fichier libSDL_image.a et enfin copiez-le avec les autres bibliothèques, à la racine de votre répertoire de projet. Je vous invite à créer un dossier images, qui contiendra les images que nous utiliserons dans 5 minutes. ;)
Voilà à quoi doit ressembler votre répertoire :
Installation sous Windows
Comme sous Linux vous aurez besoin de plusieurs fichiers dll, la bonne nouvelle est que l'on va récupérer une archive qui contient toutes ces dll. ^^ Vous devez vous rendre sur le site de SDL_image pour y télécharger SDL_image-1.2.xx-win32.zip. Une fois cette archive téléchargée, vous devez décompresser son contenu (plusieurs fichiers .dll) à la racine de votre répertoire projet (à coté de SDL.dll).
L'installation est terminée, profitez-en pour créer un nouveau dossier que vous pourrez nommer images, qui contiendra les images que nous utiliserons dans 5 minutes.
Voilà à quoi doit ressembler votre répertoire projet (en vert le nouveau dossier images, et en rouge les nouveaux fichiers dll) :
Charger une image
Pour charger une image c'est facile, vous vous souvenez des surfaces ? Eh bien figurez-vous qu'une image sera vue par la SDL comme une SDLSurface
, ce qui veut dire que pour charger et afficher une image on a juste une méthode qui change !
Tout d'abord nous devons importer la classe SDLImage
comme nous en avons pris l'habitude :
import sdljava.image.SDLImage;
Ensuite il nous faut une image, oui mais quel format ? Eh bien je risque peut-être d'en décevoir certains, mais les formats jpeg et tif sont très mal pris en charge, nous pourrons par contre utiliser des images aux formats gif, png et bmp. Pour notre exemple je prendrai une image de 640x480 au format png. Cette image devra se trouver dans le répertoire images que nous avons créé plus haut.
Nous devons maintenant créer une nouvelle surface que l'on nommera image, mais à la différence d'une surface classique, nous l'initialiserons avec la méthode load("images/monImage.png");
de la classe SDLImage
.
Une fois l'initialisation faite, c'est exactement comme une SDLSurface
, donc on blit et on flip. ;)
Mais attend ! Et la taille de l'image on la définit pas ? o_O
Eh bien non, la méthode qui charge l'image va créer une SDLSurface
de la taille de l'image, ce qui est très pratique, donc pas besoin de se soucier de la taille de l'image (juste le format).
Voici un code qui charge une image et qui l'affiche sur l'écran, par contre j'ai volontairement enlevé Thread.sleep()
pour le remplacer par un gestionnaire d'événements, que nous verrons dans le prochain chapitre. Ne prenez donc pas peur si vous ne comprenez pas (bien que ça ne soit pas compliqué du tout), mais en gros ce code permet de laisser la fenêtre ouverte tant que vous ne cliquez pas sur la croix dans la barre de tâche. Voilà tout est dit, place au code. :)
import sdljava.SDLException;
import sdljava.SDLMain;
import sdljava.event.SDLEvent;
import sdljava.video.SDLRect;
import sdljava.video.SDLSurface;
import sdljava.video.SDLVideo;
import sdljava.image.SDLImage;
public class Images {
public static void main(String[] args) throws SDLException {
// Gestion des evenements 1/2
SDLEvent event = null;
boolean boucle = true;
// Initialisation de SDL et de l'affichage
SDLMain.init(SDLMain.SDL_INIT_VIDEO);
SDLVideo.wmSetCaption("Des images avec sdljava", null);
SDLSurface screen = SDLVideo.setVideoMode(640, 480, 32, SDLVideo.SDL_DOUBLEBUF | SDLVideo.SDL_HWSURFACE);
// Chargement d'une image
SDLSurface image = SDLImage.load("images/aerith.png");
SDLRect imagePos = new SDLRect(0, 0);
/*
* Gestion des événement 2/2
*
* Boucle Principale
*
* Le code est exécuté TANT QUE la variable booléene boucle est vrai
* SI l'événement SDL_QUIT est vrai ALORS la variable boucle est fausse et donc on sort de la boucle
*/
while (boucle)
{
event = SDLEvent.waitEvent();
if (event.getType() == SDLEvent.SDL_QUIT)
boucle = false;
image.blitSurface(screen, imagePos);
screen.flip();
}
// On quitte :: Libération de la mémoire
image.freeSurface();
screen.freeSurface();
SDLMain.quit();
}
}
Tadaaa, elle est pas belle Aeris la vie ?
Un petit mot sur les événements
Bon, c'est bien parce que c'est vous, :p on commence par créer un objet de type SDLEvent
(bien qu'en réalité on dirait qu'on crée un objet qui fait référence à un objet de type SDLEvent
) et une variable booléenne qui vaut VRAI. L'objet event
une fois initialisé nous informera des événements reçus par le programme. La variable boucle
permet de lancer la boucle principale du programme (nous reviendrons sur la "boucle principale" dans le prochain chapitre), on aurait aussi pu écrire while(true)
et quitter la boucle avec une instruction break
, mais c'est plus "sale".
L'initialisation de l'objet event
se fait grâce à la méthode waitEvent()
de la classe SDLEvent
(nous verrons qu'il existe plusieurs types d'événements). waitEvent()
va mettre le programme en pause tant qu'il n'y a pas d'événements.
On teste ensuite l'événement (on utilisera des switch
dans le prochain chapitre, car ils seront plus adaptés). SDLEvent.SDL_QUIT
est une constante qui correspond au clic sur la croix de fermeture de la fenêtre.
Ensuite on blit l'image et on flip l'écran.
Pourquoi on blit et on flip dans la boucle ?
Car si on blit ou flip après la boucle, le programme se termine donc on ne voit rien :lol: et de plus quand on déplacera des surfaces, il faudra que ce soit à chaque passage de boucle, je vous montre donc comment on fait dès le début !
Ajout d'une autre image
C'est exactement pareil que d'afficher plusieurs SDLSurface
sur la fenêtre, on charge, on donne les coordonnées, on blit et on flip. ;) Bon pour vous montrer je vais ajouter une personne qui tiendra compagnie à Aeris...
public class Images {
public static void main(String[] args) throws SDLException {
// Gestion des événements 1/2
SDLEvent event = null;
boolean boucle = true;
// Initialisation de SDL et de l'affichage
SDLMain.init(SDLMain.SDL_INIT_VIDEO);
SDLVideo.wmSetCaption("Des images avec sdljava", null);
SDLSurface screen = SDLVideo.setVideoMode(640, 480, 32, SDLVideo.SDL_DOUBLEBUF | SDLVideo.SDL_HWSURFACE);
// Chargement des images
SDLSurface aeris = SDLImage.load("images/aerith.png");
SDLSurface zack = SDLImage.load("images/zack.png");
SDLRect aerisPos = new SDLRect(0, 0);
SDLRect zackPos = new SDLRect(300, 50);
while (boucle)
{
event = SDLEvent.waitEvent();
if (event.getType() == SDLEvent.SDL_QUIT)
boucle = false;
aeris.blitSurface(screen, aerisPos);
zack.blitSurface(screen, zackPos);
screen.flip();
}
// On quitte :: Libération de la mémoire
aeris.freeSurface();
zack.freeSurface();
screen.freeSurface();
SDLMain.quit();
}
}
Ce qui nous donne :
:( Mais c'est horrible ! Oui il fraudait que l'image ne soit pas rectangulaire, et qu'elle ait la forme de Zack... Bon pas de panique on va voir ça. ;)
Couleur de transparence
La bibliothèque SDL permet de définir une couleur de transparence, qui ne sera donc pas affichée. Vous avez vu que l'image que j'ai ajoutée a un fond rose, qui correspond au code de couleur 255, 0, 255 : on va donc dire à SDL de la rendre transparente, ce qui aura pour effet l'affichage correct de la deuxième image. Pour réaliser cela nous devrons utiliser UNE nouvelle méthode (oui juste une), la méthode setColorKey()
qui prendra deux paramètres :
une constante,
la couleur à rendre transparente.
Pour le choix de la constante nous utiliserons SDLVideo.SDL_SRCCOLORKEY
, elle indique à SDL qu'il faut rendre une couleur transparente. Pour la couleur on l'indiquera avec la méthode mapRGP(int r, int g, int b)
.
Il faudra donc ajouter ce code avant la boucle principale (avant de bliter cela va de soit ;) ) :
// Affichage avec transparence
zack.setColorKey(SDLVideo.SDL_SRCCOLORKEY, zack.mapRGB(255, 0, 255));
Vous pouvez essayer ça fonctionne, mais il y a encore un autre moyen qui évite l'usage de setColorKey
: l'utilisation d'une image au format png, qui inclue un canal alpha !
C'est quoi un canal Alpha ?
Pour faire simple c'est une couleur de transparence, qui est généralement représentée par des damiers.
La transparence dans The Gimp.
Il faut donc que votre image contienne un canal alpha avec cette couleur (les damiers) et qu'elle soit au format png. Lorsque vous la chargerez, SDL comprendra tout de suite que cette image contient un canal alpha et l'appliquera automatiquement (merci SDL_image).
Voilà le résultat :
C'est bon cette fois-ci. :)
Je ne vous redonne pas tout le code, car il y a juste une méthode à ajouter avant la boucle while
, donc je pense que vous vous en sortirez sans problème.
Donner de la transparence à l'image
Nous allons voir comment donner de la transparence à une image avec la méthode setColorKey()
. Cette méthode prend deux paramètres qui sont :
une constante,
le taux de transparence, compris entre 0 et 255.
La constante sert à activer le mode Alpha, cela va en quelque sorte fondre l'image sur le fond d'écran, nous utiliserons donc pour cela SDLVideo.SDL_SRCCOLORKEY
. Sachez que si à la place de cette constante vous mettez 0, cela aura pour effet de ne pas activer la couleur Alpha. Pour ce qui est de la transparence, une valeur de 0 rendra votre image complètement transparente, une valeur de 255 la rendra complètement visible. Vous pouvez donc essayer ce code :
// Chargement d'une image et position
SDLSurface jim = SDLImage.load("images/jim.bmp");
jim.setColorKey(SDLVideo.SDL_SRCCOLORKEY, jim.mapRGB(255, 0, 255));
SDLRect jimPos = new SDLRect(120, 50);
// Gestion de la transparence
jim.setAlpha(SDLVideo.SDL_SRCALPHA, 15);
Commentons se code : jim est le nom de l'image et le nom de mon objet de type SDLSurface
. J'applique dans un premier temps la couleur de transparence de l'image avec jim.setColorKey(...);
, puis je définis une position sur la fenêtre. Ensuite j'applique un taux de transparence à mon image de 15 (on ne voit presque pas l'image).
Voilà quelques exemples :
Taux de transparence : 15
Taux de transparence : 80
Taux de transparence : 200
Voici le code qui a permis de réaliser ces captures d'écran :
import sdljava.SDLException;
import sdljava.SDLMain;
import sdljava.event.SDLEvent;
import sdljava.image.SDLImage;
import sdljava.video.SDLRect;
import sdljava.video.SDLSurface;
import sdljava.video.SDLVideo;
public class Alpha {
public static void main(String[] args) throws SDLException {
// Evenements 1/2
SDLEvent event = null;
boolean boucle = true;
// Initialisation de SDL et de l'affichage
SDLMain.init(SDLMain.SDL_INIT_VIDEO);
SDLVideo.wmSetCaption("Gestion de la transparence", null);
SDLSurface screen = SDLVideo.setVideoMode(320, 240, 32, SDLVideo.SDL_DOUBLEBUF | SDLVideo.SDL_HWSURFACE);
// Chargement d'une image et position
SDLSurface jim = SDLImage.load("images/jim.bmp");
jim.setColorKey(SDLVideo.SDL_SRCCOLORKEY, jim.mapRGB(255, 0, 255));
SDLRect jimPos = new SDLRect(120, 50);
// Gestion de la transparence
jim.setAlpha(SDLVideo.SDL_SRCALPHA, 15);
// Evénements 2/2
while (boucle)
{
event = SDLEvent.waitEvent();
if (event.getType() == SDLEvent.SDL_QUIT)
boucle = false;
screen.fillRect(screen.mapRGB(20, 150, 78));
jim.blitSurface(screen, jimPos);
screen.flip();
}
// Fin du programme
jim.freeSurface();
screen.freeSurface();
SDLMain.quit();
}
}
Cette partie est terminée, je vous avais dit que c'était court, mais avouez que vous avez appris plein de nouvelles choses non ?
On a enfin fini ! Vous êtes donc capables (rapidement normalement) de créer une petite application SDL qui affiche des formes et / ou des images.
La première partie est terminée. Faites une pause histoire de bien tout assimiler (le bourrage de crâne n'est pas une bonne solution ^^ ).