I was a bit unhappy to read this, because what you describe here is
just what I've tried yesterday in my test-game with 2 balls, so if
I've pointed that out, you wouldn't have to say I
DLB don't understand threading either, it appears.
:'(
Thank you very much for putting so much effort in making things clear
to me, *this* email of your made everything clear as never. Still I
have problems, and hope you still don't mind me asking.
Some comments:
while 1:
render()
inp = get_player_input()
thread.start_new(send_inp, (inp,))
thread.start_new(accept_opponents_inp, ())
DLB You don't understand threading either, it appears. Here you are
DLB starting a new thread for each input you want...
and
while still_no_opponents_input_from_previous_iteration()
time.sleep(0.05)
DLB You're still focused on a turn based system, it looks like...
Now, that's *not* how I'm tending to do it; that's what I was thinking
of while trying the turn-based approach, and describing here;
Christopher Subich asked how it was done initially, so I brought my
hanging system out of shame again, and added something I was thinking
about to improve it, while I already realize that's not the way to go
- from your previous comprehensive posts.
DLB There should just be AN input thread, started at the very beginning,
DLB and it should just wait for input, then update the global state so
DLB the update step can do whatever.
As stated above, that's how I'm trying it right now. Still, if doing
it turn-base, I would have to create a new thread every time.
I have some other questions though - please see below.
DLB Also, recommend you use threading, not thread as the module.
Surely will, why?
DLB SERVER
DLB An input thread would look something like:
DLB while True:
DLB data = socket.read() #assumes both clients write to same socket
DLB #otherwise use a select(client_socket_list)
DLB #followed by socket.read for the flagged socket(s)
DLB parse data
DLB lock global
DLB save in global state variables
DLB unlock global
Now, few questions. Do I need to time.sleep(0.xxx) in any of these
while True: loops, not to overwhelm CPU? I can measure the time at
beginning and end of each iteration to make things happen fixed number
of times per second, but should I? And another: do I get it right that
instead of lock global you mean:
while global.locked:
time.sleep(0.001)
lock global
And I also wonder how do I make sure that 2 threads don't pass this
while loop simultaneously and both try locking global. There is a
probability, not?
Now, for update thread:
DLB That is all
DLB Update thread
DLB while True:
DLB lock global
DLB copy state variables to local
DLB unlock global
DLB compute new world state (check for collisions -- bullet hits)
DLB for c in client_list
DLB send world state to c
In my yesterday experiment, I have a separate thread for each of 2
clients, and what I do there is:
def thr_send_status(player_sock):
while 1:
t, sub_addr = player_sock.recvfrom(128) #player ready to accept
player_sock.sendto(encode_status(g.get_status()), sub_addr)
I'm reading 1 byte from client every time before sending new update to
him. OK, Ok, I know that's not good, ok. Now, I like your idea much
more, where you say we first measure the processing speed of each
client, and send data to every client as often as he can process it:
DLB Slow client receives the first at T0, but the last (packet 100) comes in
DLB at T0+60. Fast client receives all packets in T0+10...
DLB It took 60 seconds to receive 10 seconds of data. Client sends
DLB back to server a rate of 6. Other client sends back rate of 1.
DLB Server now uses a modulo function on packet sends...
DLB for c in client
DLB if t mod c.rate = 0
DLB send current world packet to client
Yes, this I great, but what if speed changes? Should I retest this
around every 10 seconds? I mean, server sending too much data to a
client is ok for server, but very bad for a client, since it starts
hanging and loses synchronization, unless I use a timestamp to throw
away late states (I think I need to re-read all your previous posts,
you've explained about synchronizing already).
While thinking about this, I've decided to go the wrong way, and to
wait for confirmation from client before sending next pack.
Still, it shouldn't slow anything a lot, because client does this:
def thr_get_status(self, g, player_sock, player_id):
while 1:
player_sock.sendto(!, addr) #ready
self.local_status = decode_status(player_sock.recvfrom(128)[0])
g.set_status(self.local_status)
So they simply exchange data all the time in separate threads, even