Introduction
On va voir dans cet article tout ce qui concerne les
fonctionnalités reliées aux animations 2D que possède notre bibliothèque
Libgdx.
Faire des animations est très pratique si on veut développer
un jeu. Une animation n’est que l’affichage d’un ensemble de textures (images
statiques) d’une manière séquentielle et à une certain vitesse, et cela pour
faire allusion à un mouvement.
Eléments
d’une animation 2D ?
Une animation va dépendre de trois caractéristiques :
- Nombre des images constituants une animation
- Le temps que va prendre une animation
- Le temps que prend chaque image et qu’on doit le calculer
à partir de la première et la deuxième caractéristique,
et qui va déterminer la vitesse d’affichage des images constituant l’animation
Les
utilisations d’une animation
Si on veut développer un simple jeu d’arcade, quatre à cinq
textures (images) suffiront par contre si on opte pour un jeu plus réaliste, on
aura besoins d’un nombre beaucoup plus de texture (images).
Il est préférable que toutes les images soient contenues
dans une seule texture (fichier) : spritesheet, car manipuler une
seule texture est plus optimisant pour le rendering.
Commet
faire une animation avec libgdx ?
Penchant, un petit peu sur le code source
* Pour faire une animation on doit utiliser la class Animation,
lors de l’instanciation de cette classe (dans la méthode create() ) deux paramètres
doivent être indiqués
1er Paramètre : c’est le temps (en seconde) que prend chaque image pour s’afficher dans le cadre d’une animation
Une petite astuce pour déterminer un temps convenable pour l’affichage de chaque image :
temps = temps Total
de l’animation / nombre d’image
Exemple : Je veux faire une animation qui se déroule pendant une seconde et cela à partir 5 images résultat
Le temps d’affichage de chaque image = 1/5 = 0.2
Bien sûr, ceci n’est pas toujours applicable, ça varie selon
le contexte.
2eme Paramètre c’est le tableau qui contient la suite des images qui vont être affichées dont le cadre d’une animation, les images doivent être de la même taille.
* Code source :
Animation
animation;
animation = new
Animation(temps, tableau_images);
Une fois l’animation instanciée dans la méthode create(), il
faut se diriger vers la méthode render() pour effectuer l’affichage de
l’animation, l’affichage s’effectue en
extrayant à chaque render une image à un instant précis et fixe , puis
l’afficher en utilisant le Spritebatch
* Pour récupérer l’image d’une animation à un instant
précis, la classe animation possède la méthode getKeyFrame qui possède deux
paramètres
1er paramètre : c’est l’instant de l’image à récupérer
2eme paramètre : c’est un boolean qui indique si l’animation est finie ou bien infinie.
*Code source :
temps
+= Gdx.graphics.getDeltaTime();
regionCourante = animation.getKeyFrame( temps, true);
batch.begin();
batch.draw(regionCourante, 100, 100);
batch.end();
Exemple 1
d’une animation
Voici un exemple d’une animation faite à partir d’un spritesheet
dédié pour un jeu d’arcade, elle est constituée de cinq images contiguës et de
même taille.
N’oubliez pas que la texture (spritesheet) doit avoir une résolution de 2x x 2y donc, il faut compléter l’image par le vide en utilisant un éditeur tel que : PAINT, ou encore GIMP
Encore une remarque, il faut aussi rendre le fond de la
texture transparent et ceci en utilisant l’éditeur GIMP par exemple
Voici à quoi ressemble une texture spritesheet prête à être charger dans une texture dans le cadre de notre exemple:
* Maintenant voici le code source de notre exemple vous
allez trouver des détails juste en dessous
package my.works.Article;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
public class AnimationExemple1 implements ApplicationListener{
private static final int nombre_image = 5;
private static final float duree_animation = 1f;
private static final int largeur_image = 58;
private static final int hauteur_image = 68;
private SpriteBatch batch;
private Texture sheetTexture;
private Animation animation;
private TextureRegion regionCourante;
private TextureRegion tabRegion[];
private float
temps;
@Override
public void create() {
// Initialisation
batch = new SpriteBatch();
sheetTexture = new Texture(Gdx.files.internal("sumoSheet.png"));
// #
<<1>>
TextureRegion[][] tmp = TextureRegion.split(sheetTexture, largeur_image, sheetTexture.getHeight());
tabRegion = new TextureRegion[nombre_image];
int index = 0;
// #
<<2>>
for(int j = 0; j < 5; j++) {
tabRegion[index++] =
tmp[0][j];
}
// # <<3>>
animation = new Animation(duree_animation/nombre_image, tabRegion);
temps=0.0f;
}
@Override
public void dispose() {
}
@Override
public void pause() {
}
@Override
public void render() {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
Gdx.gl.glClearColor(0, 0,
0, 0);
// #
<<4>>
temps += Gdx.graphics.getDeltaTime();
regionCourante = animation.getKeyFrame(temps, true);
// #
<<5>>
regionCourante.setRegion(regionCourante, 0, 0, largeur_image, hauteur_image);
// #
<<6>>
batch.begin();
batch.draw(regionCourante, 0, 0);
batch.end();
}
@Override
public void resize(int arg0, int arg1) {
}
@Override
public void resume() {
}
}
* Maintenant voici comment traiter le spritesheet à
travers le code source pour construire notre animation
<<1>> : Premièrement, on va découper la texture et mettre chaque image dans un tableau de texture cela est possible grâce à la méthode split() qui va deviser une texture en plusieurs régions de même hauteur et de même largeur (par forcément hauteur = largeur), la méthode split() prend les paramètre suivant :
1er paramètre : La texture qu’on va diviser
par régions
2eme paramètre : La largeur de chaque région
3eme paramètre : La hauteur de chaque région
<<2>> : On doit transformer le tableau de régions qui
contient les images constituants notre animation en un tableau d’une seule dimension.
<<3>> : ensuite, on instancié la classe Animation qui
prend deux paramètres
1er paramètre : Le temps que va prendre
chaque image constituant notre animation, et c’est là que vous pouvez utiliser l’astuce montrée précédemment pour
calculer ce temps.
2eme paramètre : Le tableau transformé dans
<<2>> et qui contient les images de l’animation
Puis, initialisation de la variable temps qui va être
utilisée dans la méthode render()
<<4>> :
à chaque rendu, on extrait une région du tableau à un instant précis
et cela pour l’afficher, ceci est faisable grâce à la méthode getKeyFrame() qui
nous retourne Une TextureResgion et qui a comme paramètre
1er paramètre : l’instant
de l’extraction de la région, meilleur façon de l’incrémenter est d’utiliser
l’écart du temps entre la précédente l’actuelle extraction, et a travers la
variable temps on peut manipuler la vitesse de notre animation.
2eme paramètre : est
booléen qui va déterminer si l’animation est infinie ou bien finie.
<<5>> : Ici
on précise la résolution de la région qu’on veut afficher
<<6>> :
La région est prête à être dessiné
* Voici résultat sous Desktop :
Bien sûr, il faut la classe lanceur pour lancer
l’application sous Desktop voir précédant tutoriel
* Voici le résultat sous Android :
Bien sûr, il faut la classe main pour lancer l’application
sous Android voir précédant tutoriel
Exemple 2
d’une animation
Dans le ce deuxième exemple on va réaliser une animation manipulée,
on va utiliser qui contient tous les déplacements d’un personnage de jeu RGP.
* Code source :
package my.works.Article;
import com.badlogic.gdx.Application.ApplicationType;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
public class AnimationExemple2 implements ApplicationListener{
private static final int nb_colone = 4;
private static final int nb_ligne = 8;
private static final int nombre_image_animation = 4;
private static final float duree_animation = 1f;
private float vitesse_lapin = 0.02f;
private SpriteBatch batch;
private Texture sheetTexture;
private Animation animationLapin[];
private TextureRegion regionCourante,regionInitial;
private int largeur_texture ;
private int hauteur_texture;
private float
temps;
private float xPosLapin;
private float yPosLapin;
private int type_animation;
private boolean animation_stop;
private int type_application;
@Override
public void create() {
// Type d'application
ApplicationType type = Gdx.app.getType();
type_application=
type.compareTo(ApplicationType.Desktop);
// Si Application Android Augmenter la
vitesse du lapin
if(type_application!=0)
vitesse_lapin*=10;
// Initialisation
batch = new SpriteBatch();
sheetTexture = new Texture(Gdx.files.internal("rabbitmanSheet.PNG"));
largeur_texture = sheetTexture.getWidth();
hauteur_texture = sheetTexture.getHeight();
animation_stop = false;
animationLapin = new Animation[8] ;
type_animation=0;
temps=0.0f;
// Construction du tableau d'images
constituants l'animation
TextureRegion[][] tmp = TextureRegion.split(sheetTexture, largeur_texture/nb_colone, hauteur_texture/nb_ligne);
regionInitial = tmp[0][1];
// Positionner le Lapin en milieu
xPosLapin= Gdx.graphics.getWidth()*0.5f;
yPosLapin= Gdx.graphics.getHeight()*0.5f;
// Instancier l'animation
for(int i=0;i<8;i++)
animationLapin[i] = new Animation(duree_animation/nombre_image_animation, tmp[i]);
}
@Override
public void dispose() {
}
@Override
public void pause() {
}
@Override
public void render() {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
Gdx.gl.glClearColor(0,0.5f,0.2f,0);
// Fixer lapin
if(!animation_stop) // si aucune
manipulation en cours
{
temps += Gdx.graphics.getDeltaTime();
regionCourante = animationLapin[type_animation].getKeyFrame(temps/1, true);
}
// Dessiner Lapin
batch.begin();
batch.draw(regionCourante, xPosLapin, yPosLapin);
batch.end();
// Manipuler Lapin
if(type_application == 0) // application Desktop
ManipulerLapin_clavier();
if(type_application == -1) // application Android
ManipulerLapin_accelerometre();
}
@Override
public void resize(int arg0, int arg1) {
}
@Override
public void resume() {
}
//*********************** manipulation entrées accéléromètre******************************//
private void
ManipulerLapin_accelerometre() // => destinée Android
{
// Les directions
principales
if(Gdx.input.getAccelerometerY()>1)
{
xPosLapin+=vitesse_lapin;
type_animation=7;
}
if(Gdx.input.getAccelerometerY()<-1)
{
xPosLapin-=vitesse_lapin;
type_animation=3;
}
if(Gdx.input.getAccelerometerX()>1)
{
yPosLapin-=vitesse_lapin;
type_animation=0;
}
if(Gdx.input.getAccelerometerX()<-1)
{
yPosLapin+=vitesse_lapin;
type_animation=4;
}
// La direction
initial du Lapin
if(Gdx.input.getAccelerometerX()<1
&& Gdx.input.getAccelerometerY()<1 && Gdx.input.getAccelerometerX()>-1
&& Gdx.input.getAccelerometerY()>-1 )
{
animation_stop = true;
regionCourante = regionInitial ;
}else
{
animation_stop = false;
}
}
//****************** Manipulation entrées accéléromètre***********************************//
private void
ManipulerLapin_clavier() // => Destinée pour Desktop
{
// Les directions
principales
if(Gdx.input.isKeyPressed(Keys.UP))
{
yPosLapin+=vitesse_lapin;
type_animation=4;
}
if(Gdx.input.isKeyPressed(Keys.DOWN))
{
yPosLapin-=vitesse_lapin;
type_animation=0;
}
if(Gdx.input.isKeyPressed(Keys.RIGHT) )
{
xPosLapin+=vitesse_lapin;
type_animation=7;
}
if(Gdx.input.isKeyPressed(Keys.LEFT) )
{
xPosLapin-=vitesse_lapin;
type_animation=3;
}
// Les directions secondaires
if(Gdx.input.isKeyPressed(Keys.UP) && Gdx.input.isKeyPressed(Keys.RIGHT) )
{
yPosLapin+=vitesse_lapin*0.5f;
xPosLapin+=vitesse_lapin*0.5f;
type_animation=2;
}
if(Gdx.input.isKeyPressed(Keys.UP) && Gdx.input.isKeyPressed(Keys.LEFT))
{
yPosLapin+=vitesse_lapin*0.5f;
xPosLapin-=vitesse_lapin*0.5f;
type_animation=6;
}
if(Gdx.input.isKeyPressed(Keys.DOWN) && Gdx.input.isKeyPressed(Keys.RIGHT))
{
yPosLapin-=vitesse_lapin*0.5f;
xPosLapin+=vitesse_lapin*0.5f;
type_animation=5;
}
if(Gdx.input.isKeyPressed(Keys.DOWN) && Gdx.input.isKeyPressed(Keys.LEFT))
{
yPosLapin-=vitesse_lapin*0.5f;
xPosLapin-=vitesse_lapin*0.5f;
type_animation=1;
}
// La direction
initial du Lapin
if(!Gdx.input.isKeyPressed(Keys.ANY_KEY))
{
regionCourante = regionInitial;
animation_stop=true;
}
else
animation_stop=false;
}
}
* Voici résultat sous Desktop :
Bien sûr, il faut la classe lanceur pour lancer
l’application sous Desktop voir précédant tutoriel
* Voici le résultat sous Android :
Bien sûr, il faut la classe main pour lancer l’application
sous Android voir précédant tutoriel
Conclusion
Ainsi s’achève le tutoriel de l’animation avec Libgdx,
sachez qu’il existe d’autre façon de faire une animation, mais utiliser la
classe Animation est le plus pratique des moyens.
Si vous avez des remarques ou des questions
n’hésitez pas à les poster en commentaire. Merci pour votre lecture.
i need the rabbitmanSheet.PNG
RépondreSupprimerHi, dewill
Supprimerjust refresh, and you will find the link down below
good luck
Thank you very much.
RépondreSupprimerI need it so much and happy to learn from you too.
Thks
RépondreSupprimer