0

I am coding a program that would allow multiple users to connect to a server at once and allow both of them to see both of their players. so far I have written some code that allows the players to see each other but their are some issues. For some reason my players are blitted twice in two positions where they both have the same x values but one has the right y value and the other has 10x times the y value. secondly, because of this issue my players are being blitted in one position or the other every tick and so are constantly flickering into and out of view. can anyone help with this issue.

import socket
import threading
import pygame

class Server():
    def __init__(self, port):
        self.host = (socket.gethostbyname(socket.gethostname()), port)
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server.bind(self.host)
        self.players = []
        self.positions = []

    def start(self, server):
        self.server.listen()
        while True:
            self.conn, self.addr = self.server.accept()
            self.players.append((self.conn, self.addr))
            self.positions.append((0, 0))
            self.thread = threading.Thread(target = server.handleConn, args = (self.conn, server))
            self.thread.start()
    
    def handleConn(self, conn, server):
        self.msg = str(len(self.players) - 1).encode("utf-8")
        conn.send(self.msg)
        self.connection = True
        while self.connection:
            self.msg = conn.recv(512).decode("utf-8")
            self.msg = self.msg.split(",", -1)
            if len(self.msg) >= 2:
                if self.msg[1] == "disconnect":
                    self.connection = False
                    for i in range(1, len(self.players) - 1):
                        self.msg = str(i).encode("utf-8")
                        self.players[i][0].send(self.msg)
                    self.players = []
                    self.positions = []
                else:
                    self.new_msg = []
                    self.plc = ""
                    for item in self.msg:
                        self.plc = ""
                        for char in item:
                            if char.isdigit() or char == "-":
                                self.plc += str(char)
                        self.new_msg.append(int(self.plc))
                    self.msg = self.new_msg
                    self.positions[int(self.msg[0])] = (int(self.msg[1]), int(self.msg[2]))
                    server.sendMsg((self.msg[0], self.positions[self.msg[0]]))


    def sendMsg(self, msg):
        self.msg = str(msg).encode("utf-8")
        for i in range(0, len(self.players)):
            self.players[i][0].send(self.msg)

class Client():
    def __init__(self, port):
        pygame.init()
        self.host = (socket.gethostbyname(socket.gethostname()), port)
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.x = 0
        self.y = 0
        self.run = True
        self.win = pygame.display.set_mode((700, 700))
        self.positions = []
        self.colours = [(255,0,0), (0,255,0), (0,0,255)]

    def start(self, client):
        self.client.connect(self.host)
        self.msg = self.client.recv(512).decode("utf-8")
        self.msg = self.msg.split(",", -1)
        self.id = self.msg[0]
        self.connected = True
        while self.connected:
            if self.run:
                pygame.time.delay(5)
                client.sendMsg((self.id, self.x, self.y))
                client.recvMsg()
                client.drawWin()
                client.update()
            else:
                client.sendMsg("disconnect")
                self.connected = False

    def sendMsg(self, msg):
        self.msg = str(msg).encode("utf-8")
        self.client.send(self.msg)

    def recvMsg(self):
        self.msg = self.client.recv(512).decode("utf-8")
        self.msg = self.msg.split(",", -1)
        self.new_msg = []
        self.plc = ""
        for item in self.msg:
            self.plc = ""
            for char in item:
                if char.isdigit() or char == "-":
                    self.plc += str(char)
            self.new_msg.append(int(self.plc))
        self.msg = self.new_msg
        if len(self.msg) >= 2:
            if self.msg[0] >= len(self.positions):
                self.positions.append("")
            self.positions[int(self.msg[0])] = (int(self.msg[1]), int(self.msg[2]))
        else:
            self.id = self.msg[0]
            self.positions = []

    def drawWin(self):
        self.win.fill((0,0,0))
        for i in range(0, len(self.positions)):
            pygame.draw.rect(self.win, self.colours[int(self.id)], (self.positions[i][0], self.positions[i][1], 32, 32))
            print(i, self.positions[i])
        pygame.display.update()

    def update(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_ESCAPE]:
            self.run = False
        if keys[pygame.K_w]:
            self.y -= 1
        if keys[pygame.K_a]:
            self.x -= 1
        if keys[pygame.K_s]:
            self.y += 1
        if keys[pygame.K_d]:
            self.x += 1
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.run = False
                choice.sendMsg("disconnect")
        if self.run == False:
            pygame.quit()

classes = [Server, Client]
port = int(input("4 digit port - "))
choice = classes[int(input("SERVER or CLIENT, 0 to 1 - "))](port)
choice.start(choice)
  • Can you factor out the game code to build a [mre] that has the smallest possible amount of socket-based code to reproduce the underlying problem without needing that logic to be embedded in a game? Or, if it's not socket-specific, factor out the socket code to have only pygame code? In general, the work of isolating a _narrow, specific_ technical issue and building the shortest possible program that reproduces that issue is part of the job to be done before asking a question here. – Charles Duffy Jul 03 '22 at 16:00
  • As an example of how one might go about factoring out the GUI -- if a problem is visible in where things render on screen, you should be able to make it be demonstrable when just printing coordinates to stdout. Similarly, if it currently requires user input (and thus input-handling), you can just hardcode the logic to assume that input is happening as and when it's necessary for it happen for the issue to reproduce. – Charles Duffy Jul 03 '22 at 16:01
  • This code also makes the same mistake that I see that almost all beginning python socket programmers make, the assumption that a `send()` of n bytes means that `recv()` will return n bytes. See https://stackoverflow.com/a/43420503/238704 – President James K. Polk Jul 03 '22 at 17:17
  • thank you all for your help. my problem was roughly around all of your suggestions and so you all helped. my problems were that my data wasn't being received as bytes so thank you and how my data being sent, when received was being concatenated and so the data was wrong. thank you for your help – GhostFighterz Jul 03 '22 at 19:19

0 Answers0