Flayme
-
Modifié le 5 déc. 2022 à 12:04
mamiemando
Messages postés33545Date d'inscriptionjeudi 12 mai 2005StatutModérateurDernière intervention25 février 2025
-
9 déc. 2022 à 15:16
Bonjour,
Je suis en train de créer un jeu en ligne via le module socket.
Quand je lance le serveur et 2 clients depuis mon ordinateur windows ça marche.
Mais quand je lance n'importe quel programme (serveur ou client) depuis mon ordinateur linux, l'application ne marche pas (erreur -> json decode error ou aucune erreur et le programme attend)
Voici mon code:
server.py
import socket
import threading
import json
import random
class Server:def__init__(self, addr, port):
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((addr, port))
self.CARTES =(0,1)
self.GEARS =(0,1)
self.ok_message ="OK!"
self.nope_message ="NOPE!"
self.DECO ="DECO!"
self.games ={}
self.names ={}
self.map_ok ={}
self.map ={}
self.gear_ok ={}
self.gear ={}defstart(self):
self.server.listen()while True:
conn, _ = self.server.accept()
threading.Thread(target=self.handle_client, daemon=True, args=(conn,)).start()
@staticmethod
defrecv(conn):
inf = conn.recv(1024).decode()print(inf)try:return json.loads(inf)[0]except json.decoder.JSONDecodeError:return json.loads(repr([inf,]))
@staticmethod
defsend(conn, msg):
conn.send(json.dumps([msg,]).encode())defhandle_client(self, conn):# get usernamewhile True:
username = self.recv(conn)if username in self.names.values():
self.send(conn, self.nope_message)else:
self.send(conn, self.ok_message)
self.names[conn]= username
break# get type_game
type_game = self.recv(conn)ifnot self.games.get(type_game, False):
self.games[type_game]=[conn,]else:
self.games[type_game].append(conn)# get gamewhile True:
id_game =len(self.games[type_game])whilelen(self.games[type_game])<2:passif id_game ==1:
opp = self.games[type_game][id_game]breakelif id_game ==2:
opp = self.games[type_game][id_game -2]break
self.send(conn, self.ok_message)
self.recv(opp)
self.games[type_game].pop(self.games[type_game].index(conn))
self.send(conn,[id_game, self.names[opp]])# get map
carte = None
while carte notin self.CARTES:
carte = self.recv(conn)if carte in self.CARTES:
self.send(conn, self.ok_message)
self.map[conn]= carte
breakelse:
self.send(conn, self.nope_message)if id_game ==1:if self.map_ok.get((conn, opp))is None:
self.map_ok[(conn, opp)]=[True, False]else:
self.map_ok[(conn, opp)]=[True, True]whilenotall(self.map_ok[(conn, opp)]):pass
carte = random.choice([self.map[conn], self.map[opp]])
self.send(conn, carte)
self.send(opp, carte)else:if self.map_ok.get((opp, conn))is None:
self.map_ok[(opp, conn)]=[True, False]else:
self.map_ok[(opp, conn)]=[True, True]# gearprint("GETTING GEAR")
gear = None
while gear notin self.GEARS:
gear = self.recv(conn)
ok = True
for g in gear:if g notin self.GEARS:
ok = False
breakif ok:
self.send(conn, self.ok_message)
self.gear[conn]= gear
breakelse:
self.send(conn, self.nope_message)if id_game ==1:if self.gear_ok.get((conn, opp))is None:
self.gear_ok[(conn, opp)]=[True, False]else:
self.gear_ok[(conn, opp)]=[True, True]whilenotall(self.gear_ok[(conn, opp)]):passprint(self.gear[opp], self.gear[conn])
self.send(conn, self.gear[opp])
self.send(opp, self.gear[conn])else:if self.gear_ok.get((opp, conn))is None:
self.gear_ok[(opp, conn)]=[True, False]else:
self.gear_ok[(opp, conn)]=[True, True]# gamewhile True:
msg = self.recv(opp)
self.send(conn, msg)if __name__ =="__main__":
server =Server("localhost",5070)
server.start()
game.py
from networking import Client
import game
import pygame
deftest(addr, port):
x = y = x2 = y2 =100
j_moi = pygame.Surface((50,50))
j_moi.fill((255,0,0))
j_opp = pygame.Surface((50,50))
j_opp.fill((0,0,255))
clock = pygame.time.Clock()
aff_win = True
run = True
with Client(addr, port) as client:# get some info
name =input("Entrer un nom d'utilisateur: ")whilenot client.get_username(name):print("nom deja utilise!")
name =input("Entrer un nom d'utilisateur: ")
moi_aff = game.Afficher((0,0), name,(0,0,0),30)
id_game, opp = client.get_game("!PUBLIC")print("id_game:", id_game)print("opp:", opp)
opp_aff = game.Afficher((0,0), opp,(0,0,0),30)while True:
carte_inp =input("Entrer une carte: ")try:
carte_inp =int(carte_inp)-1except ValueError:print("Entrer le nombre de la carte!")continue
carte = client.get_map(carte_inp)if carte isnot None:breakprint("map n'existe pas!")print("carte:", carte)# gearwhile True:
gear =[]for i inrange(game.GEAR_LEN):while True:
inp =input("Entrer gear "+str(i +1)+": ")try:
inp =int(inp)-1breakexcept ValueError:print("Veuillez entrer le nombre du gear que vous voulez utiliser!")
gear.append(inp)
gear_opp = client.get_gear(gear)if gear_opp isnot None:breakprint("gear n'existe pas!")print("gear opp:", gear_opp)# game
pygame.init()
screen = pygame.display.set_mode((game.width, game.height))
pygame.display.set_caption(name)while True:for event in pygame.event.get():if event.type == pygame.QUIT:
run = False
aff_win = False
breakifnot run:break
key = pygame.key.get_pressed()if key[pygame.K_UP]:
y -= game.base_J_DEP[0]if key[pygame.K_DOWN]:
y += game.base_J_DEP[0]if key[pygame.K_LEFT]:
x -= game.base_J_DEP[0]if key[pygame.K_RIGHT]:
x += game.base_J_DEP[0]
info = client.dialogue([x, y])iflen(info)==1:if info == client.DECO:print("L'ADVERSAIRE C'EST DÉCONNECTER!!!!!")
run = False
eliflen(info)==2:
x2, y2 = info
moi_aff.update(x=x + moi_aff.surface.get_width()//2, y=y - moi_aff.surface.get_height())
opp_aff.update(x=x2 + opp_aff.surface.get_width()//2, y=y2 - opp_aff.surface.get_height())
screen.fill((255,255,255))
screen.blit(j_moi,(x, y))
screen.blit(j_opp,(x2, y2))
moi_aff.draw(screen)
opp_aff.draw(screen)
pygame.display.update()
clock.tick(60)if __name__ =="__main__":
addr =input("Entrer l'address: ")while True:
port =input("Entrer le port: ")try:
port =int(port)breakexcept ValueError:print("Veuillez entrer un nombre entier pour le port.")test(addr, port)
import pygame
class Sprite:
__list =[]
@classmethod
defget_list(cls):return cls.__list
def__init__(self, coord:(int, int), surface: pygame.Surface):
self.alive = True
self.show = True
self.x, self.y = coord
self.surface = surface
self.mask = pygame.mask.from_surface(self.surface)
self.__list.append(self)
self.nb =len(self.__list)
self.nom ="Sprite{}".format(self.nb)defdraw(self, screen: pygame.Surface):if self.alive and self.show:
screen.blit(self.surface,(self.x, self.y))defis_coliding(self, m):if m =="all":
check = self.__list
check.remove(self)eliftype(m)== tuple ortype(m)== list or m is None:
check = m
if m ==()or m ==[]or m is None:returnelifhasattr(m,"mask")andhasattr(m,"x")andhasattr(m,"y"):
check =(m,)else:raise(ValueError("parameter m is not valid, please enter \"all\" ""or a Mask or a tuple/list of Mask: not a {}".format(type(m))))
res =[]for sprite in check:if self.mask.overlap_mask(sprite.mask,(sprite.x - self.x, sprite.y - self.y)).count()!=0:try:if sprite.alive:
res.append(sprite)except AttributeError:
res.append(sprite)return res
def__str__(self):return self.nom
def__repr__(self):return"{}->x:{},y:{}".format(self.nom, self.x, self.y)defcheck_alive(self):ifnot self.alive:
self.__list.remove(self)defupdate(self):
self.check_alive()
mamiemando
Messages postés33545Date d'inscriptionjeudi 12 mai 2005StatutModérateurDernière intervention25 février 20257 829 5 déc. 2022 à 12:13
Bonjour,
Merci quand tu partages de préciser dans la cellule de code le langage de programmation (python).
Autant que possible, évite de mettre tout ton programme pour parler d'un problème précis. Il faut plutôt construire un exemple minimal qui met en évidence le problème, nous expliquer comment tu le lances, le comportement observé et le comportement attendu. Ici une grande partie du code partagé n'a vraisemblablement rien à avoir avec ton problème.
Vu que le projet est volumineux et contient des ressources qui ne sont pas du code (polices, images...) il vaudrait mieux mettre ton projet par exemple sur github et nous donner l'adresse du dépôt. Car là, il manque des fichiers pour tester ton code.
Je te propose de repartir sur cet exemple relativement minimal qui montre comment écrire en pygame un jeu multijoueur ou chaque joueur peut depuis sont client déplacer un carré qui lui est propre et voir le carré des autres joueurs.
Salut, si tu souhaites avoir de l'aide afin d'identifier ce qui cloche, fais un zip de ton application que tu hébergeras quelque part afin que l'on ait pas à copier/coller chacun de tes codes dans chaque fichier, et surtout que l'on a juste à lancer ton programme pour pouvoir le déboguer, et si possible réduire au minimum ton script, il n'y a certainement pas besoin de tout ces fichiers, essaie d'identifier celui où cela bogue, client, serveur, et json, pas besoin de pygame et tous ces packages.
Sinon, comme d'habitude, des prints, des exceptions pour comprndre où ton programme plante. Déjà je vois un ÉNORME problème, c'est que tu as un fichier game, et un package game, nomme les différemment ! Même si ça fonctionne en l'état.
Bon courage.
mamiemando
Messages postés33545Date d'inscriptionjeudi 12 mai 2005StatutModérateurDernière intervention25 février 20257 829 5 déc. 2022 à 13:31
Je pense que c'est voulu, ainsi import game importe game/__init__.py qui lui même importe toute une série de fichiers en cascade.
Pour corriger mon bug, j'ai encadré tout mes messages avec un caractère: "^" ce qui permet de savoir exactement ou commence et ou finit le message pour ne pas avoir d'interférence. Avant cela, il faut vérifier si le caractère est dans le message pour éviter les problèmes.
Je ne sais pas comment on fait pour marquer résolu ma question, donc si un modérateur pouvait le faire pour moi ce serait gentil.
Merci quand même d'avoir essayer de m'aider
Au revoir
Flayme
mamiemando
Messages postés33545Date d'inscriptionjeudi 12 mai 2005StatutModérateurDernière intervention25 février 20257 829 Modifié le 9 déc. 2022 à 15:53
Pour marquer une discussion en résolu, il faut faire comme expliqué dans ce lien, mais cela nécessite d'avoir un compte CCM. Bref, je m'en occupe.
Concernant ton problème, je reste un peu sceptique sur la manière dont tu l'as résolu. Voici un petit exemple qui met en évidence un client qui envoie chaque seconde une chaîne de caractère à 5 reprises vers un serveur qui réécrit le message reçu sur sa sortie standard. Comme tu peux le voir, il n'y a pas de délimiteur impliqué dans le code.
server.py
import socket
SERVER_BIND_ADDRESS ="localhost"
SERVER_PORT =8000
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:print(f"Starting server {SERVER_BIND_ADDRESS}:{SERVER_PORT}")
server.bind((SERVER_BIND_ADDRESS, SERVER_PORT))
server.listen()(client, client_addr)= server.accept()
with client:print(f"New client {client_addr}")while True:
data = client.recv(1024)# Fetch the data, 1024 bytes by 1024 bytesifnot data:break# No more data to fetch
message = data.decode("utf-8")print(message)
client.py
import socket
from time import sleep
SERVER_HOST ="localhost"# The server's hostname or IP address
SERVER_PORT =8000# The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client:print(f"Connect to {SERVER_HOST}:{SERVER_PORT}")
client.connect((SERVER_HOST, SERVER_PORT))for i inrange(5):
client.sendall(bytes(f"Hello, world {i}","utf-8"))sleep(1)
Utilisation
Lancer server.py dans un terminal
Puis lancer client.py dans un autre terminal
Résultat (terminal server.py)
Starting server localhost:8000
New client ('127.0.0.1', 60514)
Hello, world 0
Hello, world 1
Hello, world 2
Hello, world 3
Hello, world 4