Skip to article frontmatterSkip to article content

vous aurez besoin du zip qui se trouve ici

on se propose de réaliser un petit jeu multi joueur, et pour cela nous aurons besoin de

architecture

process et isolation

un jeu multi-joueur pose des défis qui vont au-delà de ce qu’on apprend dans un cours de programmation de base
en effet on apprend pour commencer à programmer dans un monde fini et isolé - l’OS appelle ça un process - qui par définition ne partage aucune donnée avec les autres programmes qui tournent dans le même ordinateur
typiquement quand vous écrivez un programme Python et que vous le lancez avec python mon_code.py, tout le code tourne dans un seul process
(sauf si vous faites exprès d’en créer d’autres bien entendu)

comment partager

du coup lorsqu’on veut faire jouer ensemble, disons deux personnes, on aurait en théorie le choix entre

mais avec cette deuxième approche il faut trouver un moyen d’échanger des informations:
chaque process a le contrôle sur la position de son joueur, mais a besoin d’obtenir les positions des autres joueurs

on va voir comment on peut s’y prendre

une solution centralisée

l’architecture la plus simple pour établir la communication entre tous les joueurs consiste à créer un processus serveur, auquel les joueurs sont connectés, selon un diagramme dit en étoile (terme qui prend tout son sens avec plusieurs joueurs: le serveur est au centre du diagramme) :

étape 0: comprendre le starter code

vous trouverez dans le zip un jeu fonctionnel; c’est très très vaguement inspiré du jeu du snake: vous controlez un joueur qui se matérialise par une case carrée que vous bougez avec les fleches du clavier

vous lancez le jeu en faisant

# ajoutez --help pour voir les options disponibles

python game.py pierre

votre première mission consiste donc à lire le code et à comprendre comment il fonctionne, au moins dans les grandes lignes
remarquez notamment qu’on a déjà prévu de passer un ‘server’ au programme en faisant

python game.py --server localhost pierre

mais que pour l’instant ce paramètre n’est pas utilisé

objectifs du TP

vous devez modifier ce code pour qu’il puisse fonctionner à plusieurs joueurs, potentiellement sur plusieurs ordinateurs

si vous vous sentez, vous pouvez vous lancer sans indication supplémentaire; sinon, lisez la suite

étape 1: installer redis

requirements

pour installer les librairies Python nécessaires, faites

pip install -r requirements.txt

installation de redis

en plus de la library Python, il vous faudra installer le serveur redis
sur toutes les plateformes, on peut l’installer avec conda install redis
voici aussi à tout hasard d’autres options, selon votre système d’exploitation

Windows
MacOS
Linux
  • autre option: memurai
    dont l’installation se charge de créer un service microsoft

pour lancer redis

pour commencer on va travailler uniquement en local (tous les process tournent sur l’ordinateur local); lancez le serveur redis avec

redis-server --protected-mode no

comme d’habitude, ce process ne se termine pas, donc il va monopoliser le terminal
il faut le laisser tourner pendant tout le temps du jeu
lancez un autre terminal pour continuer le travail

micro-cheatsheet redis

quelques astuces pour commencer:

voici une toute petite session pour vous montrer comment ça marche
je suppose qu’on vient juste de lancer un serveur tout neuf
pour simplifier on n’utilise qu’un seul interpréteur Python (comme toujours je vous recommande d’utiliser ipython), mais bien sûr vous pouvez essayer tout ça avec deux process Python différents

from redis import Redis
import json

# connect to server
redis_server = Redis("localhost", decode_responses=True)

# inspect keys - returns an empty list at first
redis_server.keys()

# one can only attach atoms (numbers or strings) to keys
# so we json-encode the data

# to set multiple fields
redis_server.hset('pierre',
  mapping = {
    'position': json.dumps([10, 20]),
    'color': json.dumps([255, 0, 0]),
  })

# to set only one field
redis_server.hset('pierre', 'position', json.dumps([20, 30]))

# to retrieve the full mapping for a key
redis_server.hgetall('pierre')
# -> would return
# {'position': '[20, 30]', 'color': '[255, 0, 0]'}
# remember the values are JSON-encoded

# at that point there is one key in the server (and it's a bytes)
len(redis_server.keys()) == 1

# it's important you make sure you clean up after yourself
# since the keys essentially give the list of players currently in the game
# remove a key
redis_server.delete('pierre')

étape 2: rendre le jeu multi-joueur

il vous faut maintenant modifier le code pour que le rendre multi-joueurs

quelques suggestions dans ce sens:

bien entendu vous commencez par faire marcher le jeu avec un seul joueur; une fois que ça fonctionne vous pouvez passer à deux joueurs
notez que la touche de raccourci a permet de passer en mode automatique, où le joueur se déplace tout seul au hasard

étape 3: jouer sur plusieurs ordinateurs

jusqu’ici on a fait tourner tous les processus dans le même ordinateur

en vraie grandeur bien sûr, on veut faire tourner ça sur plusieurs ordinateurs

pour jouer sur plusieurs ordinateurs, il nous reste quelques étapes - plus de codage, mais de la mise en place:

rendre le serveur redis joignable de l’extérieur

on va devoir lancer le serveur redis sur un des ordinateurs
peu importe où il est lancé (ça pourrait même être dans un cloud si on voulait), mais par contre il faut que les autres ordinateurs puissent y accéder

aussi on ne peut plus lancer le serveur redis avec localhost (qui est une adresse uniquement joignable depuis le même ordi); il va falloir utiliser cette fois une adresse IP visible de l’extérieur; pour cela, faire plutôt

# jacques lance le serveur comme ceci
redis-server --bind 0.0.0.0

trouver l’adresse IP du serveur

de cette façon le serveur redis sera joignable sur l’adresse IP de l’ordinateur; sur notre exemple c’est 192.168.0.20, mais comment on le sait ?

selon les systèmes, Jacques lance dans un terminal la commande suivante

Windows
MacOS
Linux
ipconfig

et cherche une adresse parmi les intervalles réservés aux adresses privées:

plagetaille
192.168.0.0/16216=65,5362^{16} = 65,536 adresses
172.16.0.0/12220=1,048,5762^{20} = 1,048,576 adresses
10.0.0.0/8224=16,777,2162^{24} = 16,777,216 adresses

utiliser le même code partout

il va falloir aussi que tout le monde utilise le même code; pour cela vous pouvez utiliser:

lancer le jeu

une fois que l’adresse IP est connue, tout le monde peut lancer le jeu avec

python game.py --server 192.169.0.20 chacun-son-nom-ici

et, si tout va bien, on a un jeu multi-joueur qui tourne en réseau

firewall

il y a toutefois une probabilité que ça ne marche pas du premier coup
en effet, les ordinateurs sont souvent protégés par un firewall qui bloque certains ports de communication
si c’est le cas avec l’ordi de Jacques, il va devoir trouver le moyen