Re[4]: 2-player game, client and server at localhost

2005-08-03 Thread Michael Rybak
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

Re[4]: 2-player game, client and server at localhost

2005-08-01 Thread Michael Rybak
Again, thank you very much for your help.

DLB The server should basically handle the multiple client
DLB connection logic, and determination of interactions between movable
DLB objects -- collision detection, for example (and I don't mean in the
DLB terms of graphics rendering but in terms of object one at current
DLB movement intersecting object two moving at some other vector).

My problem is: there are about 30 movable objects, so transferring
all their coordinates is much more traffic consuming (about 150 bytes
per transfer) rather than sending only user's motions (10 bytes per
transfer). But on the other hand, sending user's motions between two
non-server-neither-clients means that I needed stricted
synchronization, which means the turn-based approach, as you've said.


DLB I'm also NOT a game programmer, so I'm not sure how well most of
DLB them separate screen updates from I/O, but I'd turn the above loop into
DLB something like:


DLB create screen thread
DLB create I/O thread

DLB {screen thread}
DLB loop:
DLB compute/display screen using snapshot of local status

DLB {I/O thread}
DLB loop
DLB if keyboard has activity
DLB read data
DLB send data to server
DLB if server has activity
DLB read data
DLB update local status

DLB Note that the keyboard, in this simple example, never affects
DLB the local (client) display -- only the status sent back by the server is
DLB used. Okay, you may need to process things like quit locally G.

Well, this look really elegant, but will need me some time to rewrite
my networking that way. Thank's a lot, I'll let you know when it
works.

[..snip..]

]DLB The server looks like:

DLB loop
DLB if new client connect
DLB add client to list of clients
DLB send client current status
DLB if data from client
DLB update world state (collision detects, damage, etc.)
DLB for c in client list
DLB send current status
DLB if client disconnect
DLB remove client from list

consider this part:
DLB if data from client
DLB update world state (collision detects, damage, etc.)
DLB for c in client list
DLB send current status
the problem is - I should do this not if data from client, but every
50 milliseconds or so, because objects are still moving when not
affected by users. To give you a better idea of what my game is:

Each player controls a snake, which is 2 to 12 balls connected to each
other with ropes; by mouse motions you move the snake's head, and the
rest of the body moves adhering normal physics. The objective/gameplay
is unimportant here, but if you're curios - all the balls of your
snake are bullets, and right-clicking releases current tail. So, you
have to spin around, and release the tail in appropriate moment so it
reaches your opponent, causing as much damage as much impulse it had.
There are health-pots and other stuff on game field of course.

So, you see - server will have to send current status as much time per
second, as much fps I want, and that's quite a lot of data.

I'd also like to mention (if I haven't already) that I have a 33.6
modem, while the friend I'm testing with has a 2 Mbit dedicated line,
if this is the right term.


I also was advised (by Peter Hansen) to try using Twisted, Pyro os
something like that. I've looked at Pyro, and tried using it, without
a lot of success compared to what I have now. I'm starting a new topic
here, describing my experiment.


DLB Recall my warning -- I'm not a game programmer; this is just how
DLB /I'd/ consider implementing something like this.
You're being very helpful anyway :)


DLB -- 
DLB   == 
DLB [EMAIL PROTECTED]  | Wulfraed  Dennis Lee Bieber  KD6MOG 
DLB[EMAIL PROTECTED] |   Bestiaria Support Staff   
DLB   == 
DLB Home Page: http://www.dm.net/~wulfraed/
DLB  Overflow Page: http://wlfraed.home.netcom.com/



-- 
Best Regards,
 Michael Rybak   mailto:[EMAIL PROTECTED]

-- 
http://mail.python.org/mailman/listinfo/python-list