Network multiplayer pygame
server.py
import socket # Import socket moduleserver_ip = "127.0.0.1" # Server host IP address on the networks = socket.socket() # Create a socket objects.bind((server_ip, 5000)) # Bind to the IP and service ports.listen(5) # Listen and set maximum connectionspool = set() # For tracking concurrent connectionsimport threadingimport jsondef gameThread(client, address):try:pool.add(client) # On connect join the poolprint(address, 'joined the game.')while True:raw = client.recv(1024).decode("utf-8") # Recieve data into a string buffer with a maximum size of 1024bytes at one time# "For best match with hardware and network realities, the value of bufsize should be a relativelysmall power of 2, for example, 4096"# Source: https://docs.python.org/3/library/socket.htmldata = 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 receivedexcept (BrokenPipeError, IOError): # Client socket disconnect, triggers a "SIGPIPE" or "brokenpipe" signalprint(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 poolclient.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 socketserver_ip = "127.0.0.1" # Server host IP address on the networks = socket.socket()s.connect((server_ip, 5000))import timeimport pygamepygame.init()screen = pygame.display.set_mode((400, 300))done = Falseclock = pygame.time.Clock()x,y = 170,120 #start square in middle centreimport json #for sending and receiving data using a clean syntaxother_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 varx,y = data['x'],data['y'] #other x,yother_players.update( {ip+':'+str(port):{'x':int(x),'y':int(y)}} )except:passimport threadinglistener = threading.Thread(target=updateOtherPlayersMovements)listener.start()while not done:pygame.event.clear()pressed = pygame.key.get_pressed()if pressed[pygame.K_UP]: y = y - 3if pressed[pygame.K_DOWN]: y = y + 3if pressed[pygame.K_LEFT]: x = x - 3if pressed[pygame.K_RIGHT]: x = x + 3if pressed:s.send( json.dumps({'x':x, 'y':y}).encode('utf-8') )screen.fill((255, 255, 255)) #white backgroundpygame.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()