Dernière séance : Axel nous met un jeu en réseau

Pour cette dernière séance, Axel a accepté le challenge : prendre la main de la classe virtuelle et coder un petit jeu pygame ou une petite interface de type « grille » en réseau.

Moi, j’ai uniquement posé des questions. Respect Axel !

On y parle de Threads et de Sockets mais aussi de classe avec des instances dont les attributs sont des dictionnaires… Un sacré tour d’horizon de ce qu’on a appris dans ce cycle NSI.

Bravo et merci Axel ! Les codes en cliquant sur « lire la suite »


Émotion de finir ce cycle terminal avec des élèves géniales et géniaux, un plaisir de vous côtoyer depuis un, deux, parfois trois ans (avec l’ancienne option de seconde ICN).

Au revoir ! Bonne continuation !

Le client / jeu

from socket import *
from threading import Thread
from time import time, sleep

ip = "localhost" # / "127.0.0.1"
port = 16168

uuid = time()
last_event = 0
events = []
joueur2 = []

def connect_c(ip, port):
    try:
        client = socket(AF_INET, SOCK_STREAM)
        server = (ip, port)
        client.settimeout(4) # 10 secondes avant annulation de la connexion
        client.connect(server)
        if client.recv(16).decode() == "ok":
            print("Connecté")
            global message
            message = ["Connecté...", 60]
            while not socket_cc.stop:
                if socket_cc.envoi != []:
                    data = str(socket_cc.envoi)
                    socket_cc.envoi = []
                    try:
                        reply = sending(data, client)
                        if reply != None:
                            socket_cc.recup = reply.copy()
                        else:
                            break #socket_cc.stop = True
                    except:
                        pass
                else:
                    sleep(1 / 61)
    except:
        pass
    print("Pas de connexion")
    message = ["Déconnecté ;(", -1] #¤
    socket_cc.recup = [] # La connexion est terminée, on supprime les données

def sending(data, client):
    client.send(str.encode(data))
    return eval(client.recv(2048).decode("utf-8"))

class Multi_c:
    def __init__(self):
        self.envoi = []
        self.recup = []
        self.stop = False # Variable pour stopper la connexion
    def recup_infos(self):
        "Récupère les données transmises par le serveur. [] si aucune"
        return self.recup.copy()
    def envoyer_infos(self, infos):
        "Doit être une liste : [uuid, + autres variables]"
        self.envoi = infos

socket_cc = Multi_c() # Socket classe client
connexion_serveur = Thread(target = connect_c, args = [ip, port])
connexion_serveur.start()
message = ["Recherche serveur...", -1]






import pygame
from pygame.locals import *

pygame.init()

largeur = 10
hauteur = 10
taille = 60

grille = [[0] * largeur for ligne in range(hauteur)]

fenetre = pygame.display.set_mode((largeur * taille, hauteur * taille))

pygame.display.set_caption("Jeu PYTON")


clock = pygame.time.Clock()


x_curseur, y_curseur = -1, -1
x_click, y_click = -1, -1

#message = ["", 0]

pseudo = "Joueur"
tour = 1

continuer = True

def affichage():
    fenetre.fill((42, 42, 42))
    for y in range(hauteur):
        for x in range(largeur):
            if grille[y][x] == 0:
                pygame.draw.rect(fenetre, (192, 192, 192), \
                                 (x * taille + 1, y * taille + 1, taille - 2, taille - 2), 0)
            elif grille[y][x] == 1:
                pygame.draw.rect(fenetre, (0, 192, 0), \
                                 (x * taille + 1, y * taille + 1, taille - 2, taille - 2), 0) # case verte
            elif grille[y][x] == 2:
                pygame.draw.rect(fenetre, (192, 0, 0), \
                                 (x * taille + 1, y * taille + 1, taille - 2, taille - 2), 0) # case rouge
    if message[1] != 0:
        message[1] -=1
        text(message[0], (255, 0, 0), 42, 10, 10)
    pygame.display.flip()

fonts = {}
def text(text, color, size, x, y):
    if size not in fonts:
        fonts[size] = pygame.font.SysFont("Arial", size)
    fenetre.blit(fonts[size].render(text, True, color), (x, y))


