JeuWeb - Crée ton jeu par navigateur
le Pvp en Php/SQL/Ajax - 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 : le Pvp en Php/SQL/Ajax (/showthread.php?tid=1451)

Pages : 1 2


le Pvp en Php/SQL/Ajax - Taressik - 20-04-2014

Bonjour, Bonsoir. Veuillez excuser toutes les fautes d'orthographes ^^ Je suis généralement consciencieuse et studieuse mais il se fait tard...

Je suis dans une impasse et malheureusement mon cerveau sature très rapidement ces derniers temps, ainsi je viens vers vous pour soulager mes peines é_è !

Je m'explique. Je suis en pleine création d'un jeu (Php/SQL) de type mmorpg et je me suis demandé comment était il possible de créer du PVP, du combat "joueur vs joueur".
Enfaite j'arrive pas a bien cerner comment nous pouvons faire cela?
Un exemple je suis dans une arène, j'ai la liste des joueur voulant combattre. J'en choisi un. Puis si il accepte ou est ce que le combat se déroule? (je parle techniquement)
Je sais pas si je suis assez explicite. Jespere que la question n'a pas été posé a mainte reprise..

Merci d'avance pour votre attention. :$


RE: le Pvp en Php/SQL/Ajax - Ekilio - 20-04-2014

De mon point de vue, le combat se déroule de toutes façons dans ton serveur. Les joueurs (qu'ils jouent en temps réel ou au tour par tour) vont envoyer les actions au serveur, qui va les traiter et envoyer en retour la réponse (IE : le nouvel état du combat) à tous les joueurs.

La façon exacte de procéder dépend de ton type de combat. Quelques exemples :

- Combat au tour par tour, méthode simple, sans même javascript : Les joueurs ont un temps défini pour effectuer leurs actions, par exemple une minute. Le serveur garde trace (si tu part sur un jeu php / sql simple sans accès ou quoi au serveur pour faire du persistant, via une table "combats" dans la base de données) de qui a le droit de jouer. Chaque minute, la fenêtre du combat s'actualise pour mettre à jour le tour et indiquer l'action de l'autre. Ce système permet par exemple de faire un combat du type "heartstone", en un contre un.

- Combat au tour par tour plus lent : même principe que précédemment, sans l'actualisation de la fenêtre. Dans cet exemple, il n'y a plus de temps limité pour un joueur ; il agit quand l'autre a agit, et cela envoi un message à son adversaire pour lui dire d'agir. Le workflow devient donc : Joueur A joue => joueur B reçoit un message lui disant qu'il peut jouer => Joueur B joue => Joueur A reçoit un message lui disant qu'il peut jouer. L'inconvénient de cette méthode est que le combat devient très lent.

- Combat en temps réel avec action chronométrées : ici, les deux joueurs ont le choix de leurs actions et ne dépendent pas de l'adversaire. On suppose que le joueur ayant accepté reste devant son écran pour le combat. Il va donc effectuer ses actions quand elles sont prêtes, et la fenêtre de combat sera périodiquement rafraîchie pour mettre à jour l'état du combat. Cette méthode a l'avantage d'être plus agréable pour le joueur, mais l'inconvénient d'être assez lourde.

-Utilisation de websockets : On en arrive maintenant à la méthode que je trouve la plus propre pour gérer ce genre de choses. Le principe est ici un peu différent et nécessite un accès plus grand qu'un simple hébergement web. L'idée va être de faire tourner un serveur persistant, sur lequel tes clients vont se connecter en websocket. Une websocket est une connexion réseau persistante ; tu n'as plus de chargement de page, mais uniquement des données qui vont dans un sens ou dans l'autre. Tu trouveras un exemple d'implémentation ici : https://code.google.com/p/phpwebsocket/ . L'intérêt de cette méthode est qu'elle ne dépend pas d'actualisation chronométrée de page ; à la place, le combat se déroule au même titre que dans un mmorpg classique, avec l'envoi des données en direct. Ici, c'est le serveur de websocket qui garde en mémoire ton combat en cours (plus besoin de le stocker en base de données ; c'est une bonne chose car ces données sont temporaires et l'accès à la base de données est plus lent que l'accès à la ram). Les connexions en websocket étant identifiées, il peut associer un joueur à un combat ; et le workflow devient donc : Joueur fait une action => Javascript envoi l'action au serveur => Serveur traite l'action => Serveur envoi les nouvelles données aux clients des joueurs. Techniquement, le code est un peu plus complexe, mais le résultat est nettement plus agréable pour les visiteurs.

Je ne détail pas plus car je ne suis pas certain que ce soit exactement cela que tu veux comme réponse ; mais si oui, n'hésites pas à préciser quelle(s) solution(s) te plais(ent), et je la détaillerais volontiers plus !


RE: le Pvp en Php/SQL/Ajax - Taressik - 20-04-2014

Waaw.. merci beaucoup je ne m'attendais pas a une réponse aussi rapide.. merci de prendre le temps de m'expliquer.
Je t'explique comment je vois le jeu :
Perso A vs Perso B
Le 1er tours le perso A attaque.
Puis c'est au tours du perso B, lui a 2 actions :
1)D'abord il peut esquiver ou amoindrir la charge de l'attaquant.
2)Ensuite il peut attaquer

