JeuWeb - Crée ton jeu par navigateur

Version complète : [PHP] Programmation événementielle - Scripter les actions
Vous consultez actuellement la version basse qualité d'un document. Voir la version complète avec le bon formatage.
Salut à tous,

Depuis quelques temps, je travaille sur un système permettant de scripter des tas de choses pour Seelies , du système de combats aux réactions des créatures, en passant par la gestion des ressources ou même des constructions.

Je commence donc à développer le concept pour le système de combat. L'idée est de modéliser une capacité par un objet JSON, avec différents paramètres et événements.

Voici par exemple la façon dont est codé la capacité Attack : Pastebin.

Le but est donc de créer une fonction PHP du genre resolve($action, $settings) qui prend donc le nom de l'action et les paramètres sous forme de tableau :

Code PHP :
$charOne->resolve('Attack', array(
    
"castingUnit"    => "Sephi-Chan",
    
"targetedUnit"    => "Dryops"
    
)
); 

Le système gérerai la récursivité (sur l'évenement onCounter, le personnage qui a contré lance à son tour une attaque).

Je finirai mon post de retour chez moi. J'attends vos suggestions sur l'idée et éventuellement des pistes de réalisations.


Sephi-Chan
Ton "resolve" fait furieusement penser à un "notify" qu'on retrouve dans l'orienté évènement 16

Tu dois certainement avoir des objets qui "écoutent" en attente de l'action "Attack", puis renvoient l'évènement à d'autres objets, etc... On est vraiment dans du Event, et si tu regardes dE ce coté tu trouveras beaucoup de matériau 16
Je ne sais pas vraiment de quoi tu parles. Les rares fois où j'ai concrètement entendu parler de programmation événementielle, c'est au sujet de Visual Basic, que j'ai commencé à pratiquer à l'école récemment.

Pourrais-tu m'en dire un peu plus, s'il te plaît ? Où bien me donner quelques pistes supplémentaires (des recherches Google sur l'orienté événement ou sur l'événementiel n'ont pas été très fructueuses), que je cherche de mon côté.

L'idée est d'interpréter ce fichier pour remplacer les substituts par leur valeur (première difficulté) puis ensuite de provoquer les actions en conséquences (seconde difficulté) et de gérer la récursivité (troisième difficulté).


Sephi-Chan, qui a dû booter sur sa partition Vista pour faire du VB.NET…
En fait c'est assez simple :
- 1 objet "écoute" un évènement donné
- 1 autre objet "provoque" l'évènement, et à ce moment tous les objets qui sont en train d'écouter l'évènement (ou juste la cible de l'évènement si c'est un évènement ciblé, comme un click sur un bouton) le reçoivent.

L'idée c'est d'avoir un registre global qui contient l'information "qui écoute quoi". Chacun des objets "écouteur" a associé un évènement à une fonction de callback.
Ensuite on lance l'évènement :
- soit de manière globale, et là tous les objets enregistrés comme écouteurs pour cet évènements sont notifiés
- soit de manière ciblée, et seul l'objet en question est notifié
Un objet écouteur qui reçoit une notification d'évènement agit en conséquence, en exécutant sa fonction de callback.

Dans ton cas ça donnerait quelque chose comme ça :
Code PHP :
class Seelie extends EventListener
{

  public function 
__construct()
  {
    
// on écoute l'évènement "attack" et "attack.counter" (contre-attaque)
    
$this->registerEvent('attack', array($this'onAttack'));
    
$this->registerEvent('attack.counter', array($this'onAttack'));
    
// on écoute l'évènement "attacked" et "attacked.counter" (contre-attaque)
    
$this->registerEvent('attacked', array($this'onAttacked'));
    
$this->registerEvent('attacked.counter', array($this'onAttacked'));
  }

  public function 
onAttack(Event $event)
  {
    
$jetAttaque mt_rand(1,100); // mon jet pour toucher
    
$jetDegats mt_randt(1,30); // mon jet de dégats, en fonction de mon arme
    // On construit l'évènement
    
$settings = array('attacker' => $this'attack' => array('touch' => $jetAttaque'damages' => $jetDegats));
    
$event_name $event->getName() == 'attack.counter' 'attacked.counter' 'attacked';
    
// On lance l'évènement "attacked" ou "attacked.counter" sur la cible de l'attaque
    
$event Events::notify($event->get('target'), $event_name$settings);
  }

  public function 
onAttacked(Event $event)
  {
    
$jetEsquive mt_rand(1100); // mon esquive
    
$jetArmure mt_rand(110); // ma réduction de dégats
    
if ($event->get('attack.touch') > $jetEsquive) {
      
// Argh ! je suis touché !
      
$degats max(0$event->get('attack.damages') - $jetArmure);
      
// perdre de la vie, etc... etc...
    
}
    
// Je contre-attaque, seulement si j'étais la cible d'une attaque normale
    
if ($event->getName() == 'attacked') {
      
// Je lance une contre-attaque, en me notifiant de l'évènement "attack.counter" avec pour cible mon attaquant
      
Events::notify($this'attack.counter', array('target' => $event->get('attacker')));
    }
  }



Voir le code du gestionnaire d'évènement

C'est un peu "brut de décoffrage" mais le concept est là, et une implémentation simpliste (enfin pas si simpliste que ça, mais il y a pas mal de chose qui ne sont pas gérées comme les règles de propagation d'évènements).
J'essaye de déchiffrer tout ça et je dois reconnaître que j'ai bien du mal ! Je n'arrête pas de faire des sauts dans le code.

L'une des choses qui me perturbe, c'est le passage en argument d'objets. Le systèmes que tu proposes (c'est toi qui l'a mis au point ?) y recourt beaucoup. Il faut que je m'y fasse.

En tout cas, c'est très enrichissant. Merci beaucoup de partager ça, Naholyr. 2


Sephi-Chan, qui continue son exploration du code source…
Le set de classes que je t'ai mis en pastebin j'en suis l'auteur oui, mais je n'ai pas inventé la programmation évènementielle 8

Le concept de base est celui que je t'ai énoncé : un registre qui enregistre les déclarations d'écoute et qui se charge de distribuer les évènements, et des écouteurs (qui s'enregistrent auprès du registre) qui agissent à la notification d'évènement.
Là où les implémentations diffèrent, c'est au niveau de la façon dont on va traiter les infos supplémentaires, ce que va véhiculer l'évènement, la façon dont l'évènement se propage ou non, la façon dont on gère les valeurs de retour, etc... Là il y a mille façons de faire 16

Deux petits liens pour aller plus loin :
- un autre set de classes, plus complet : http://www.phpclasses.org/browse/package/2783.html
- le chapitre "events" de Symfony : http://www.symfony-project.org/book/1_1/...ony#Events
Si tu veux un bon exemple de langage evenementiel, je te conseille de jeter un coup d'oeil a la facon dont ActionScript 3 marche, ca me paraitrait etre une tres bonne base pour construire quelque chose d'evenementiel en php.
Si je ne me trompe pas c'est le principe du design Pattern Observer ce que naholyr te dit.
Donc au pire si tu ne comprends pas son explication regarde de ce côté là.

Ca me fait penser que ça peut toujours servir ça, faut que je vois ça.
La discussion n'est plus vraiment d'actualité… 16


Sephi-Chan
URLs de référence