Petite amélioration : l’un des principes de la programmation objet est de cacher les détails techniques. Le code gérant les événements n’a pas besoin de savoir comment tirer une probabilité, juste d’accéder à un mécanisme le faisant à sa place.
On peut faire ça en ajoutant une nouvelle fonction à la classe Player.
// Tirage aléatoire
func tirageAleatoire(probabilite:Double) -> Bool {
if Double.random(in: 0.0 ... 100.0) <= probabilite {
return true
}
return false
}
J’ai ajusté la plage de probabilité de 0.0 à 100.0, car c’est mathématiquement plus exact que de commencer à 1, surtout pour des variables flottantes.
J’ai choisi le type Double pour gérer les chiffres à virgules, car c’est le type flottant le plus utilisé en Swift.
Utilisation :
//Attaque normal avec 75% de reussite
if self.tirageAleatoire(probabilite: 75.0) {
// ... réussite
} else {
// ... échec
}
Le code est plus lisible. Mais surtout l’algorithme de probabilité n’est présent qu’à un seul endroit dans le code. Si pour une raison quelconque, tu veux modifier la manière de calculer une probabilité, il suffit de mettre à jour la fonction tirageAleatoire() et c’est bon.
Si la méthode de calcul est présente à plusieurs endroits dans le programme, il faut modifier plusieurs lignes pour mettre le code à jour, ce qui peut sembler facile sur un code court tapé hier, mais pas forcément si le travail date de 3 mois, ou plus ! Sans même parler d’un listing de 3000 lignes. C’est une source inépuisable de bugs !
Centraliser les algorithmes, en les regroupant dans des fonctions spécialisées permet de s’éviter bien des problèmes par la suite. C’est l’un des principes de base de la bonne programmation.
Pourquoi des probabilités exprimées avec des variables flottantes et non des entiers, comme dans les exemple de Maxime ?
Parce que c’est beaucoup plus souple et évolutif. Exemple : le mécanisme actuel ne tient pas compte des dégâts reçus. Dans un combat réel, les blessures ou les dégâts diminuent les capacités offensives, sans parler de la fatigue. Il suffit de regarder un combat dans une série médiévale (non, je n’ai pas dit Games Of Thrones, je l’ai juste pensé), pour constater que les combattants sont nettement moins fringants après avoir encaissé quelques coups.
Dans le cas des boots, la violence des coups peut abimer les mécanismes internes, altérant les capacités offensifs. Sans parler d’attaques spéciales, comme des jets d’acides ou des lances-flammes.
On pourrait simuler ça en ajoutant un paramètre vitalite, calculé en fonction des points de vie maximum et de l’état de santé courant. Par exemple, un Joueur avec 100 points de vie au début, et n’ayant plus que 67 points de vie aura une vitalité de 67%.
Sa force d’attaque sera diminué, et ne sera plus que :
force théorique (100%, 75% ou 50%) * vitalite
Dans le cas d’une attaque à 75%, cela donne :
75% * 0.67 = 50.25%
D’où l’intérêt d’utiliser des variables flottantes pour avoir un résultat exact.
C’est un exemple assez violent. On peut utiliser une courbe de vitalité plus faible, pour refléter la perte de puissance offensive en cas de blessures.
On pourrais aussi gérer des bonus et malus de combat. Par exemple, le joueur pourrais perdre 10% de ses capacités offensives si le Boot lui crache de l’acide au visage.
force attaque = force théorique * (100 - malus acide)
Dans le cas d’une attaque à 75% :
force réel = 75% * (1.0-0.1) = 75% * 0.9 = 67.5%
Petit détail technique, on code généralement les pourcentages par des nombres flottants compris entre 0.0 et 1.0. C’est pratique pour simplifier les lignes de code, quand plusieurs pourcentages sont utilisés.
Pour obtenir 79% d’une valeur, il suffit de la multiplier par 0.79.
Dans certains jeux, comme les jeux de rôles ou de stratégie militaire, on peut avoir une longue liste de malus ou de bonus appliqués sur les caractéristiques de base des combattants, pour réfléter l’état du terrain, du moral, etc …
Exemple de base : un combattant chargeant l’ennemi depuis une hauteur à un gros bonus d’attaque.