pythonpython-3.xpygamepython-sockets

How to update a position in Pygame after it has been sent over a socket server


I am making a program in Pygame to allow 2 people to connect to a server and send their positions to the server.

The server will:

1 - Identify which player sent their position

2 - Wait for both players to send their positions in

3 - Send out the positions according to the player (player_1 position goes to player 2, etc.)

So far, I am testing with one client, so I am sending player1's position to the server, which sends it back to the same client (me) and I draw that position as player2.

But for some reason the client can send the position data, but Pygame draws player2 across my whole screen, even though I specified a width and height of player 2.

Here is the server code

import NKSERVER
import time

id_1_occupied = True
id_2_occupied = False

print(id_1_occupied, id_2_occupied)

addr_p1 = ''
addr_p2 = ''

p1_pos = (0, 0)
p2_pos = (0, 0)

clients_ready = False

queue = 0

ip = '192.168.158.117'
port = 5555

serv = NKSERVER.server(ip, port)
print('Server Started')

serv.listen(2)

while True:
    conn, addr = serv.server.accept()

    recv = conn.recv(2048)
    recv_data = recv.decode('utf-8')
    print('Data received as:', recv_data)

    if clients_ready == False:
        # Check if the client wants an ID
        if recv_data == 'ClientReqId':
            # Check for an avaliable id
            if id_1_occupied == False:
                # Assign an id to the player
                addr_p1 = addr

                # Make a "new_client" object and assign it to the player
                player_1 = NKSERVER.new_client(addr_p1)

                # Send the ID data back to the player
                serv.send_to_client('id1', player_1.addr, conn)
                time.sleep(1)
                print('Sent id to player')

                id_1_occupied = True

            if id_2_occupied == False:
                if id_1_occupied == True:
                    # Check if we are not double-sending an id
                    if addr == addr_p1:
                        print('Player already has an id assigned')
                    else:
                        # Assign an id to the player
                        addr_p2 = addr

                        # Make a "new_client" object and assign it to the player
                        player_2 = NKSERVER.new_client(addr_p2)

                        # Send the id data back to the player
                        serv.send_to_client('id2', player_2.addr, conn)
                        time.sleep(1)
                        print('Sent id to player')

                        id_2_occupied = True

                        print('INIT: StartPosUpdate')
                        serv.send_to_client('StartPosUpdate', player_2.addr, conn)

                        print('Sent: StartPosUpdate')
                else:
                    pass

            # Check if our clients are ready to play
            if id_1_occupied == True:
                if id_2_occupied == True:
                    clients_ready = True

    while clients_ready:
        recv = conn.recv(2048)
        recv_data = recv.decode('utf-8')
        print('Data received as:', recv_data)

        # Add "CheckStat" in case our client did not receive "StartPosUpdate"
        if recv_data == 'CheckStat':
            print('INIT: CheckStat')

            print('INIT: StartPosUpdate')
            serv.send_to_client('StartPosUpdate', player_2.addr, conn)

            print('Sent: StartPosUpdate')

        # Once our clients are ready, deal with updating player positions
        if recv_data != 'CheckStat':
            if recv_data != 'ClientReqId':
                if clients_ready == True:
                    if queue < 1:
                        if addr == addr_p1:
                            p1_pos = recv_data
                            queue += 1

                        if addr == addr_p2:
                            p2_pos = recv_data
                            queue += 1

                    if queue > 0:
                        serv.send_to_client(p2_pos, player_2.addr, conn)
                        queue = 0

Here is the client code

# Import modules
import pygame as p
import NKNET

p.init()

# Player variables
p_width = 100
p_height = 100
p_velocity = 2

# Position variables
p2_pos = None
p2_x = 0
p2_y = 0

# Server variables
ip = '192.168.158.117'
port = 5555

# ID Variables
local_id = ''

# Timer event to send position
send_pos = p.time.set_timer(p.USEREVENT, 1000)


# Set up the screen
width = 1000
height = 700
sc = p.display.set_mode((width, height))
p.display.set_caption('Barebones: By Nathan Keidel')

# Start our client
client = NKNET.network(ip, port, local_id)

# Ask the server to give us an ID
client.get_id()
print(client.id)