while continuer:
    clock.tick(60)

    for event in pygame.event.get():
        if event.type == QUIT:
            continuer = False
        elif event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                continuer = False
        elif event.type == MOUSEMOTION:
            x_curseur, y_curseur = event.pos
        elif event.type == MOUSEBUTTONDOWN:
            if tour == 1:
                x_click, y_click = x_curseur, y_curseur


    recup = socket_cc.recup_infos()
    if len(recup) == 1:
        tour = 2

    for liste_joueur in recup:
        if liste_joueur[0] != uuid:
            joueur2 = liste_joueur

    if joueur2 != []:

        # On gère les évènements de l'autre joueur
        for event in joueur2[3]:
            # evnt = [uuid, type, infos+]
            if event[0] > last_event:
                last_event = event[0]

                if event[1] == "click":
                    x_click, y_click = event[2], event[3]

                """elif event[1] == "tirer":
                    ...""" # Pour un autre jeu par ex


        # On compare nos évènements avec le last_event du joueur 2
        invalid = 0
        for my_event in events:
            if my_event[0] < joueur2[2]:
                invalid += 1
        events = events[invalid:]






    if x_click > -1 or y_click > -1:
        grille[y_click // taille][x_click // taille] = tour
        if tour == 1:
            events.append([time(), "click", x_click, y_click]) # Si je joue, envoie l'évènement
        tour += 1
        if tour > 2:
            tour = 1
        x_click, y_click = -1, -1

    socket_cc.envoyer_infos([uuid, pseudo, last_event, events])

    affichage()

    

pygame.quit()

Le serveur

from socket import *
from threading import Thread

port = 16168
joueurs_max = 2



"""
Serveur:
    Recois:
        [uuid, + autres variables]
    Envoie:
        [[uuid, + autres variables], [uuid, + autres variables], ...] # Les infos de chaque joueur
"""

def client(conn, addr):
    try:
        uuid = 0
        conn.send(str.encode("ok"))
    except:
        pass
    print("Une connexion", addr)

    while True:
        try:
            data = conn.recv(2048).decode("utf-8")
            data = eval(data)

            if not data:
                break
            else:
                uuid = data[0]
                if uuid == 0:
                    break
                else:
                    socket_cs.infos_joueurs[uuid] = data

                    prepare_envoyer = socket_cs.infos_joueurs.copy()
                    conn.sendall(str.encode(str(list(prepare_envoyer.values()))))
        except:
            break

    try:
        socket_cs.nb_joueurs -= 1
        if uuid != 0:
            del socket_cs.infos_joueurs[uuid]
    except:
        pass

    try:
        conn.close()
    except:
        pass
    print("Une déconnexion", addr)

class Multi_s:
    def __init__(self, joueurs_max):
        self.nb_joueurs = 0
        self.joueurs_max = joueurs_max
        self.infos_joueurs = {} # uuid : [uuid, + autres variables]

def connect_s(port, joueurs_max):
    try:
        global socket_cs
        socket_cs = Multi_s(joueurs_max) # Socket classe serveur

        s = socket(AF_INET, SOCK_STREAM)

        s.bind(("", port))
        s.listen(4)
        print("Serveur lancé")
        while True:
            try:
                conn, addr = s.accept()
                conn.settimeout(10) # 10 secondes
                if socket_cs.nb_joueurs < socket_cs.joueurs_max:
                    socket_cs.nb_joueurs += 1
                    nouveau_client = Thread(target = client, args = [conn, addr])
                    nouveau_client.start()
            except:
                pass
    except:
        pass

try:
    serveur = Thread(target = connect_s, args = [port, joueurs_max])
    serveur.start()
except:
    pass

input("")

N'hésitez-pas à poser une question, ou faire avancer le schmilblick

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l’aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Google

Vous commentez à l’aide de votre compte Google. Déconnexion /  Changer )

Image Twitter

Vous commentez à l’aide de votre compte Twitter. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l’aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur la façon dont les données de vos commentaires sont traitées.