2-player game, client and server at localhost
hi, everyone. I'm writing a 2-players game that should support network mode. I'm now testing it on 1 PC since I don't have 2. I directly use sockets, and both client and server do computations, the only data transfered is user mouse/kbd input. It works synchronously, but somehow, when I play in client window, both client and server have 17 fps, while when playing in server window, server has 44 fps while client has 5, and due to forced synchronization, they both run very slowly (I wonder how come server says it has 44fps?). Does anybody have an idea how can this be? Not that users will test 2 game intances communicating via localhost, but I need to make it work properly. -- Best Regards, Michael Rybak mailto:[EMAIL PROTECTED] -- http://mail.python.org/mailman/listinfo/python-list
Re[2]: 2-player game, client and server at localhost
DLB> This logic will suck up as much CPU time as the OS will give the DLB> program... While if the client looks like DLB> loop DLB> send data to server DLB> read reply (blocking) DLB> do nasty computation DLB> end loop DLB> then it not only has to compete for CPU time, it does nothing while DLB> waiting for the server to handle the section inside the IF block. DLB> But what would happen if you put something like os.sleep(0.025) DLB> inside the loops? Assuming the loop takes 0.025sec to process, the total DLB> comes to 0.05 seconds (20fps) AND releases the CPU for the other process DLB> to compute. 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
using Pyro for network games
Hi, everyone. In topic "2-player game, client and server at localhost", I've asked about subj, and Peter Hansen suggested to switch to Twisted, Pyro or the like. I've tried using Pyro. I've written a very very simple test-game, in which you have 2 balls controlled by 2 players. Each player moves his mouse somewhere at his window, and his ball starts moving towards the pointer. No objectives, just to test how it works. The code is very small, so I can put it all here, skipping obvious stuff. I've tried playing this test-game via local-host - all is ok. Then I've tested via Internet connection with my friend. I have a 33.6 Kbps modem, he has a 2 MBps dedicated line (if this is the term), and we ran a server at his pc and both connected to it. His ball ran as a child, smoothly and quickly, while I had about 5 fps :(, and for him it looked like my ball is simply very slow. I realise that client at my pc *has* to work slower than the client at server's pc, but hey, I've played Quake2 and WarCraft 2 via 33.6 modem, and those should have much more stuff to transfer per second :( Please help me in any way you can think of. I'd welcome links to Python games written with Pyro, tips on what I am doing wrong, on not Pythonically enough - anything. server.py# # [..imports..] class game__(game_, Pyro.core.ObjBase): def __init__(self): #storage for balls' coordinates game_.__init__(self) Pyro.core.ObjBase.__init__(self) [..server initialization..] daemon.requestLoop() END#server.py# client.py# [..imports..] [..preparations to create proxy..] proxy=Pyro.core.getAttrProxyForURI(URI) [..imports..] def process_user_input(game, id):#id is client's id - 0 or 1 nx, ny = pygame.mouse.get_pos() x, y = game.ball[id].get_pos() dx, dy = nx - x, ny - y leng = sqrt(dx*dx + dy*dy) k = 20 / leng dx *= k dy *= k game.move(id, dx, dy) #remote call: move ball id = proxy.get_n_clients() #which ball to control if id < 2: proxy.new_client() pygame.init() scr = pygame.display.set_mode((640, 480)) g = game(proxy.get_status(), scr) #get_status provides 2 pairs of balls's current coordinates #g, "game" instance, is a local storage, able to render itself while 1: g.set_status(proxy.get_status()) g.render() process_user_input(proxy, id) time.sleep(0.03) [..quit = (ESCAPE is pressed)..] if quit: break END#####client.py# -- Best Regards, Michael Rybak mailto:[EMAIL PROTECTED] -- http://mail.python.org/mailman/listinfo/python-list
Re[4]: 2-player game, client and server at localhost
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 . 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
Re[2]: need for speed
SDA> On Mon, 01 Aug 2005 02:28:36 -0700, [EMAIL PROTECTED] wrote: >> hi everyone >> can someone suggest me where find a lot programming tricks for >> achieving the top speed in python? SDA> There is only one programming trick you need to know about making code run SDA> fast. SDA> Never even waste one second on optimising code before it is working, SDA> or before you have tested it and profiled it and know (1) that it IS slow; SDA> and (2) WHERE it is slow. SDA> Why would you waste your valuable time making bugs run faster? Why waste SDA> time and effort to speed up something that is already fast enough? SDA> In other words: Make your code work. Make it work right. Then, and only SDA> then, make it run fast -- and only if it isn't already fast. SDA> Now that you have written your code, and you have made it work right, SDA> please tell us what the code is, and the results of profiling the code, SDA> and we will help you speed it up. Is there a way of profiling other than manual (debug output with measurements and all)? Some tools? And is there some kind of plugin for native Python's IDLE to trace scripts? I'm a bit tired of getting all info from debug output and exceptions SDA> -- SDA> Steven -- Best Regards, Michael Rybak mailto:[EMAIL PROTECTED] -- http://mail.python.org/mailman/listinfo/python-list
Re[4]: need for speed
sorry for emailing privately, pressed the wrong "reply" button DLB> On Mon, 1 Aug 2005 20:14:51 +0300, Michael Rybak <[EMAIL PROTECTED]> DLB> declaimed the following in comp.lang.python: >> >> Is there a way of profiling other than manual (debug output with DLB> Chapter 10 of the Python Library Reference... You have looked at DLB> that document, haven't you? Already am, yes! >> measurements and all)? Some tools? And is there some kind of plugin >> for native Python's IDLE to trace scripts? I'm a bit tired of getting DLB> Have you read Chapter 9? ok, I'm looking through. A bit tough for me I think, I can live with debug outputs :) Well I'm too much used to M$ V$ / Borland Delphi interfaces to switch to almost-asm-like debugging. DLB> BTW: if you are working on M$ Windows, only on that DLB> you might want to consider installing the ActiveState release I tried, and the installer gives me that stupid Internal Error 2229: Control, SELECT 'Control', 'Type', 'X', 'Y', [..snip..], 'Dialog' = ? And I forgot the OK button. DLB> -- PythonWin might be nicer than IDLE (and has the referenced DLB> manuals formatted as Windows help files). I am using a *.chm file containing all online documentation available from python.org 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
Re[6]: 2-player game, client and server at localhost
those 30 frames, because input from other player comes instantly, about 10 times per second, and server tries sending this to all clients. So my slow client simply can't know current true status, thus has nothing to draw, because it can't handle 10 transfers per second. And if server doesn't send user motions equal number of times to all clients, while they compute the world's status, they will happen to have different pictures :( -- Best Regards, Michael Rybak mailto:[EMAIL PROTECTED] -- http://mail.python.org/mailman/listinfo/python-list
Re[2]: need for speed
sorry for emailing privately, pressed the wrong "reply" button BD> Michael Rybak a écrit : BD> (snip) >> >> Is there a way of profiling other than manual (debug output with >> measurements and all)? Some tools? BD> http://docs.python.org/lib/profile.html BD> HTH Oh, wow! Manuals rule, I should have at least skimmed through. Thanks a lot, already profiling :) -- Best Regards, Michael Rybak mailto:[EMAIL PROTECTED] -- http://mail.python.org/mailman/listinfo/python-list
Re[2]: using Pyro for network games
gn20kjss> Do not use pyro, use simple UDP protocol. gn20kjss> I've written networked tetris in python, communicating via gn20kjss> UDP protocol, and used it successfully on very congested lines. Would you please be so kind to share that with me? That would be greatly helpful, because 1) I'd run it together with my friend to see what speed I can get from UDP 2) I'd grasp the networking part of your code and reuse it. gn20kjss> If all you need is to transfer pointer coordinates, UDP is perfect since gn20kjss> you do not need feedback. gn20kjss> use something like this for server: gn20kjss> import socket gn20kjss> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) gn20kjss> s.bind(('', port)) gn20kjss> while 1: gn20kjss> data, addr = s.recvfrom(1024) gn20kjss> print `data` gn20kjss> and for client: gn20kjss> import socket gn20kjss> outsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) gn20kjss> outsock.bind(('', 0)) gn20kjss> outsock.sendto('message', ('server-hostname', server_port)) Would you recommend some reading on this? I have some immediate questions to your code, but don't want to flood here. OK, I will flood here a bit: what's the print `` syntax? P.S. I loved your virus alert ;) gn20kjss> -- gn20kjss> --- gn20kjss> | Radovan Garabik http://kassiopeia.juls.savba.sk/~garabik/ | gn20kjss> | __..--^^^--..__garabik @ kassiopeia.juls.savba.sk | gn20kjss> --- gn20kjss> Antivirus alert: file .signature infected by signature virus. gn20kjss> Hi! I'm a signature virus! Copy me into your signature file to help me spread! -- Best Regards, Michael Rybak mailto:[EMAIL PROTECTED] Antivirus alert: file .signature infected by signature virus. Hi! I'm a signature virus! Copy me into your signature file to help me spread! -- http://mail.python.org/mailman/listinfo/python-list
Re[2]: 2-player game, client and server at localhost
CS> Michael Rybak wrote: >> That's the problem - "or a player input comes in". As I've explained, >> this happens a dozen of times per second :(. I've even tried not >> checking for player's input after every frame, but do it 3 times more >> rare (if framecount % 3 == 0 : process_players_input()). Well, I've >> already got it that I shouldn't tie this around framerate, but >> nevertheless... CS> There's the key. How are you processing network input, specifically CS> retrieving it from the socket? A "sock" class has a socket with 0.1 timeout, and every time I want anything, I call it's read_command() method until it returns anything. read_command() and send_command() transfer user's actions in special format so that it takes 10 bytes per transfer. I believe this should be rewritten to be done in a separate thread, and that *current* user input should be processed as *next* one: while 1: render() inp = get_player_input() thread.start_new(send_inp, (inp,)) thread.start_new(accept_opponents_inp, ()) while still_no_opponents_input_from_previous_iteration() time.sleep(0.05) process_previous_player_input() physics.make_step I will try writing it that way, but I doubt it shall make things much better... You see, I've tried the normal 1-server-2-clients approach with Pyro (and today with simulating RMI proxy via UDP), and resulted with nothing comforting. Please read the "using Pyro for network games" topic here for details. -- Best Regards, Michael Rybak mailto:[EMAIL PROTECTED] Antivirus alert: file .signature infected by signature virus. Hi! I'm a signature virus! Copy me into your signature file to help me spread! P.S. here's the sock class. My server_sock and client_sock are derived from it, with additional accept_connection and establish_connection methods respectively. #sock.py import socket import com_network import constants as c_ class sock: def __init__(self, host): self.host = host self.port = c_._PORT self.sockobj = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sockobj.settimeout(0.1) self.curcon = None #connection will be created and saved here self.connected = False def read_command(self): """format: command_id - 1 byte command_size - CMD_LEN_BIT_SIZE bytes command_text - command_size bytes returns a triple (int id, int size, str text)""" if not self.connected: return (None, None) cmd = com_network.read_fixed(self.curcon, 1) if len(cmd) < 1: #no cmd return (None, None) sz = com_network.read_fixed(self.curcon, CMD_LEN_BIT_SIZE) cmd, sz = str_to_cmd(cmd + sz) text = com_network.read_fixed(self.curcon, sz) return (cmd, text) def send_command(self, cmd, obj): send_text(self.curcon, com_network.cmd_to_str(cmd, str(obj))) def close(self): if self.connected: self.connected = False self.curcon.close self.curcon = None self.sockobj.close() -- http://mail.python.org/mailman/listinfo/python-list
Re[4]: 2-player game, client and server at localhost
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 through separate sockets (not to dispatch the confirmations from different players into corresponding threads via global flags), which makes the "ready" thing ok from speed point of view, but I prefer your way, quoted above, so my question is still valid - do I remeasure speed? I'm also almost sure it's wrong to have separate sockets and threads for each player, you say I should select()/dispatch instead, but I'm afraid of that some *thing* being wrong with select() for Windows. Somehow, I'm doing a lot of thins the wrong way :( Before describing another problem I've encountered, I thought I'd remind you of what my test game is: each player controls it's ball by moving mouse pointer, towards which his ball starts moving; that's it. When I first tried this with threads, 1 client ran nearly perfect. But when running 2 clients via localhost, they eat cpu away, and bad things happen. Now, you see, sending user motions to server appears to be faster (or at least not slower) than getting new status, so, as a result, I have the following picture: I place my pointer somewhere, and the ball runs to it, and then runs a bit beyond it, because by the moment server knows the ball is already at my pointer, client still thinks it's not. Several seconds later, thins "a bit beyond" becomes "a lot beyond", and finally both balls run away from game field, being helpless; seems like I/O thread being much more productive than send_status one? I thought that the reason is my stupid "ready" check before every status update, and removed it. As a result, even single client via local host was very slow, but no artifacts. This all was when I had *no* time.sleeps in the while 1: loops. So I added time.sleep(0.005) to server's send_status loop and to client's send_user_action loop. Things became better, but still balls are spinning around the mouse pointer instead of running under it. Every time client tries moving towards the mouse, it's ball is already at another place at server, and it runs in wrong direction. Obviously, if I have these problems in such a primitive test at localhost, I shouldn't even try running it online with the Snakes :( Thanks again for being this helpful, Dennis, and thank you for your patience! -- Best Regards, Michael Rybak mailto:[EMAIL PROTECTED] Antivirus alert: file .signature infected by signature virus. Hi! I'm a signature virus! Copy me into your signature file to help me spread! -- http://mail.python.org/mailman/listinfo/python-list