déc
29
2010

[Tutoriel AndEngine] Partie 5 – Arrête ton char !

Bonsoir à tous, nous n’allons pas parler du film Ben-Hur malgré le titre en concordance avec cette expression, mais comment faire bouger un char d’assaut dans une scène :biggrin:

Tout d’abord nous allons apprendre à séparer notre scène de l’activité principale pour plus de propreté, nous continuerons en ajoutant un contrôle analogique fournit par l’andengine (oui oui ça existe !) et pour terminer nous allons faire bouger notre petit char (la classe non ?).

Comme d’habitude on commence par créer notre projet, puis à définir les propriétés de notre activité, comme ceci :

public class MonActivite extends BaseGameActivity {

	public static Camera camera;

	public final static int CAMERA_LARGEUR = 480;
	public final static int CAMERA_HAUTEUR = 320;

	@Override
	public Engine onLoadEngine() {
		// Initialisation de la caméra
		camera = new Camera(0, 0, CAMERA_LARGEUR, CAMERA_HAUTEUR);

		// Retourne le moteur de jeu
		return new Engine(new EngineOptions(true,
			ScreenOrientation.LANDSCAPE,
			new RatioResolutionPolicy(CAMERA_LARGEUR, CAMERA_HAUTEUR),
		camera));
	}

	@Override
	public void onLoadResources() {

	}

	@Override
	public Scene onLoadScene() {

	}

	@Override
	public void onLoadComplete() {

	}

}

Puis nous allons créer notre propre classe héritant de scène pour pouvoir travailler dedans et nous permettre de rendre notre code plus propre, vous remarquerez que setBackground, qui permettra de d’afficher une couleur verte en arrière plan (j’aime la pelouse sous les roues d’un char pas vous ?) :whistle:

public class SceneJeu extends Scene {

	/**
	* Constructeur
	*
	* @param pLayerCount
	*/

	public SceneJeu() {
		super();
		setBackground(new ColorBackground(0.52f, 0.75f, 0.03f));
	}

}

Voilà nous avons notre scène séparée de notre activité, nous allons donc l’ajouter à notre activité pour la charger

// Déclaration de la scéne du jeu
private SceneJeu maScene;

Puis dans le onLoadEngine(…)

// Initialisation de la scéne du jeu
maScene = new SceneJeu();

Et pour finir dans le onLoadScene()

@Override
public Scene onLoadScene() {
	// Retourne la scéne
	return maScene;
}

Nous allons maintenant créer une classe Tank héritant de Sprite

public class Tank extends Sprite{

	public Tank(float pX, float pY, float pWidth, float pHeight,TextureRegion pTextureRegion) {
		super(pX, pY, pWidth, pHeight, pTextureRegion);
	}

}

Jusque la rien d’insurmontable, mais nous avons tout ce qu’il faut pour commencer à travailler, c’est moi qui vous le dit !

Prenons une belle photo d’un char d’assaut futuriste

Char d'assaut

Rajoutez le dans le dossier gfx, puis déclarons celui-ci dans notre scène

// Texture du tank
private BitmapTextureAtlas texture;
private TextureRegion textureRegionTank;

Petit soucis dans une scène nous n’avons pas accès au contexte ni au moteur pour charger les textures ! Hé bien feintons en rajoutant une méthode à notre scène nommée LoadResources avec 2 paramètres (Engine et Context)

/**
 * Chargement des resources
 *
 * @param engine
 * @param context
 */
public void LoadResources(final Engine engine, Context context) {
	// Chargement des textures du tank
	texture = new BitmapTextureAtlas(128, 256);
	textureRegionTank = BitmapTextureAtlasTextureRegionFactory.createFromAsset(texture, context, "gfx/tank.png", 0, 0);

        // Chargement des textures dans le texture manager
        engine.getTextureManager().loadTextures(texture);

        // Lance l'initialisation de la scéne
        init();
}

Et pour finir dans notre activité puis dans la méthode onLoadResources appelons notre petite méthode

@Override
public void onLoadResources() {
	// Chargement des textures de la scéne
	maScene.LoadResources(getEngine(), this);
}

Voilà notre tank texture est chargée en mémoire, plus qu’a l’afficher, pour cela nous allons rajouter la méthode init() à notre classe Scène

/**
 * Initialisation de la scéne
 */
private void init() {
	// Initialisation de notre tank
	tank = new Tank(0, 0, textureRegionTank.getWidth(), textureRegionTank.getHeight(), textureRegionTank);
	// Redimensionne notre tank
	tank.setScale(0.5f);

	// Ajout de notre tank à la scéne
	attachChild(tank);
}

Si nous lançons l’application vous verrez notre cher petit char d’assaut, super mais il bouge pas on va pas aller bien loin avec ça ! Qu’à cela ne tienne, on va arranger ce petit soucis.

