Dans le développement d'applications Android dédiées aux jeux de cartes comme le Dou Dizhu, la gestion des ressources graphiques constitue un enjeu critique. Ce guide technique aborde la conception, l’organisation et l’optimisation d’un jeu complet de 54 cartes — incluant les 52 cartes classiques (cœurs, carreaux, trèfles, piques) et les deux jokers — sous forme d’actifs numériques prêts à l’emploi dans un environnement Android Studio.
- Architecture des ressources dans Android
Les ressources sont centralisées dans le répertoire res/, structuré selon leur nature et leur usage. Pour les cartes, les sous-répertoires suivants sont pertinents :
res/drawable-mdpi/,res/drawable-hdpi/,res/drawable-xhdpi/,res/drawable-xxhdpi/,res/drawable-xxxhdpi/: contiennent les versions redimensionnées des images selon la densité d’écran.res/values/dimens.xml: définit des dimensions scalables utilisées dans les layouts (ex. : largeur standard d’une carte).res/mipmap/: réservé aux icônes d’application (non utilisé ici, mais bon à savoir).
- Stratégie multi-densité pour les cartes
Au lieu de générer manuellement chaque variante, une approche automatisée est recommandée. Voici un script Python simplifié permettant de produire des variantes adaptées à partir d’une version source haute résolution (300×420 px) :
import subprocess
from pathlib import Path
SOURCE = Path("src/cards/ace_spades.png")
DPI_SCALES = {
"mdpi": 1.0,
"hdpi": 1.5,
"xhdpi": 2.0,
"xxhdpi": 3.0,
"xxxhdpi": 4.0
}
for dpi, scale in DPI_SCALES.items():
output = Path(f"res/drawable-{dpi}/ace_spades.png")
subprocess.run([
"magick", str(SOURCE),
"-resize", f"{int(300*scale)}x{int(420*scale)}!",
str(output)
])
Ce processus garantit une cohérence visuelle tout en évitant les artefacts liés au redimensionnement dynamique à l’exécution.
- Choix foramtique : pourquoi PNG ?
Pour les cartes, le format PNG est privilégié pour trois raisons techniques :
- Transparence alpha native : indispensabel pour les masques de découpe ou les effets d’ombre portée.
- Compression sans perte : préserve les contours nets des symboles et des chiffres, critiques pour la lisibilité.
- Prise en charge universelle : aucun pilote supplémentaire requis sur aucune version d’Android ≥ 4.0.
Contrairement au JPEG (compression avec pertes, pas de transparence) ou au WebP (bien que plus compact, support limité sur les anciennes versions), PNG assure robustesse et compatibilité maximale.
- Optimisation avancée des actifs
L’optimisation ne se limite pas à la compression. Elle intègre aussi la gestion mémoire et le chargement intelligent :
4.1 Réduction de poids via optiPNG
Commande recommandée pour une balance optimale entre taille et qualité :
optipng -o7 -strip all -zm1-9 card_01.png
-o7: niveau maximal d’optimisation heuristique.-strip all: suppression des métadonnées EXIF et commentaires superflus.-zm1-9: essai exhaustif des algorithmes de compression ZLIB.
4.2 Chargement asynchrone avec Glide
Pour afficher une carte sans bloquer l’interface, utilisez Glide avec une stratégie de cache intelligente :
GlideApp.with(context)
.asBitmap()
.load(R.drawable.card_king_hearts)
.override(240, 336) // adaptation dynamique à la vue
.centerCrop()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(imageView);
- Intégration visuelle avancée
Un ImageView standard peut être étendu pour supporter des comportements spécifiques aux cartes :
5.1 Effet de retournement 3D
Utilisez ObjectAnimator pour simuler un retournement réaliste lors du tirage :
ObjectAnimator flipX = ObjectAnimator.ofFloat(cardView, "rotationY", 0f, 90f, 0f);
flipX.setDuration(400);
flipX.setInterpolator(new AccelerateDecelerateInterpolator());
flipX.start();
5.2 Détection gestuelle personnalisée
Implémentez un ScaleGestureDetector pour permettre le zoom sur une carte sélectionnée :
ScaleGestureDetector detector = new ScaleGestureDetector(context, new ScaleGestureDetector.SimpleOnScaleGestureListener() {
@Override
public boolean onScale(ScaleGestureDetector detector) {
float scale = detector.getScaleFactor();
cardView.setScaleX(cardView.getScaleX() * scale);
cardView.setScaleY(cardView.getScaleY() * scale);
return true;
}
});
cardView.setOnTouchListener((v, event) -> {
detector.onTouchEvent(event);
return true;
});
- Organisation des ressources en production
Pour faciliter la maintenance, adoptez une hiérarchie claire dans votre projet :
app/src/main/res/
├── drawable-mdpi/ # 100% (base)
├── drawable-hdpi/ # 150%
├── drawable-xhdpi/ # 200%
├── drawable-xxhdpi/ # 300%
├── drawable-xxxhdpi/ # 400%
└── values/
└── cards.xml # constantes : noms, valeurs, couleurs
Le fichier cards.xml peut contenir :
<resources>
<string-array name="card_ranks">
<item>3</item><item>4</item><item>5</item>...<item>2</item>
</string-array>
<integer-array name="card_values">
<item>3</item><item>4</item><item>5</item>...<item>15</item>
</integer-array>
</resources>
- Validation cross-device
Avant déploiement, testez systématiquement sur plusieurs profils d’appareils via l’émulateur Android Studio :
- Nexus 5 (1080×1920, xxhdpi)
- Pixal 3a (1080×2220, xxxhdpi)
- Galaxy Tab A (800×1280, mdpi)
Vérifiez notamment l’absence de flou, de décalage de position ou de coupure de symboles dans les coins.