# Make a player class
class player:
    def __init__(self, x, y, player_width, player_height, vel, color):
        self.x = x
        self.y = y
        self.width = player_width
        self.height = player_height
        self.vel = vel
        self.color = color

        self.rect = (x, y, width, height)

    def draw(self, window):
        p.draw.rect(window, self.color, self.rect)

    def move_player(self):
        keys = p.key.get_pressed()

        if keys[p.K_a]:
            self.x -= self.vel
        if keys[p.K_d]:
            self.x += self.vel
        if keys[p.K_w]:
            self.y -= self.vel
        if keys[p.K_s]:
            self.y += self.vel

        self.rect = (self.x, self.y, self.width, self.height)

    def set_boundires_to_window(self):
        if self.y <= 0:
            self.y = 1

        if self.y >= height - p_height:
            self.y -= 3

        if self.x <= 0:
            self.x = 1

        if self.x >= width - p_width:
            self.x -= 3
        else:
            pass

# Update window funtion
def update_window(player_1, window):
    sc.fill('black')
    player_1.draw(window)

def main():
    run = False

    player1 = player(100, 100, p_width, p_height, p_velocity, (0,255,0))
    player2 = player(p2_x, p2_y, p_width, p_height, p_velocity, (0, 0, 255))

    # Make sure we receive the "StartPosUpdate" message from the server
    while True:
        client.recv_with_backup('CheckStat')
        print('Data received as:', client.recv_data)

        if client.recv_data == None:
            print('INIT: CheckStat')
            client.send('CheckStat')
            print('Sent: CheckStat')

        if client.recv_data == 'StartPosUpdate':
            print('INIT: StartPos')
            run = True
            break

    while run:
        for event in p.event.get():
            if event.type == p.QUIT:
                run = False
                p.quit()

        # Make a "player1_pos" var so we can cleanly send the position data to the server
        player1_pos = (player1.x, player1.y)
        print('player1 position:', player1_pos)

        client.send(str(player1_pos))

        client.recv()

        p2_pos = client.recv_data
        p2_pos = (tuple(map(int, p2_pos.strip("()").split(","))))

        (player2.x, player2.y) = p2_pos
        print('player2 position:', p2_pos)

        player1.set_boundires_to_window()
        player1.move_player()


        update_window(player1, sc)
        update_window(player2, sc)

        p.display.update()

main()

Custom modules used for these 2

import socket

class network:
    def __init__(self, ip, port, id):
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_ip = str(ip)
        self.port = int(port)
        self.addr = (self.server_ip, self.port)
        self.id = id

        self.conn = self.connect()
        self.recv_data = None

    def connect(self):
        try:
            # Connect to the server
            self.client.connect(self.addr)
        except socket.error as e:
            print(e)

    def send(self, data):
        try:
            self.client.send(str.encode(data))
        except socket.error as e:
            print(e)

    def recv(self):
        try:
            self.recv_data = self.client.recv(2048).decode('utf-8')
        except socket.error as e:
            print(e)

    def recv_with_backup(self, backup_data):
        try:
            self.recv_data = self.client.recv(2048).decode('utf-8')

            if self.recv_data == None:
                self.send(backup_data)
            else:
                pass
        except socket.error as e:
            print(e)

    def get_id(self):
        try:
            self.client.send(str.encode('ClientReqId'))
            self.id = self.client.recv(2048).decode('utf-8')

            if self.id == None:
                self.get_id()
            else:
                pass
        except socket.error as e:
            print(e)

# Import socket
import socket

# Make a server class
class server:
    def __init__(self, ip, port):
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.ip = ip
        self.port = port
        try:
            self.server.bind((self.ip, self.port))
        except socket.error as e:
            str(e)

    def listen(self, num_of_conns):
        self.server.listen(num_of_conns)

    def accept(self):
        self.server.accept()

    def send_to_client(self, data, addr, conn):
        conn.sendto(str.encode(data), addr)

    def send_to_all_clients(self, data, conn):
        conn.sendall(str.encode(data))

# Make a class to store the data of a new client
class new_client:
    def __init__(self, addr):
        self.addr = addr

Solution

  • Look at this line:

    self.rect = (x, y, width, height)
    

    width is 1000, and height is 700, so the rect covers the entire screen.

    I guess you want to use:

    self.rect = (x, y, self.width, self.height)
    

    or

    self.rect = (x, y, player_width, player_height)
    

    instead.