Et ainsi de suite le perso A peut esquiver puis il attaque. Au final il faudrait attendre l'esquive avant de calculer les dégâts infligés.
Vois tu ? J'ai crée un gameplay très equilibré avec des" points actions". Je sais pas si c'est possible..
Peut être suis je trop compliqué eou trop rêveuse mais j'imaginais bien ce système de jeu.


RE: le Pvp en Php/SQL/Ajax - Ekilio - 20-04-2014

Salut,

Pour ce genre de chose, tu peux tout à fait utiliser la plupart des solutions que j'ai proposées. Avant de répondre plus en détails, quel est ton niveau en PHP et Javascript ? J'adapterais ma réponse en fonction Smile


RE: le Pvp en Php/SQL/Ajax - Taressik - 20-04-2014

Disons que j'ai un bon niveau en php et un petit peu moins bon en javascript


RE: le Pvp en Php/SQL/Ajax - Ekilio - 20-04-2014

Ok ! Alors allons-y Smile

Donc, je vais partir sur un exemple en ajax tout simple, histoire d'éviter les websockets pour le moment (mais si besoin je te ferais ça ensuite).

Admettons que tu as une table battle qui ressemble à ça :

(int) battle_id
(int) player1
(int) player2
(int) hpPlayer1
(int) hpPlayer2
(int) incomingDamages
(enum) currentStep (PLAYER1_ATTACK, PLAYER2_AVOID, PLAYER2_ATTACK, PLAYER1_AVOID)

Au début du combat, tu créé dans cette table une ligne :

Code :
$table = new BattleTable;

$battleRow = $table->createRow();

$battleRow->player1 = $idOfPlayer1;
$battleRow->player2 = $idOfPlayer2;
$battleRow->hpPlayer1 = $initialHpOfPlayer1;
$battleRow->hpPlayer2 = $initialHpOfPlayer2;
$battleRow->currentStep = 'PLAYER1_ATTACK';

$battleRow->save();

$_SESSION['battleId'] = $battleRow->id;

Ensuite, tu lances le combat. Donc, tu vas avoir une page avec la vie des deux joueurs, quelque chose de ce genre :

Code :
<div id="battle">
Player 1's life : <span id="hpPlayer1">100</span><br />
Player 2's life : <span id="hpPlayer2">100</span><br />

<div class="action">
</div>

Histoire de faire simple, je vais réduire au maximum le code javascript. On va donc juste actualiser à intervalle régulier la bataille (c'est pas la manière la plus propre de faire, mais c'est pour te donner une idée de base, je te laisse voir comment l'améliorer en chargeant et parsant du json par exemple Smile )

Code :
setInterval(function () {
$("#battle").load('battle.php');
}, 5000);

Ça va permettre de mettre à jour la page. Maintenant, modifions un peu notre page de bataille ! On va d'abord devoir récupérer les valeurs (je considère ici que tout est dans la même page, mais si tu fais les choses proprement, c'est séparé Smile ). On va d'abord ajouter simplement les points de vie.

Code :
<?php

$table = new BattleTable;

$row = $table->findRowWhere('battle = ?', $_SESSION['battleId']);

?>

<div id="battle">
Player 1's life : <span id="hpPlayer1"><?php echo $row->hpPlayer1; ?></span><br />
Player 2's life : <span id="hpPlayer2"><?php echo $row->hpPlayer2; ?></span><br />

<div class="action">
</div>

Maintenant, on avance un petit peu : on veux les différentes actions possibles. Pour cela, rien de plus simple : il nous suffit d'ajouter un test sur l'état actuel du combat ! Et bien entendu, il nous faut savoir quel joueur nous sommes ; un simple test nous le dira.

Code :
<?php

$table = new BattleTable;

$row = $table->findRowWhere('battle = ?', $_SESSION['battleId']);
$isPlayer1 = $userId == $row->player1;

$canAttack = ($row->currentStep == 'PLAYER1_ATTACK' && $isPlayer1) || ($row->currentStep == 'PLAYER2_ATTACK' && $isPlayer2);
$canAvoid = ($row->currentStep == 'PLAYER1_AVOID' && $isPlayer1) || ($row->currentStep == 'PLAYER2_AVOID' && $isPlayer2);

?>

<div id="battle">
Player 1's life : <span id="hpPlayer1"><?php echo $row->hpPlayer1; ?></span><br />
Player 2's life : <span id="hpPlayer2"><?php echo $row->hpPlayer2; ?></span><br />

