Network multiplayer pygame
server.py
import socket # Import socket module server_ip = "127.0.0.1" # Server host IP address on the network s = socket.socket() # Create a socket object s.bind((server_ip, 5000)) # Bind to the IP and service port s.listen(5) # Listen and set maximum connections pool = set() # For tracking concurrent connections import threading import json def gameThread(client, address): try: pool.add(client) # On connect join the pool print(address, 'joined the game.') while True: raw = client.recv(1024).decode("utf-8") # Recieve data into a string buffer with a maximum size of 1024 bytes at one time # "For best match with hardware and network realities, the value of bufsize should be a relatively small power of 2, for example, 4096" # Source: https://docs.python.org/3/library/socket.html data = json.loads(raw) #e.g.: {'x': 287, 'y': 192} data['addr'] = address #now: {'x': 287, 'y': 192, 'addr': ('127.0.0.1', 57861)} for connection in pool: if connection != client: # For all OTHER connections listening in the pool: connection.send(json.dumps(data).encode("utf-8")) # Broadcast the data received except (BrokenPipeError, IOError): # Client socket disconnect, triggers a "SIGPIPE" or "broken pipe" signal print(address, 'left the game.') except Exception as e: print(address, 'had an error:', e) finally: pool.remove(client) # try except finally always comes last, remove from pool client.close() ## MAIN ## while True: client, address = s.accept() # Establish connection with client. # Create an activity that will run in a separate flow (or control) of execution (i.e., a Thread): t = threading.Thread(target=gameThread, args=(client, address)) t.start() # This program will therefore have multiple Threads (seemingly) happening at once
client.py
import socket server_ip = "127.0.0.1" # Server host IP address on the network s = socket.socket() s.connect((server_ip, 5000)) import time import pygame pygame.init() screen = pygame.display.set_mode((400, 300)) done = False clock = pygame.time.Clock() x,y = 170,120 #start square in middle centre import json #for sending and receiving data using a clean syntax other_players = {} def updateOtherPlayersMovements(): while True: try: raw = s.recv(1024).decode('utf-8') if raw: #e.g., data = ['275', '216', ('127.0.0.1', 57752)] data = json.loads(raw) #e.g.: {'x': 170, 'y': 120, 'addr': ['127.0.0.1', 57284]} ip,port = data['addr'] #other addr, [0] is ip, [1] is port int, unpacks to 2 var x,y = data['x'],data['y'] #other x,y other_players.update( {ip+':'+str(port):{'x':int(x),'y':int(y)}} ) except: pass import threading listener = threading.Thread(target=updateOtherPlayersMovements) listener.start() while not done: pygame.event.clear() pressed = pygame.key.get_pressed() if pressed[pygame.K_UP]: y = y - 3 if pressed[pygame.K_DOWN]: y = y + 3 if pressed[pygame.K_LEFT]: x = x - 3 if pressed[pygame.K_RIGHT]: x = x + 3 if pressed: s.send( json.dumps({'x':x, 'y':y}).encode('utf-8') ) screen.fill((255, 255, 255)) #white background pygame.draw.rect(screen, (0,0,0), pygame.Rect(x, y, 60, 60)) for player in other_players: other_x, other_y = other_players[player]['x'], other_players[player]['y'] pygame.draw.rect(screen, (255,0,0), pygame.Rect(other_x, other_y, 60, 60)) pygame.display.flip() clock.tick(60) pygame.quit()