Introduction
Libgdx possède une camera 2d qu’on peut
facilement la manipuler pour l’utiliser dans des jeux et même des applications.
La caméra 2d fournissent plusieurs fonctionnalité on va voir quelques une dans
ce tutoriel
Pour quoi une caméra ?
Une Caméra parce qu’on peut la manipuler comme
une vrai camera c’est ç dire la faire bouger dans toutes directions et aussi
‘effectuer des rotations et de zoomer et dézoomer.
Besoin d’une camera
L’utilisation d’une caméra est très pratique
pour la réalisation d’un jeu ou bien une application dont celle-ci a besoin de
la fonctionnalité du zoom, exemple : Une application qui vous permet de
visualiser des photos et de faire un zoom sur ces photos, Un jeu RPG qui
possède une grande carte qu’on peut se déplacer là-dedans.
Opérations
principales
-
Bouger la camera
-
Zoomer et dézoomer
-
Rotation
Othographic camera
* Initialiser position de la camera
camera = new OrthographicCamera(largeur_Ecran,hauteur_Ecran);
camera.position.set(largeur_Ecran*0.5f, hauteur_Ecran*0.5f, 0);
* pour qu’on puisse prendre en
considération la modification sur camera
camera.update();
* pour lier la camera au spriteBatch.
batch.setProjectionMatrix(camera.combined);
* Définir le cadre de la camera :
GL10 gl = Gdx.graphics.getGL10();
gl.glViewport(0,0,largeur_Ecran,hauteur_Ecran);
camera.apply(gl);
* Déplacer la camera
Vers le haut :
camera.translate(0, +1);
Ou aussi :
camera.position.y-- ;
Vers le bas :
camera.translate(0, -1);
Ou aussi :
camera.position.y-- ;
Vers la
droite :
camera.translate(1, 0);
Ou aussi :
camera.position.x++ ;
Vers gauche :
camera.translate(-1, 0);
Ou aussi :
camera.position.x-- ;
* Zoom camera :
En avant :
camera.zoom-=0.1f;
En arrière :
camera.zoom-=0.1f;
* Rotation camera :
Vers la droite :
camera.rotate(-0.05f);
vers la gauche :
camera.rotate(0.05f);
Exemple pratique
Dans cet exemple on va manipuler une caméra
en la déplaçant dans tous les sens, faire des rotations, zoomer sur l’écran.
J’ai choisi une carte qui représente un
terrain d’un jeu pour effectuer l’exemple. ici pour télécharger la carte
Manipulation de la camera :
Pour manipuler la camera sous le Desktop
on utilise le clavier : les touches haut, bas, droite, gauche, pour bouger
la camera dans tous les sens et la touche ‘z’ et la touche ‘e’ pour zoomer en
avant et en arrière.
Pour manipuler la camera sous Android on
utilise les gestes tactiles tels que le pinch, zoom, pan … pour implémenter ces
gestes on fait appel au listener GestureListener qui peut détecter ces
gestes (voir tutoriel précédant).
Ou encore on peut l’implémenter nous-même
grâce à la classe InputListener par exemple le zoom c’est deux doigt qui
se rapproche l’un deux l’autre donc pour détecter un tel geste on calcule la distance
entre les coordonnés du premier doigt et les coordonnés du deuxième doigt.
D = (x0 – x1)2 + (y0-y1)2
Puis on compare ce résultat avec la prochaine
distance calculée
* Voici le code source nous permettons
d’effectuer quelques fonctionnalités de la camera 2D Libgdx
package my.works.Article;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
public class CameraExemple1 implements ApplicationListener{
public static float vitesse_zoom = 0.02f;
public static float vitesse_deplacement_camera = 2;
public static float max_zoom = 1f; // maximum qu'on peut zoomer
public static float min_zoom = 0.5f; // minimum qu'on peut zoomer
private int limite_image_maxHauteur ; // limite déplacement camera
private int limite_image_maxLargeur ; // limite déplacement camera
public static int limite_image_minHauteur = 0; // limite déplacement camera
public static int limite_image_minLargeur = 0 ; // limite déplacement camera
private int largeur_Ecran ;
private int hauteur_Ecran ;
private SpriteBatch batch;
private Texture mapTexture;
private OrthographicCamera camera;
int x0,y0,x1,y1; // position du premier et deuxième doigt
int lastx0 ; // précédente position du 1er doigt
int lasty0 ; // précédente position du 1er doigt
int lastx1 ; // précédente position du 2eme doigt posé
sur l'écran
int lasty1 ; // précédente position du 2eme doigt posé
sur l'écran
@Override
public void create() {
largeur_Ecran = Gdx.graphics.getWidth();
hauteur_Ecran = Gdx.graphics.getHeight();
batch = new SpriteBatch();
mapTexture = new Texture(Gdx.files.internal("map.png"));
camera = new OrthographicCamera(largeur_Ecran,hauteur_Ecran);
camera.position.set(largeur_Ecran*0.5f, hauteur_Ecran*0.5f, 0);
camera.update();
limite_image_maxHauteur = mapTexture.getHeight() /2;
limite_image_maxLargeur = mapTexture.getWidth() /2;
limite_image_minHauteur = hauteur_Ecran/2;
limite_image_minLargeur = largeur_Ecran/2;
}
@Override
public void dispose() {
}
@Override
public void pause() {
}
@Override
public void render() {
GL10 gl = Gdx.graphics.getGL10();
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glViewport(0,0,largeur_Ecran,hauteur_Ecran);
camera.apply(gl);
camera.update();
manipulerCameraDesktop();
manipulerCameraAndroid();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(mapTexture, 0, 0);
batch.end();
}
@Override
public void resize(int arg0, int arg1) {
}
@Override
public void resume() {
}
//*********************** Manipuler la
camera*******************************//
public void manipulerCameraDesktop()
{
if(Gdx.input.isKeyPressed(Keys.UP)) // si on appuie sur la touche haut
{
if(camera.position.y<limite_image_maxHauteur) // limiter
déplacement vers haut
camera.translate(0, +1);
}
if(Gdx.input.isKeyPressed(Keys.DOWN)) // si on appuie sur la touche bas
{
if(camera.position.y>limite_image_minHauteur) // limiter déplacement vers bas
camera.position.y--;
}
if(Gdx.input.isKeyPressed(Keys.RIGHT)) // si on appuie sur la touche droite
{
if(camera.position.x<limite_image_maxLargeur) // limiter déplacement vers droite
camera.position.x++;
}
if(Gdx.input.isKeyPressed(Keys.LEFT)) // si on appuie sur
la touche gauche
{
if(camera.position.x>limite_image_minLargeur) // limiter déplacement vers gauche
camera.position.x--;
}
if(Gdx.input.isKeyPressed(Keys.Z)) // si on appuie sur la touche Z
{
if(camera.zoom<max_zoom) // limiter le zoom arrière
camera.zoom+=vitesse_zoom;
}
if(Gdx.input.isKeyPressed(Keys.E))// si on appuie sur
la touche E
{
if(camera.zoom>min_zoom) // limiter le zoom avant
camera.zoom-=vitesse_zoom;
}
if(Gdx.input.isKeyPressed(Keys.R))// si on appuie sur
la touche R
{
camera.rotate(0.05f); // rotation vers la gauche
}
if(Gdx.input.isKeyPressed(Keys.A))// si on appuie sur
la touche A
{
camera.rotate(-0.05f); // rotation vers la droite
}
if(Gdx.input.isKeyPressed(Keys.M))// si on appuie sur
la touche M
{
if(camera.viewportWidth<1024)
camera.viewportWidth++;
}
if(Gdx.input.isKeyPressed(Keys.K))// si on appuie sur
la touche K
{
if(camera.viewportWidth>320)
camera.viewportWidth--;
}
if(Gdx.input.isKeyPressed(Keys.O))// si on appuie sur
la touche O
{
if(camera.viewportHeight<512)
camera.viewportHeight++;
}
if(Gdx.input.isKeyPressed(Keys.L))// si on appuie sur
la touche L
{
if(camera.viewportHeight>320)
camera.viewportHeight--;
}
}
public void
manipulerCameraAndroid()
{
Gdx.input.setInputProcessor(new InputProcessor() {
@Override
public boolean touchUp(int x, int y, int pointer, int bouton) {
return false;
}
@Override
public boolean touchDown(int x, int y, int pointer, int bouton) {
return false;
}
@Override
public boolean touchDragged(int x, int y, int pointer) {
// **************
Saisir les coordonnées actuelles ********************/
if(pointer==1) // Pour le 2eme
doigt
{
x1=x;
y1=y;
}
if(pointer==0) // Pour le 1er
doigt
{
x0=x;
y0=y;
}
/***********
Opération : Zoom sur carte *******************************/
if(Gdx.input.isTouched(1)) // si deux doigt
sont posés sur l'écran {
// Comparer entre
la distance actuelle (entre les 2 doigts) et la distance précédente
if(Math.pow(x0-x1,2)+Math.pow(y0-y1,2)>Math.pow(lastx0-lastx1,2)+Math.pow(lasty0-lasty1,2))
{
if(camera.zoom>min_zoom) // limite du zoom avant
camera.zoom-=vitesse_zoom;
}
else
{
if(camera.zoom<max_zoom) // limite du zoom arrière
camera.zoom+=vitesse_zoom;
}
}
/**********
Operation : Déplacer camera avec un doigt ******************/
if(!Gdx.input.isTouched(1)) // si un seul doigt est posé sur l'écran
{
// les quatres
directions principales :
//-------------------------------------
if(y0-lasty0>0 && x0-lastx0<5 && x0-lastx0>-5 )
//
si drag vers haut avec tolérance sur x
{
if(camera.position.y<limite_image_maxHauteur) // limite de la
camera
{
camera.translate(0, vitesse_deplacement_camera);
}
}
else
{
if(y0-lasty0<0 && x0-lastx0<5 && x0-lastx0>-5)
//
Si drag vers bas
{
if(camera.position.y>limite_image_minHauteur) // Limite de la
camera en bas
{
camera.translate(0, -vitesse_deplacement_camera);
}
}
}
if(x0-lastx0<0 && y0-lasty0>-5 && y0-lasty0<5) // Si drag vers droite
{
if(camera.position.x<limite_image_maxLargeur) // Limite de la
camera a droite
{
camera.translate(vitesse_deplacement_camera, 0);
}
}
else
{
if(x0-lastx0>0 && y0-lasty0>-5 && y0-lasty0<5) // Si drag vers gauche
{
if(camera.position.x>limite_image_minLargeur) // Limite de la camera à gauche
{
camera.translate(-vitesse_deplacement_camera, 0);
}
}
}
}
// *********
Sauvgarder les coordonnées ****************************/
if(pointer==1) // 2eme doigt
{
lastx1 = x1;
lasty1 = y1;
}
if(pointer==0)// 1er doigt
{
lastx0 = x0;
lasty0 = y0;
}
return false;
}
@Override
public boolean scrolled(int arg0) {
// TODO Auto-generated
method stub
return false;
}
@Override
public boolean mouseMoved(int arg0, int arg1) {
// TODO Auto-generated
method stub
return false;
}
@Override
public boolean keyUp(int arg0) {
// TODO Auto-generated
method stub
return false;
}
@Override
public boolean keyTyped(char arg0) {
// TODO Auto-generated
method stub
return false;
}
@Override
public boolean keyDown(int arg0) {
// TODO Auto-generated
method stub
return false;
}
});
}
}
* Voici le résultat sous desktop
Bien sûr, il faut la classe lanceur pour lancer l’application sous Desktop voir précédant tutoriel
Conclusion
La camera est très pratique est son
utilisation ne se limite pas aux exemples vus dans ce tutoriel. Si vous avez
des remarques ou des questions n’hésitez pas à les poster en commentaire. Merci
pour votre lecture.
Un grand merci pour tout le mal que tu te donnes pour nous faire des tutoriels toujours aussi excellents.
RépondreSupprimerTu es le seul proposant des tuto en langue française ! Libgdx est déjà un challenge pour le novice que je suis mais devoir se dépatouiller avec des tuto anglais c'est mission impossible, heureusement tu es la ;)
Encore merci, j’attends la suite avec impatience XD
tout le plaisir est pour moi !
RépondreSupprimerUne idée me viens, pourquoi ne crées-tu pas un forum ? Ce serrai intéressant de pouvoir partager nos expériences avec Libgdx, de créer une communauté francophone (il n'en existe pas encore à ma connaissance).
RépondreSupprimerbonjour , je veux vous dire d'abord merci pour ce blog qui m'aide vraiment beaucoup !
RépondreSupprimerje voudrais vous poser une question : si mon jeux comporte une grande carte et que je veux l'afficher au fur et a mesure que le personnage avance vers le haut , comment dois je faire , est ce en utilisant le camera , et si oui , comment ?
merci d'avance !
Ouais tu peux utiliser cette camera. Par exemple lorsque tu décides que ton personnage peut avancer vers le haut, tu peux faire:
SupprimeryPosPerso+=vitesse_perso;
positionYPixel+=vitesse_perso;
if(camera.position.y<limite_image_maxHauteur)
camera.translate(0, +vitesse_perso);
Bonjour, merci d'abord pour ces tutoriels qui m'ont beaucoup appris.
RépondreSupprimerJ'ai également une question à propos du système de caméra : j'aimerai savoir si il est possible de dissocier les coordonnées en x et y du jeu à celle de windows. Je m'explique : quand je clique sur une image dans ma fenêtre de jeu, je peut récupérer une coordoonées en x et y, cependant si je réalise un zoom ou une translation de caméra mon objet va changer de position par rapport à l'écran et quand je voudrai récupérer ses coordonnées à l'aide d'un clique elles seront différentes de celle initiale. Savez-vous comment éviter ce problème? Merci d'avance .
Bonjour ;
SupprimerJ'ai bien compris votre problème en attendant a ce que je fasse un petit tuto là-dessus je vous explique rapidement comment moi je fais les choses
Quand on zoom dans un écran sur un objet ça position change le principe ici c’est de convertir cette position avec une formule mathématique pour qu’elle reste toujours la même position première (la position avec non zoom [camera.zoom =1]).
Par exemple les coordonné d’un objet placé dans un écran est x= 200 y = 300 quand on zoom de x2 l’écran (camera.zoom =2 )ça position devient (par exemple )x= 400 y = 500
Le principe c’est de mettre en considération que 400 et 500 de zoom x2 sont respectivement 200 et 300 de zoom x1 et cela on le convertant
200= XFromule (400) plus générale ( xPosition non zoom ) = xFormule ( xPosition avec zoom)
Voici les formules que j’utilise
public float xzunit(float x)
{
float resultat = 0;
if(x<largeur_ecran * 0.5f)
resultat= (int) ((x - (largeur_ecran - largeur_ecran/camera.zoom))*0.5f)*camera.zoom);
else
resultat= (int) (((x-largeur_ecran+ ((largeur_ecran-(largeur_ecran/camera.zoom))*0.5f))*camera.zoom)+largeur_ecran);
return resultat;
}
public float yzunit(float y)
{
float resultat = 0;
if(y<hauteur_ecran * 0.5f)
resultat= (int) ((y - (hauteur_ecran - (hauteur_ecran/camera.zoom))*0.5f)*camera.zoom);
else
resultat= (int) (((y-hauteur_ecran+ ((hauteur_ecran-(hauteur_ecran/camera.zoom))*0.5f))*camera.zoom)+hauteur_ecran);
return resultat;
}
Vous n’avez qu’ à utiliser ses deux fonction
X = Xzunit (x) ;
Y = Yzunit (z) ;
Attention ceci marche que pour le zoom par rapport au centre de l’écran
N’hésitez pas si vous avez plus de question
Bonne continuation
Merci beaucoup pour cette réponse ! J'avais trouvé une solution similaire pour la translation de caméra mais je n'avais pas pensé à cela pour le zoom. Merci encore !
SupprimerTu ne fais plus de tutoriels ? ._.
RépondreSupprimerPourrais tu en faire un sur le module audio ? =)
Sinon, merci, vraiment du bon boulot ;)