<div class="action">
<?php
if ($canAttack) {
?>
<a href='attack.php'>Attack</a>
<a href='pass.php'>Do nothing</a>
<?php
}
?>
<?php
if ($canAvoid) {
?>
<a href='avoid.php'>Avoid</a>
<a href='pass.php'>Do nothing</a>
<?php
}
?>
</div>

Ok, notre page de combat est maintenant prête ! Il ne nous reste plus qu'à coder les pages d'attaque, d'esquive et pour passer. Commençons par la plus simple : la phase d'attaque. Ici, rien de bien difficile, on va simplement enregistrer la valeur d'attaque dans la ligne de base de données ; le but est d'éviter de diminuer les points de vie directement pour pouvoir réduire les dégâts avec l'esquive. Ça nous donne donc :

Code :
$table = new BattleTable;

$row = $table->findRowWhere('battle = ?', $_SESSION['battleId']);

// Note : tu devrais probablement vérifier ici si c'est bien à nous de jouer !

$row->incomingDamages = $attackValue;
$row->currentStep = ($row->currentStep == 'PLAYER1_ATTACK' ? 'PLAYER2_AVOID' : 'PLAYER1_AVOID');

$row->save();

redirect('battle.php');

Voila pour l'attaque, dans sa forme la plus simple (et la moins sécurisée - voir mes commentaires !). Maintenant, l'esquive. Elle fonctionne presque pareil, si ce n'est qu'elle va infliger des dégâts :

Code :
$table = new BattleTable;

$row = $table->findRowWhere('battle = ?', $_SESSION['battleId']);

// A nouveau, il faudrait vérifier que c'est bien à nous de jouer !

$playerNumber = $row->player1 == $userId ? 1 : 2;
$otherPlayerNumber = $playerNumber == 1 ? 2 : 1;

$damagesToInflict = $row->incomingDamages - $avoidanceValue;

if ($damagesToInflict < 0)
$damagesToInflict = 0;

$columnToModify = 'hpPlayer' . $otherPlayerNumber;
$row->$columnToModify -= $damagesToInflict;

// Gérer la mort ici

$row->currentStep = "PLAYER{$otherPlayerNumber}_ATTACK";
$row->save();

redirect('battle.php');

Il ne nous reste enfin que la possibilité de ne rien faire. Là, un petit switch peut nous simplifier la vie. Note qu'il n'y a pas d'esquive si l'adversaire n'a pas attaqué :

Code :
$table = new BattleTable;

$row = $table->findRowWhere('battle = ?', $_SESSION['battleId']);

switch ($row->currentStep)
{
case 'PLAYER1_ATTACK':
$row->currentStep = 'PLAYER2_ATTACK';
break;

case 'PLAYER1_AVOID:
// Ici, on doit du coup infliger les dégâts
$row->hpPlayer1 -= $row->incomingDamage;
$row->currentStep = 'PLAYER2_ATTACK';
break;

case 'PLAYER2_ATTACK':
$row->currentStep = 'PLAYER1_ATTACK';
break;

case 'PLAYER2_AVOID':
$row->hpPlayer2 -= $row->incomingDamage;
$row->currentStep = 'PLAYER1_ATTACK';
break;
}

$row->save();
redirect('battle.php');

Et voila ! Comme la partie concernée de la page va se recharger toute seule via ajax régulièrement, tu n'auras au final jamais d'affiché que ce qui doit l'être, mais le combat évoluera de lui-même. L'interval du setInterval déterminera la vitesse de rafraichissement (pas de push dans ce cas donc à toi de faire la part des choses entre la bande passante et le confort des joueurs !).

Note qu'une bonne partie de tout ce code (en particulier la gestion des dégats) gagnerait à être transféré dans une classe à part ; ce n'est que pour te donner une idée générale.


RE: le Pvp en Php/SQL/Ajax - Taressik - 20-04-2014

Oh.. je peux t'epouser ? :O !!!! Merci beaucoup tu as eclairé vraiment mes idées.. c'est superbe ! Je comprend Mieux !


RE: le Pvp en Php/SQL/Ajax - Ekilio - 20-04-2014

Avec plaisir Smile N'hésites pas si tu as besoin de plus d'informations ou quoi que ce soit !

Et pour les demandes en mariage, j'attendrais de revenir de Corée du Sud avant de répondre :p


RE: le Pvp en Php/SQL/Ajax - Taressik - 20-04-2014

Ahh ! J'attendrais alors Tongue !
j'ai une petite question que represente " createRow() " dans $battleRow = $table->createRow();


RE: le Pvp en Php/SQL/Ajax - Ekilio - 20-04-2014

C'est la création d'un nouvel objet dans la base de données vide. Je me suis inspiré du modèle de Zend Framework 1 ; mais si tu utilises un autre système, il suffit en fait de créer un nouvel enregistrement dans ta table avec les données qui sont créées à ce moment-là Smile