L’équipe de développement d’AndEngine à tout prévu en ajoutant un contrôle analogique dans le moteur de jeu, nous allons le rajouter pour pouvoir travailler avec.
Commençons par télécharger les deux images du contrôle et plaçons les dans le répertoire GFX

Continuons en déclarant les textures dans notre scène

// Textures des contrôles pour se déplacer
private BitmapTextureAtlas mOnScreenControlTexture;
private TextureRegion mOnScreenControlBaseTextureRegion;
private TextureRegion mOnScreenControlKnobTextureRegion;

Puis dans notre LoadResouces

// Chargement des textures du contrôle analogique
mOnScreenControlTexture = new BitmapTextureAtlas(256, 128, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
mOnScreenControlBaseTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mOnScreenControlTexture, context, "gfx/onscreen_control_base.png", 0, 0);
mOnScreenControlKnobTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mOnScreenControlTexture, context, "gfx/onscreen_control_knob.png", 128, 0);

// Chargement des textures dans le texture manager
engine.getTextureManager().loadTextures(texture,mOnScreenControlTexture);

Nous avons chargé nos images en mémoire, y’a plus qu’a définir notre contrôle analogique

// Controle analogique
private AnalogOnScreenControl analogOnScreenControl;

Et pour finir dans notre méthode init

// Initialisation du controle analogique
analogOnScreenControl = new AnalogOnScreenControl(0,
	MonActivite.CAMERA_HAUTEUR - mOnScreenControlBaseTextureRegion.getHeight(),
	MonActivite.camera,
	mOnScreenControlBaseTextureRegion,
	mOnScreenControlKnobTextureRegion,
	0.1f,
	200,
	this);

// Spécifie que le contrôle analogie sera transparent
analogOnScreenControl.getControlBase().setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
// Valeur de la transparence
analogOnScreenControl.getControlBase().setAlpha(0.5f);
// Taille du centre
analogOnScreenControl.getControlBase().setScaleCenter(0, 128);
// Redimensionnement de la base du controle
analogOnScreenControl.getControlBase().setScale(0.5f);
// Redimensionnement du joystick
analogOnScreenControl.getControlKnob().setScale(0.5f);
// Rafraichit le controle
analogOnScreenControl.refreshControlKnobPosition();

// Ajout du controle à la scéne enfant
setChildScene(analogOnScreenControl);

Je n’explique pas plus, tout est dans les commentaire du code, passons à la gestion du déplacement du joystick, pour cela nous rajoutons l’interface à notre classe

public class SceneJeu extends Scene implements IAnalogOnScreenControlListener

Eclipse vous propose alors d’ajouter automatiquement les méthodes manquantes, faites le vous verrez ces deux méthodes supplémentaires :

@Override
public void onControlChange(BaseOnScreenControl pBaseOnScreenControl,float pValueX, float pValueY) {

}

@Override
public void onControlClick(AnalogOnScreenControl pAnalogOnScreenControl) {

}

La première permet de savoir la position du joystick
La deuxième si l’on clique dessus

Nous allons nous intéresser uniquement à la première, après je vous laisserais faire ce que vous voulez de la deuxième :happy:

@Override
public void onControlChange(BaseOnScreenControl pBaseOnScreenControl,float pValueX, float pValueY) {
	// Lorsque l'on bouge notre joystick le tank se déplace
	tank.setPosition( tank.getX() + (pValueX * 5), tank.getY() + (pValueY * 5));	

	// Fait pivote notre tank selon la direction du joystick
	if(pValueX != 0 && pValueY != 0)
		tank.setRotation(MathUtils.radToDeg((float)Math.atan2(pValueX, -pValueY)));
}

Quand nous allons bouger notre joystick le tank va se déplacer, puis il va pivoter selon l’orientation du joystick.

Vous avez plus qu’a faire un petit jeu avec tout ça non ?

Ça roule

Bon allez je vous dit à la prochaine pour un nouveau tutoriel (on va faire tirer notre tank !)

