I am very new to python. I had several times that I got stuck when trying to learn, but I could eventually figure it out after looking up the error report. Now, after 8 hours of trying to solve this problem I am out of ideas.
I am trying to make a very simple networked (sort-of)game. The client tells the server the location of the mouse. The server adds the new client to its list of clients and sends the list of clients and their locations back to the client. After-which the client translates the values that were sent into circles on the screen.
tl;dr Everybody's mouse is supposed to be represented by a circle on the white background. Here is the code for the client:
import socket
import sys
import pygame
from pygame.locals import *
import inputbox
import threading
import Queue
import time
host = ''
port = 0
server_port = 5000
FPS = 60 # frames per second, the general speed of the program
WINDOWWIDTH = 1280 # size of window's width in pixels
WINDOWHEIGHT = 720 # size of windows' height in pixels
GRAY = (100, 100, 100)
NAVYBLUE = ( 60, 60, 100)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)
YELLOW = (255, 255, 0)
ORANGE = (255, 128, 0)
PURPLE = (255, 0, 255)
CYAN = ( 0, 255, 255)
BGCOLOR = WHITE
ALLCOLORS = (RED, GREEN, BLUE, YELLOW, ORANGE, PURPLE, CYAN)
def server_info_processing(name, sock, queue):
while True:
try:
while True:
data, addr = sock.recvfrom(1024)
queue.queue.clear()
queue.put(data)
except:
pass
def main():
players_pos = []
pygame.init()
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
FPSCLOCK = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
mousex = WINDOWWIDTH / 2
mousey = WINDOWHEIGHT / 2
s.bind((host, port))
s.setblocking(0)
q = Queue.Queue()
#server processing thread
sPThread = threading.Thread(target = server_info_processing, args = ("RecvThread", s, q))
sPThread.daemon = True
sPThread.start()
while True:
try:
answer = inputbox.ask(DISPLAYSURF, "Server IP")
s.sendto(str(mousex) + " " + str(mousey), (answer, server_port))
break
except Exception:
print "The IP address you entered is either not currently available or doesn't exist."
while True:
try:
players_pos = q.get_nowait()
q.task_done()
players_pos = eval(players_pos) #The server is returning a string, but we need a list.
except Queue.Empty:
pass
DISPLAYSURF.fill(BGCOLOR)
for event in pygame.event.get(): # event handling loop
if event.type == QUIT:
#send a msg to have the server delete this connection
print "Quitting."
s.sendto('quit', (answer, server_port))
pygame.quit()
s.close()
sys.exit()
elif event.type == MOUSEMOTION:
mousex, mousey = event.pos
s.sendto(str(mousex) + " " + str(mousey), (answer, server_port))
else:
pygame.event.clear()
allcolors_index = 0
for index, value in enumerate(players_pos):
if allcolors_index < len(ALLCOLORS):
current_color = ALLCOLORS[allcolors_index]
else:
allcolors_index = 0
current_color = ALLCOLORS[allcolors_index]
if value:
pygame.draw.circle(DISPLAYSURF, current_color, (int(players_pos[index][1][0]), int(players_pos[index][1][1])), 50)
allcolors_index += 1
pygame.display.flip()
FPSCLOCK.tick(FPS)
if __name__ == '__main__':
main()
Here is the server:
import socket
import time
import threading
host = ''
port = 5000
clients = []
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
s.setblocking(0)
peoples_pos = []
in_database = False
addr_location = None
print "Server Started"
while True:
try:
data, addr = s.recvfrom(1024)
for index, value in enumerate(peoples_pos):
if data == 'quit':
if addr == peoples_pos[index][0]:
#removing the item at the index that contains addr
del peoples_pos[index]
elif addr == peoples_pos[index][0]:
in_database = True
addr_location = index
if data != 'quit':
if in_database == False:
peoples_pos.append([])
peoples_pos[(len(peoples_pos)-1)].append(addr)
peoples_pos[(len(peoples_pos)-1)].append(data.split())
else:
peoples_pos[addr_location][1] = data.split()
in_database = False
print time.ctime(time.time()), peoples_pos
for index, value in enumerate(peoples_pos):
s.sendto(str(peoples_pos), peoples_pos[index][0])
except Exception as e:
pass
s.close()
Update 1: It seems that the main while loop in the client is running only once. If you put a print statement at the bottom of the loop, the text will be printed, but only once. I don't know why that is and whether it is a symptom or a cause or both.
Update 2: It seems like using q.get() is causing a problem by stopping the script until there is an item in the queue. I am not quite sure why. I have changed it to queue.get_nowait() and added a try except. Now when I move the mouse, circles show up but the old ones are not removed and the client crashes after about 3 seconds.
Update 3: It turns out the old circles were removed, but the server was sending the data of the old circles as if it was a new player. I fixed that bug then made my thread a daemon, because unless it is a daemon when I call sys.exit() the thread will not exit and I have to close the command prompt in order to recover. As far as I can tell the code is working as it should. Above is the new, corrected code.