JeuWeb - Crée ton jeu par navigateur
[Résolu] Structuration d'un code plutôt complexe et avis - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : [Résolu] Structuration d'un code plutôt complexe et avis (/showthread.php?tid=2433)



[Résolu] Structuration d'un code plutôt complexe et avis - omsi668 - 16-02-2008

Bonsoir,

Pour la V1.03 de mon jeu (Sujet sur JeuPHP), je comptes refaire le système de combats, enfin, tout du moins le déroulement en lui même, afin de rendre la défense plus interessante, et la chose plus réaliste et complexe. Jusqu'alors mes combats se résumaient en :

Un tas de paramètres + un nombre de troupes + des variables aléatoires + une formule... Ensuite on compare le résultat pour l'attaque et la défense et celui qui a la plus grosse (:wowowowSmile gagne le combat empoche la thune et on calcule les pertes... Quelquechose de plutot simpliste quoi (enfin pas tellement vu le nombre de paramètres pris en compte, mais d'un point de vue défensif, a par faire de la défense, aucun interet, et l'attaque, à part faire l'attaque, aucun interet..

Pour comprendre ce que je vais tenter d'expliquer par la suite, il faut savoir qu'il y a 5 unités sur mon jeu (enfin y'en a une sixième, le cheval de troie, mais elle est spéciale, elle permet juste de sauter l'enceinte de l'adversaire lors d'un combat, c'est facile à mettre en place) : l'hoplite, le frondeurs, l'archer, la catapulte, et la trirème. Les trirèmes ne peuvent être achetées que par les villes portuaires et fluviales, et donc ne sont pas prises en compte quand l'attaquant ne possède pas une ville fluviale ou portuaire. Chaque joueur n'a qu'une seule ville.

Mon nouveau système se veut inspiré de la réalité... Cela donc un peu selon le type de ville.

Mais tout d'abord je vais parler des options que le joueur peut choisir avant le combat, et donc expliquer comment se déroule le combat

Options d'attaquant :
Les hoplites peuvent attaquer prioritairement (avant la pénétration dans la ville) les hoplites ou les frondeurs adverses, puis, quand ils ont pénétrer dans l'enceinte adversaire, ils peuvent soit choisir de piller un maximum la ville, soit de massacrer l'armée adverse (plus de gains, ou plus de morts.
Les frondeurs peuvent attaquer prioritairement (avant la pénétration dans la ville) les hoplites, les archers ou les frondeurs adverses, puis, quand ils ont pénétrer dans l'enceinte adversaire, ils peuvent soit choisir de piller un maximum la ville, soit de massacrer l'armée adverse (plus de gains, ou plus de morts.
Les archers se comportent comme les frondeurs, mais sont plus puissants, et possèdent une attaque corps à corps.
Les catapultes détruisent l'enceinte adverse en priorité (dans le futur, elles détruiront peut être des bâtiments une fois l'enceinte détruite, mais c'est pas d'actualité)
Les trirèmes, attaquent prioritairement les trirèmes adverses, si il n'y a pas de troupes maritimes adverses, elles aident à la destruction de l'enceinte. On peut choisir de laisser les archers ou les frondeurs à bord des trirèmes pour aider au combat naval... On considère que lorsqu'une ville fluviale ou portuaire attaque une autre ville fluviale ou portuaire, elle passe obligatoirement par une voie fluviale ou maritime pour attaquer.

Options de défenseur :
Les hoplites sortent de l'enceinte au début du combat. On peut choisir d'attaquer prioritairement les archers, catapultes, frondeurs ou hoplites adverses... Si les archers et/ou les frondeurs ne sont pas disponibles, les hoplites se retournent par défaut contre les catapultes ou les hoplites (par défaut)
Les frondeurs peuvent soit se positionner sur l'enceinte, soit descendre dans la pleine. SI ils sont sur les enceintes ils ne peuvent qu'attaquer les hoplites, si ils descendent sur le champ de bataille il y a le choix entre archers, hoplites, frondeurs ou catapultes adverses.
Les archers se comportent comme les frondeurs, mais peuvent aussi attaquer les frondeurs/archers adverses si ils sont positionnés sur l'enceinte.
Les catapultes peuvent être sorties mais elles perdent énormément en puissance et n'ont qu'un impact limité sur le combat.
Les bateaux se comportent comme lors d'une attaque.

A savoir que pour l'instant au moins, on ne pourra pas choisir de mettre 10000 hoplites la et 2000 hoplites la bas.

Le combat devrait se dérouler de la manière suivante : par exemple j'ai choisis que les frondeurs visent les archers adverses en attaquant. Si ils sont plus forts les frondeurs passent à autre chose, sinon ils s'arretent la (mais ne meurent pas tous, trop cruel pour les joueurs sinon).


J'aimerais donc savoir comment coder ce systeme de choix et de priorité de façon optimisée et efficace. Parce que j'aimerais autant éviter de taper 500 lignes de if else. Si vous avez des idées pour en faire sortir des fonctions je prends, j'en ai deja quelques une pour les pertes notamment dans ma classe. J'ai donc des notions de POO même si j'ai pas la 'mentalité objet', comme disent les puristes.
Vous pouvez aussi donner votre avis ou des idées pour faire mieux, c'est toujours bon à prendre.

Merci de votre aide.


RE: Structuration d'un code, plutot complexe et avis - 'AluCard! - 16-02-2008

omsi668 a écrit :Le combat devrait se dérouler de la manière suivante : par exemple j'ai choisis que les frondeurs visent les archers adverses en attaquant. Si ils sont plus forts les frondeurs passent à autre chose, sinon ils s'arretent la (mais ne meurent pas tous, trop cruel pour les joueurs sinon).


je ne suis pas trop ou tu veux en venir la. Enfin le plus simple et de faire deux bêtes fonctions je pense ou tu joue sur la différences par des calcul pas très savants
si >1 alors y sont plus fort
si = 1 même force
<1 Moins fort
Code PHP :
<?php 
function priorité()
{
Tes calcul avec tes if et else
}

function
prioritéunitée(){
switch(
$unitée){
case
'archers':
priorité()
break;
case
'frondeur':
priorité()
etc }

Enfin je fait simple par manque de temps mais si je fait pas mauvaise route j'essayerais de te faire un exemple plus detaillé


RE: Structuration d'un code, plutot complexe et avis - omsi668 - 17-02-2008

Merci de ton aide...

Mais mon probleme se situe plutot dans la reconnaissance des unités, contre qui vont elles se battre, avec d'autres unités peut etre etc ...

Peut être pouvoir faire, du coup le calcul de hoplites vs hoplites avec le même bout de code que si c'est frondeurs vs archers sur enceinte..


RE: Structuration d'un code, plutot complexe et avis - alfanor - 17-02-2008

Bon j'ai lu ça vite fait et je pense que quelque chose de bête et méchant comme ça ira parfaitement.

Je pars du principe que chaque joueur doit paramétrer les priorités d'actions par unité et qu'il existe aussi des priorités établies par défaut si le joueur ne connais pas cette option ou tout simplement s'il oublie ou ne veut pas les modifier, alors voici ce que ça donne pour moi :

Code PHP :
<?php
$priorité
= array();

$priorité[0] = $tableau_priorite_defaut_attaque;
$priorite[1] = $tableau_priorite_defaut_defense
$priorite
[2] = $tableau_priorite_defenseur;
$priorite[3] = $tableau_priorite_attaquant;
?>

Ainsi, si nous appliquons un print_r($priorite), nous obtiendrons alors quelque chose comme cela si je comprend bien :

Citation :array
{
[0] => array
{
'hoplite' => 'hoplite'
'archer' => 'hoplite'
'frondeur' => 'hoplite'
}

[1] => array
{
'hoplite' => 'hoplite'
'archer' => 'archer'
'frondeur' => 'hoplite'
}

[2] => array
{
'hoplite' => 'hoplite'
'archer' => 'frondeur'
'frondeur' => 'hoplite'
}

[3] => array
{
'hoplite' => 'hoplite'
'archer' => 'hoplite'
'frondeur' => 'hoplite'
}
}

Donc là je ne gère que trois unités et en gère que les priorités d'actions au combat et non les objectifs de batailles telle que tu les as décris (piller la ville, massacrer tout le monde ...)

Dans le code ce tableau peut être exploité de la manière suivante :

Code PHP :
<?php
/* On déclare des caractéristiques au pif pour les unités afin de faire le script, à noter
que tout cela se trouve bien entendu dans la Base De Donnée en théorie et n'est donc
pas directement présent dans le script de combat. */
$tableau_caracteristique = array();

$tableau_caracteristique['hoplite'] = array( 'defense_tir' = 5,
'defense_corps' = 10,
'attaque_corps' = 10,
'attaque_distance' = 0);

$tableau_caracteristique['archer'] = array( 'defense_tir' = 3,
'defense_corps' = 6,
'attaque_corps' = 4,
'attaque_distance' = 20);

$tableau_caracteristique['frondeur'] = array( 'defense_tir' = 2,
'defense_corps' = 4,
'attaque_corps' = 5,
'attaque_distance' = 12);

/* On déclare les différentes priorités, en réalité celles-ci sortent de la Base De Donnée,
il est aussi à préciser qu'afin d'alléger tout cela il sera préférable d'utiliser des identifiants
pour définir une unité plutôt que le nom réel de celle-ci (par exemple 1 == hoplite) */
$priorite = array();

$priorite[0] = array( 'hoplite' => 'hoplite',
'archer' => 'hoplite',
'frondeur' => 'hoplite');

$priorite[1] = array('hoplite' => 'hoplite',
'archer' => 'archer',
'frondeur' => 'hoplite');

$priorite[2] = array('hoplite' => 'hoplite',
'archer' => 'frondeur',
'frondeur' => 'hoplite');

$priorite[3] = array('hoplite' => 'hoplite',
'archer' => 'hoplite',
'frondeur' => 'hoplite');


/* On déclare ensuite l'ordre dans lequel chaque unité sera attaqué suivant la disparition des autres
(si l'hoplite veut taper l'archer mais qu'il n'y en a plus il va se rabattre sur les frondeurs s'il n'y en a
plus i lse rabat sur les hoplites et ainsi de suite) (sachant que l'on revient toujours à la case départ
même si l'on ciblé les derniers de la liste)*/
$liste_defil = array('hoplite', 'archer', 'frondeur');

/* Ceci fait on peut déclarer les tableaux des armées défensives et attaquantes */
$armee_offensive = array( 'hoplite' => 2000,
'archer' => 500,
'frondeur' => 200);

$nombre_troupe_attaque = 2700;

$armee_defensive = array( 'hoplite' => 1000,
'archer' => 1000,
'frondeur' => 100);

$nombre_troupe_defense = 2100;

/* Enfin nous pouvons lancer la boucle du combat qui ne s'arrêtera pas avant qu'une des deux armées soient dissoutes :P */
$numero_phase = 1;

while(
$nombre_troupe_attaque != 0 && $nombre_troupe_defense != 0)
{
if(
$numero_phase == 4)
$numero_phase = 0;

/* On va partir du principe que le combat se déroule de façons linéaire, la première action revient au défenseur
qui est le premier à pouvoir atteindre l'ennemi grâce à la hauteur de ses archers, ainsi nous allons définir les phases
comme cela :
- Phase 1 : Tir des archers défense PUIS attaque
- Phase 2 : Tir des frondeurs défense PUIS attaque
- Phase 3 : Combat au corps à corps avec initiative automatique à la défense une fois de plus
À noter que le script suivant en tient pas compte des notions d'initiatives pouvant changer de camp ni des notions de
positions, de portée ...

À préciser que je ne donnerai que l'exemple des archers, et à préciser également qu'il faudra bien entendu découper tout cela
en fonction par la suite si jamais ç te sert à quelque chose. */

if($numero_phase == 1)
{
$cible_definit = 0;

/* On commence donc par faire tirer nos amis les archers de la défense, on vérifie déjà que la cible existe */
if($armee_offensive[$priorite[2]['archer']] == 0)
{
$parcourt_cible = 0;

while(
$cible_definit == 0)
(
if(
$armee_offensive[$liste_defil[$parcourt_cible]] != 0)
$cible_definit = $liste_defil[$parcourt_cible];

$parcourt_cible++;
}
}

else
$cible_definit = $priorite[2]['archer'];

/* On a définit une cible pour nos amis les archers, on peut donc tirer dans le tas,
on part du principe simple que l'on compare à l'arrache defense / attaque et que
l'on fait un petit calcul bidon que je ne testerait même pas pour trouver le nombre
de pertes. */
$pertes = (($armee_defensive['archer'] * $tableau_caracteristique['archer']['attaque_distance']) /
(
$armee_offensive[$cible_definit] * $tableau_caracteristique[$cible_definit]['defense_tir']);

/* On vire les pertes de l'armée et de la variable contenant la totalité des troupes */
$armee_offensive -= $pertes;

if(
$pertes > $armee_offensive[$cible_definit])
$armee_offensive[$cible_definit] = 0;

else
$armee_offensive[$cible_definit] -= $pertes;
}

$numero_phase++;
}
?>

Il est à noter que ce script ne fonctionne certainement pas (c'est même sûr), il n'est là que pour présenter ma vision du déroulement du combat de base et la gestion des cibles. (en gros je ne gère rien à part les cibles lol)

D'ailleurs je ne prends pas en compte cette histoire de "si plus fort ils passent à autre chose", car soit j'ai pas compris soit c'est stupide.


RE: Structuration d'un code, plutot complexe et avis - omsi668 - 17-02-2008

Ca repond approximativement à mes questions...

Sauf que je suis pas trop combat au tour par tour, avantage beaucoup trop l'attaquant... Mais comme c'est plutot la reconnaissance des priorités qui m'interesse, c'est pas grave

Maintenant j'ai une autre question, Si les frondeurs attaquent les hoplites adverses avec les hoplites (attaquants), et que les hoplites défenseurs sont programmés pour cibler les catapultes, comment retranscrire ca dans le code efficacement et de manière assez réaliste?


RE: Structuration d'un code, plutot complexe et avis - alfanor - 17-02-2008

Il faut partir du principe qu'une unité à le droit à la fois d'attaquer et de riposter (ici une unité représente un groupe d'un certain type de troupe), ainsi il faudra définir les combats à réaliser avant de les commencer selon les priorités établies par les joueurs, donc nous allons prendre comme exemple celui que tu énonces, soit :

Trois groupes attaquants :
  • Hoplite
  • Frondeur
  • Catapulte

Un groupe de défense :
  • Hoplite

Ici les relations d'attaques qui nous intéressent sont les suivantes :
  • Frondeur VS Hoplite_defenseur
  • Hoplite VS Hoplite_defenseur
  • Hoplite_defenseur VS Catapulte

Ces trois relations entraînent donc les relations de ripostes suivantes :
  • Catapulte VS Hoplite_defenseur
  • Hoplite_defenseur VS Frondeur & Hoplite

À noter que par catapulte j'entends les ingénieurs qui les manipulent.

Donc dans le code ça donnerait quelque chose comme ça je pense :

Code PHP :
<?php 
/* En fait pas besoin de code, c'est assez explicite je pense */