Lien vers les sources : Sources de la formation

  • http://SiteWeb Alex R

    Enfin du nouveau, ça fait plaisir. Je n’ai plus tellement besoin de ces cours puisque j’utilise pas mal la bibliothèque à présent et que je vais bien plus loin que les notions ici abordées (mais c’est grâce à tes 3 premiers tuto que je me suis lancé :p). Cependant, ça reste un plaisir de te lire, continue comme ça :)

    (Petit soucis d’email dans le commentaire d’avant)

  • http://www.ace-art.fr/wordpress/ Pierre-Emmanuel Mercier

    Merci à toi, je vais surement préparer un tutoriel qui met en scène un jeu simple mais complet, tu es le bien venu si tu veux participer à sa rédaction et son élaboration ;)

  • http://SiteWeb Deedo

    Salut,

    J’ai un petit souci sur ce tuto :smile:
    Si on prend la dernière version de andengine.jar via ton lien dans le premier tuto sur cette librairie, on se retrouve avec des erreurs au niveau des instructions

    getTopLayer().addEntity(tank);

    et

    tank.setVelocity(pValueX * 100, pValueY * 100);

    Eclipse me dit que getToplayer() est deprecated et que addEntity() et setVelocity() n’existent pas :getlost: j’ai bidouillé et remplacé par

    getLastChild().attachChild(tank);

    et

    VelocityInitializer velocity = new VelocityInitializer(pValueX * 100, pValueY * 100);
    velocity.onInitializeParticle(tank);

    Ca semble marcher. Vu que la méthode est deprecated je pense que le tuto a utilisé une version de la librairie moins récente non? Ou alors j’y comprend rien xD

  • http://SiteWeb Deedo

    Et j’ai oublié de dire que du coup, la classe tank héritait de Particle…
    Etant débutant dans le dév Android, je ne sais pas trop si c’est une bonne méthode ou pas ^^”

  • http://www.ace-art.fr/wordpress/ Pierre-Emmanuel Mercier

    Effectivement j’ai utilisé une ancienne version d’Andengine, je mettrais à jour le tutoriel dans les prochain jour avec la nouvelle version.

  • http://SiteWeb Deedo

    Oki ^^
    Et merci encore pour ces petits tutos, j’attends avec impatience celui du jeu complet :smile:

  • http://SiteWeb FYE

    Salut,
    tout d’abord merci beaucoup pour ces tutos, qui me motivent à continuer sur Andengine.

    Le problème c’est que je ne trouve pas d’autres tutos (meme en anglais), et aucune documentation pour le Andengine, donc j’aimerais savoir comment toi tu as fait pour apprendre a t’en servir?

  • http://www.ace-art.fr/wordpress/ Pierre-Emmanuel Mercier

    En lisant le code source des exemples de andengine :)

  • http://SiteWeb Alex R.

    En effet, comme le dit l’auteur d’Andengine, il n’existe aucune doc mais une foule d’exemples et une communauté toujours prête à aider sur le forum d’AndEngine.

  • http://SiteWeb FYE

    OK merci!

    En tous cas j’attends la suite avec impatience!

  • http://SiteWeb abc

    Il y a une petite coquille sur la rotation apportée au tank: c’est tank.setRotation(MathUtils.radToDeg((float)Math.atan2(-pValueX, pValueY)));
    (il faut inverser les signes de pValueX et pValueY)

  • http://www.benjamincornec.fr Siin

    Pour la classe Tank, il y a une erreur chez moi.
    Il manque la classe setVelocity, je pense que c’est pas la même librairie c’est pour ça.
    Du coup j’ai rajouté cette méthode et cela marche très bien :

    public void setVelocity(float pX,float pY){
    this.mX+=pX;
    this.mY+=pY;
    }

  • http://SiteWeb Tagadac

    Salut! Déjà merci beaucoup pour ce tuto qui m’a beaucoup aidé! Mais j’aurais une petite question. Comment faire pour afficher les valeurs de pValuex et de pValueY?
    Dans MonActivite j’ai mis des lignes de codes qui me permettent d’afficher du texte, mais ça fait 2 jours que je cherche comment récupérer ces valeurs…

    Y a t-il un moyen?

    Merci d’avance!

  • http://SiteWeb david

    et pour le physique SVP ?
    et collision ?

  • http://Aucun Batlac

    Salut,
    Je suis très interrresé par tes tutos sur Andengine et je voudrais
    savoir si tu vas continuer a en faire sur andengine ?

    Merci d’avance et bonne contnuation !

  • http://www.ace-art.fr/wordpress/ Pierre-Emmanuel Mercier

    Merci Batlac, je pense continuer mais pour le moment j’ai peu de temps à consacrer a AndEngine.

  • http://www.facebook.com/julien.bertozzi Julien Bertozzi

    Merci pour tes tutos, c’est dur d’en trouver sur andengine :)
    Pour les interessés, Travis s’y attaque allez voir sur mybringback

  • http://www.ace-art.fr/wordpress Acesyde

    Le problème principal d’AndEngine c’est que les concepteurs changent les API à tout bout de champ.

  • http://www.facebook.com/julien.bertozzi Julien Bertozzi

    Est-ce qu’il existe un autre moteur sympathique alors ?

  • http://www.ace-art.fr/wordpress Acesyde

    Oui LibGDX, après il demande plus de dev il possède moins de fonctions pré-faites, mais il est plus rapide et moins consommateur.