Post on 13-Dec-2014
description
Développement jeux
Android
Retour d’expérience
Lead developper plateforme
cloud mobile chez Sage
Développeur de
Space Corsair
• Introduction au développement mobile
• Comment développer son premier jeu
• Monétiser son projet
• Conseils pour réussir sa sortie
Plan de la présentation
Statistiques sur le jeu vidéo mobile
• Un marché estimé à 22 Milliards de $ en 2015
• 80% des revenus mobile viennent des jeux
• En 2012, les 25 premiers développeurs prennent à eux
seuls 50% des revenus.
• Dépense moyenne de 21$ par joueur en 2011
• 80 % des développeurs mobile ne gagnent pas assez
pour en faire une activité principale.
Pourquoi développer son jeu?
• Apprendre, développer ses compétences
• Ajouter une expérience sur son CV
• Revenus complémentaires
• S’évader des contraintes de son emploi principal
• Sortie sur le marché d’un vrai produit ( préparation
marketing, publicité)
Dur développer un jeu?
On peut faire un jeu à succès en utilisant uniquement les
composants d’une application Android non ludique
(quizz , jeu de gestion).
La complexité dépend du type de jeu et de son
expérience en développement, l’important c’est de
choisir un projet à sa portée.
Différents types de jeux mobiles
• 3D / simulation (Asphalt)
• 2D / action rpg ( Space corsair)
• Réflexion / physique (angry birds, cut the rope)
• 2D scrolling ( jetpack joyride)
• Gestion / action (Clash of clan, tower defense)
• Puzzle games (candy crush)
• Cartes / casino
• Mix de tout ça et autres ...
Réalisation du projet
Je suis motivé, j'ai du temps, je souhaite me lancer dans
la réalisation d’un jeu mobile ...
Comment faire ?
Trouver une idée
Originale ...
• Avoir un concept de base amusant et ajouter des éléments autour
… ou inspirée
• Reprendre un concept existant (vieux jeu pc, jeu d’une autre
plateforme, actualité, ...)
=> Dans tous les cas, choisir un élément démarquant.
Exemple de flappy bird :
• Gameplay limité, concept très classique, son élément démarquant est
une difficulté exagérément haute.
Trouver une idée
Pour un premier projet, éviter de :
• Partir sur un projet de trop grande envergure.
o Risque de perte de motivation plus important
o Moins de chance de le sortir
• Mettre la barre trop haut techniquement
o Privilégier la 2D à la 3D
o Sortir un jeu solo plutôt que multijoueur
Tester son idée
• Faire un storyboard
• Lister les points clés du gameplay
• Chercher des jeux similaires sur les stores
• Réfléchir à la monétisation
• Présenter le concept à des tiers, recueillir des retours.
Avoir une équipe
Rôles à remplir
• Manager (Chef produit, marketing, chef de projet)
• Game designer (level design, son, ergonome, design)
• Graphiste (Graphiste 2d, modeleur et textureur 3d)
• Techno (Dev Moteur physique, gameplay, IA, réseau, ... )
Conseils
• Etre à plusieurs permet de compenser les baisses de motivations.
• Partir du principe que le jeu aura du succès: décider dès le début
comment les gains sont répartis dans l’équipe.
Réalisation : Composition d’un jeu
• Logique du jeu (règles, moteur physique, …)
• Moteur de rendu graphique (canvas, opengl, …)
• Ressources (textures, son, textes, localisation ...)
• Gestion des entrées utilisateur (touche écran,
gyroscope, ...)
• IA
• Stockage sur le device( sauvegardes, ...)
• Communication réseau
• Intégration api externes (pub, achat inapp, réseaux
sociaux, analytics)
Réalisation : Moteur
Un choix important s’impose dès le début du projet :
L’utilisation ou non d’un moteur de jeu.
Réalisation : Moteur
Pour :
• Réaliser des trucs “cool” plus simplement
• Code du moteur testé et de haute qualité
• On se concentre davantage sur son jeu que sur l’aspect technique
• Des exemples clé en main, communauté.
Contre :
• Peut être dur de sortir du cadre du moteur : risque de jeu “clone”
• On développe des compétences spécifiques au moteur et pas forcément
utiles ou valorisables ailleurs
• Ne convient pas à tout type de jeu
Box 2D
• Moteur physique uniquement
• Implémentation java et native
• Gestion des collisions
• Gestion de formes complexes (cercles et polygones)
• Gestion des forces (gravité, friction, spin, …)
Utilisé pour : angry birds
Chipmunk2D
• Moteur physique uniquement
• Utilisé par le moteur iOS coco2d
• Codé en c : pas compatible android SDK
• Intégration android plus compliquée (NDK)
• Globalement même fonctionnalités que Box2d
• Plus optimisé pour objets de même taille
• Version gratuite et Pro
Unity 2d/3d
• Solution intégrée à 100%
• Licence gratuite (si revenus < 100K$ annuel)
• Large compatibilité (Android, iOS, WP8, ...)
• Grosse communauté
• Mieux adapté à la 3D (a suivre version 4.3)
• Langage propriétaire ou C#/JS
• Mais ... on développe des compétences Unity
uniquement
Utilisé pour : Dead trigger 2
LibGDX
• Api java (ou autre langage JVM) multi plateforme
• Gère l’affichage, l’audio, les contrôles, le stockage.
• Pas d’IDE dédié, intégration à éclipse.
• Extension pour moteur physique (box2d natif)
• Compatible 3D
• Moteur d'exécution desktop
• Beaucoup d’exemples disponibles
AndEngine
• Framework java opensource
• Surcouche opengl
• Intégration du moteur physique box2d (natif ou jar)
• Pas de 3D
• On conserve la main sur le code
• Android only
• moins complet que libGDX mais plus facile à prendre
en main
Utilisé pour : Dream Zoo (Zynga)
Réalisation : Moteur
Choisir un moteur pour :
• Faire un test, sans vouloir trop s'investir et avoir un bon résultat
• Aller plus loin sur un projet commencé en POC sans moteur.
• Réaliser un jeu multi plateforme
• Réaliser un jeu 2D/3D sans expérience
Faire tout à la main si :
• Le jeu est non graphique
• Le jeu possède des contraintes spécifiques non adaptées au moteur
• L’on souhaite monter en compétence techniquement et qu’on est prêt à
en baver.
Réalisation : retour d’xp
Motivation pour faire Space Corsair sans moteur
• Monter en compétence sur OpenGL.
• Les moteur physiques ne gèrent pas bien les collisions avec plus de
400/500 objets ce qui pouvait être mon cas dans le gamedesign prévu.
• Savoir faire soi-même pour mieux comprendre le moteur ensuite.
Réalisation : Dev
Itération : Temps nécessaire pour dessiner la scène du jeu et calculer les
éléments de la scène suivante.
Objectif : Faire tenir une itération entre 20 et 30 millisecondes.
Plusieurs thread :
• Thread opengl
• Thread physique / logique du jeu
• Thread de l’activity (reçoit les input)
• Thread musique et son
Thread graphique
Possède sa propre liste d’éléments à afficher
Algo :
• Attendre d’avoir une nouvelle liste d’éléments à afficher
• Afficher chaque élément de la liste via des appels openGL
Réalisation : Dev
Thread physique
Possède une liste des éléments du niveau en cours (joueur, astéroïdes,
ennemis, …)
Algo simplifié V1 :
• Déterminer combien de ms depuis ma dernière exécution
• Appliquer à chacun de mes objets son mouvement en fonction des ms
• Gérer les collisions entre objets
• Ajouter l'objet à la file des éléments à dessiner
Réalisation : Dev
Réalisation : Dev
Chaque objet du jeu est un objet java qui étend d’une classe commune
“Element”. Cette classe contient des paramètres qui permettent de gérer
sa physique, affichage, l’ia.
• Drawable (Objet qui contient les infos opengl pour se dessiner)
• Puissance de poussée
• Vecteur vitesse actuel
• Masse
• Dimension
• Vie
• Visible sur le radar oui/non
Un Element contient aussi des méthodes utilisées pour l’affichage ou la
logique de jeu :
• doPhysic(long elapsed)
• public void registerYourselfToDrawQueue() {
• public void applyMovement(long elapsed)
• public void applyAcceleration(long elapsed)
• estimateFurutrePosition(long futureInMs)
• testColide(Element otherElement)
• applyDamage(float dmge, Element damageSource, Projectile projectile)
• public void onDestroyed(boolean playerLootCompatible)
Réalisation : Dev
• Exemple de la méthode pour appliquer le mouvement
Réalisation : Dev
public void applyMovement(long elapsed) {
this.position.x += this.speed.x * elapsed / 10;
this.position.y += this.speed.y * elapsed / 10;
this.spin += spinSpeed * elapsed / 10;
}
Communication inter-thread : permettre au moteur de modifier les objets pendant
que le thread graphique les affiche
Réalisation : Dev
Utilisation de deux listes d’objets
Une liste A d'éléments à dessiner en ce moment :
● ne change pas pendant l'itération, destiné au thread d'affichage
Une liste B d'élément à dessiner à la prochaine itération :
● vide au début et se remplit avec la progression du thread physique
A la fin d'une itération, on inverse les deux listes, B devient A, et A est vidé et sert a
préparer les éléments N+1
Thread physique
Algo simplifié V2 :
• Déterminer combien de ms depuis ma dernière exécution
• Déterminer la position de la caméra
• Appliquer à chacun de mes objets son mouvement en fonction des ms
• Si objet visible, ajouter l'objet à la file des éléments à dessiner
• Gérer les collisions entre objets
• Si le temps d’exécution < 16 ms (60 FPS), se mettre en “pause” le temps
d’atteindre 16 ms.
Réalisation : Dev
Gestion des inputs
les inputs ne doivent pas accéder au thread physique “en direct”.
• Risque de modification concurrente : les input viennent de
l'activité/view qui n'est pas le même thread que celui qui exécute le
moteur.
Utiliser à la place une file d’attente d’évènement utilisateur à prendre en
compte
• Le thread physique décide quand traiter les derniers traitements depuis
sa dernière exécution .
• Déterminer combien de ms depuis ma dernière exécution
• Déterminer la position de la caméra
• Appliquer à chacun de mes objets son mouvement en fonction des ms
• Si objet visible, ajouter l'objet à la file des éléments à dessiner
• Gérer les collisions entre objets ( on en parlera plus tard)
• Si le temps d’exécution < 16 ms (60 FPS), se mettre en “pause” le temps
d’atteindre 16 ms.
Réalisation : Dev
Thread physique
Algo simplifié V3 :
• Déterminer combien de ms depuis ma dernière exécution
• Déterminer la position de la caméra
• Appliquer à chacun de mes objets son mouvement en fonction des ms
• Si objet visible, ajouter l'objet à la file des éléments à dessiner
• Gérer les collisions entre objets ( on en parlera plus tard)
• Gérer les input utilisateur (touch, move, gyro, …)
• Si le temps d’exécution < 16 ms (60 FPS), se mettre en “pause” le temps
d’atteindre 16 ms.
Réalisation : Dev
Gestion des collisions
• Brute force
• Découpage en grille
• Sweep and Prune
Réalisation : Dev
• Simple
• Ne permet pas de gérer beaucoup d’objets
Brute force
Réalisation : Dev
for (int i = 0 ; i < elementSize-1; i++){
for (int y = i+1; y < elementSize ; y++){
detectionCollision(elements.get(i),elements.get(y));
}
}
Découpe en grille
Réalisation : Dev
● Plus efficace que le brute force
● Bien choisir sa taille de carré
Optimisation : QuadTree
Sweep and prune
Réalisation : Dev
● Phase 1 : Sweep
Extrait des paires d’objet
potentiellement en collision.
● Phase 2 : Prune
On effectue le test de collision
complet sur les paires.
Intégrer des missions
Utilisation d’interfaces, chaque mission doit fournir une implémentation
que contient la logique de la mission.
Réalisation : Dev
public abstract class MissionListener {
public abstract void onElementDestroyedByPlayer(Element element);
public abstract void onPlayerDeath();
// trigger every 10 sec
public abstract void onEveryTenGameSec();
}
Exemple de mission
Détruire x objets d’un même type (ennemis, astéroides, …)
Réalisation : Dev
@Override
public void onElementDestroyedByPlayer(Element element) {
if ( elementToDestroy.isInstance(element) && !completed) {
remainingElementToDestroy--;
if (remainingElementToDestroy <= 0) {
completed = true;
currentPhase = Phase.GATHER_RECOMP;
}
}
}
Gestion de la musique
Utilisation de la classe MediaPlayer
Réalisation : Dev
MediaPlayer levelMusic = MediaPlayer.create(context, R.raw.space1);
levelMusic.setLooping(true);
levelMusic.start;
●
● Lit la plupart des formats audio. Format Ogg bon compromis entre
performance et qualité.
● Créer un thread dédié pour le mediaplayer évite des problèmes
Effets sonores
Utilisation de la classe SoundPools
Réalisation : Dev
// chargement
private int[] soundPoolIndex = new int[30];
soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 100);
int laserSoundIndex = soundPool.load(context, R.raw.laser11, 1);
// utilisation
soundPool.play(laserSoundIndex, volume, volume, 1, 0, 1f);
Optimisations
• Limiter au maximum la création d’objets après le chargement du jeu.
o Utilisation de pool d’objets
o Un objet à retirer de la scène retourne dans le pool.
Réalisation : Dev
public static RubyAsteroid newRubyAsteroid() {
RubyAsteroid rubyAsteroid = GamePools.rubyAsteroidPool.getObject();
if (rubyAsteroid == null) {
rubyAsteroid = new RubyAsteroid();
rubyAsteroid.myPool = GamePools.rubyAsteroidPool;
}
return rubyAsteroid;
}
Optimisations
• Ne pas utiliser de boucle de type foreach
• Utiliser les types primitifs au maximum, ne pas faire d’autoboxing.
• Limiter les appels de méthode
o Remplacer les getter setter par des champs pubic
Réalisation : Dev
Localisation
• Supporter au minimum l’anglais
• Idéalement : koréen, japonais, russe
• Penser aux images
• Texte du play store (très important)
Réalisation : Dev
Sécuriser son code
• Utiliser un obfuscateur (proguard)
• Ne pas laisser de chaînes de caractères sensibles dans le code
• Retirer les logs
Réalisation : Dev
Courbe de motivation
Réalisation
Utiliser les fonctionnalités beta du play store
• Basé sur les communauté G+
• Permet d’inviter des personnes à tester son jeu depuis le store
• Attention notes et commentaires actifs.
Beta
Eléments à intégrer pour une béta
• Un message qui alerte que le jeu est en béta
• Formulaire de contact / fonction d’email au dev
• Librairie de gestion d’erreur
o ACRA (Application Crash Report for Android)
o Crashlytics
• Google analytics
Beta
Différents modèles
• Payant
• Gratuit avec pub
• Freemium (gratuit et inapp premium upgrade)
• Vente de code source
• Partenariat
• Dons
• Vente de stats
Monétiser son app
Types de publicité
• Bannière
• Interstitiel (le plus rentable)
• Vidéo
• Pub géolocalisée
• Cross promotion network
Utiliser un “ad network” : admob, appBrain, greyStrike, ...
Monétiser son app
Achat inapp
• Différents types (Upgrade, Consommable, Monnaie virtuelle)
• Doit être codé pour chaque app store
• Plus compliqué à intégrer proprement que la pub
• Commission des stores de 30%
• Adapter les prix en fonction du pays
• Avantage des gifts code
Monétiser son app
Modèle freemium
• 90% des joueurs n’achèteront rien
o Mais les notes positives de ceux-ci font venir les 10% restants
• 50% des revenus de jeux viennent de 0.15% des joueurs
• Modèle le plus rentable
Monétiser son app
Principaux stores
• Google play store
• Amazon app store
• Opera mobile store
• Samsung apps mobile
• …
Publier son app
• Localiser la description dans les stores
• Publier plus tôt sans forcément avoir toutes les features
• Choisir sa date de sortie : idéalement un vendredi
• Ajouter un lien pour noter son app
• Ajouter un changelog
Publier son app
• Faire une vidéo
o Genymotion + capture vidéo
• Préparer un dossier de presse
o Présentation de l’équipe
o Date de lancement
o Point discriminent de l’app
o Screenshot/vidéos
o Statistiques
• Avoir un article dans les site de niche
Promouvoir son app
Promouvoir son app
• Ajouter une dimension sociale
o facebook api
o google play game services
• Présentation dans les forums, réseaux sociaux
• Campagne de pub o Optimiser le nombre de week end
o Ne promouvoir que les pays dont l’app est localisée
• Classement (quotidien, hebdo, mensuel, …)
• Succès
• Multijoueur (mise en relation)
• Stockage en ligne de backup
• Les joueurs se connectent avec un compte g+
Google Play Games Services
• Surveiller les bugs et les corriger
• Répondre aux mails des joueurs
• Répondre aux commentaires sur les stores
• Orienter ses futures mises à jour en fonction des retours des joueurs.
• Faire des mises à jour régulières
Après la sortie