Submitting a bug is... KIND of like contributing... right?
Since I enjoy writing at myself so much, I figure I’ll go ahead and update this! :)
I finally started getting back into this little by little, and actually made some pretty good progress. I fixed the rendering quirks I was running into by digging into and correcting my usage of the multiprocessing library; I still have some locking to implement, but it’s quite trivial compared to the major revamp I just finished.
There’s just a small problem left with rendering on moving to a new map, but I know where the problem is, and it’s something that just hasn’t been fully thought out yet.
As for the title, as I was going through my multiprocessing implementation, I hit a VERY frustrating issue. Long story short, it turns out you can’t start this particular type of shared memory controller in a file that’s imported by the invoked script — whether it’s created in an import or not, is start() method MUST be called from the script you actually RUN. Yeah, screwy. I filed a bug, though, so rock on!
Things that are now working:
Client
- Input, graphics and networking are handled in separate threads
Server
- Processes are spawned for and take input from any number of clients
General
- Movement around a map and between maps works
- Collision detection with map boundaries and impassible tiles works
I’m noticing that the graphics and networking processes are eating an irresponsible amount of CPU time, so that’s going to be something to look into, but I don’t think it’s going to be a big problem; there shouldn’t be anything too non-standard about the way I’m handling those things.
Last night's progress
Well, I got the client and server on speaking terms, which is a plus. They’re pickling and compressing to communicate; I just need encryption now, which won’t be difficult and will have to wait until I have actual authentication systems in place (which is a little while out yet).
The client is already tracking the game world (well, a set of maps, anyway), so that’s fine; it needs to be using a child class that adds rendering information and methods to the maps, but that’s pretty trivial, and it means I can use most of what’s there on the server, which will track the basic map, since it doesn’t render anything.
I think I may be to the point of taking a break on the really technical stuff and getting some rendering going. Making the client do something useful, at first anyway, is going to revolve around activating objects and then adding a chat interface; doing that on the console would probably end up making more work for me than it’d be worth, so I think the next thing I do will be getting basic rendering up and running.
From there I can start work with rendering panels for menus, chat boxes, alerts, etc., which I’m hoping to use for anything that displays text to the user — if that works out, and I’m not sure why it wouldn’t, I’ll be able to use them to build the entire menu system very quickly, including the initial startup and login interfaces, which will be the starting point for authentication with the server.
Back at it! Pydoc, processing and client-server communication.
OK… I’m finally putting a little more time into this project. Man, it’s been way too long.
I’ve been pondering using pydoc to make sure I can keep a handle on what I’ve written, what needs to be done and how it’s working. I’m now doing so, with simple doc strings for my classes and methods, but the tool itself is a bit messy — not that I’m criticizing it, just that doing its job well necessitates putting a whole lot of information in one place, and that’s just difficult to format. It’s still useful, though; it’ll happily run as its own local web service, so all I have to do is nohup it as root and it happily runs while I’m working; plus, it recreates its pages whenever you hit them in the browser, so changes to the code are reflected immediately. Handy!
As for the actual game, I had intended to start doing a bit of graphical work next… after reviewing the client stuff that’s already working, though, I think it’ll be a lot more useful to get communication between the client and server working first.
I quickly ported over the old threading-based server I wrote initially to use processes instead, tested it and it seems to be happy. I do love the fact that processing mirrors the interfaces to threading so closely; despite IPC being a lot more involved than talking between threads, at least it makes the basic functionality almost trivial to swap.
Another related but largely irrelevant (mwahaha, ponder) tidbit: I use git for version tracking (god how I love it). For business stuff I have my repos set up on an Amazon EC2 instance (don’t worry, they’re on an EBS volume); however, for local stuff I usually just used my file server. Unfortunately, I haven’t bothered to hook it up yet, so that doesn’t do me much good. Instead, I managed to set up a bare repo on my EC2 instance and push all the previous refs out to that… and it took all of five minutes to get it set up and sync that fresh repo with my local one. Most of that was spent looking for the right command (git push --all). MAN do I love git!
OK! Back on topic, I’m hoping to get the client sending movement updates to the server tonight. I may not get that far, as the whole IPC with processing thing is a hassle (and despite the server happily accepting connections and spawning handler processes, it needs some infrastructure to manage incoming requests from multiple procs, apply them and respond).
I don’t think this will encompass sending game state updates down to the clients; I still have to figure out exactly how I want to handle that. diffing cpickled game state representations and sending a patch is kind of an interesting idea, but it probably wouldn’t be all that fast and it’d get needlessly complicated, I think; something involving queued records of actions accepted by the server and applied to the game world is probably how it’ll end up being represented, then wrapping up the actions that haven’t been sent to a particular client yet might be efficient. The other thing that’s been in mind is sending the parts of the current game state that differ from the client’s representation, but that involves a lot of duplication in memory to keep track of every client’s current opinion of the game world, and then going through the changed states and guessing how to transition… no, I think sending a series of actions is far better.
And now I’m off to write some code.
Threading to processing on the server... FAR too easy.
Something is wrong; someone has pulled a fast one on me, I swear, because switching my TCP server over from threading to processing (forking) was ridiculously simple.
All I did (aside from changing the class names themselves) was swapping ThreadingMixIn with ForkingMixIn for my TCPServer extension class… and holy crap, it runs perfectly. Watched top to see the processes get spawned, ran a few different clients and connected happily.
Holy crap. :)
Granted, this has nothing to handle concurrency at the moment (all the actual work beyond setting up the server to accept connections has been on the client side), but I’ve already largely wrapped my head around doing that with processing/multiprocessing, so that won’t be such a major undertaking.
This isn’t a huge accomplishment in terms of deliverables or anything, but it’s pretty cool to see something major like this just up and work.
Switching to Python and other intriguing developments
After getting a bit tired of my non-interactive HR/blockquote updates page, I installed a portal and reopened the forum as the main site.
Python/Pygame
I’ve switched from C++ to Python for all code and from straight SDL to Pygame for graphics. The increase in productivity per hour is awesome.
Client progress
Separately, I have implemented both sprite motion and movement control from inputs and animation from the same. However, I haven’t mixed them yet, and I’m still going back and forth on threading vs. multiprocess for the client, which is where I’m a little stalled right now (largely trying to find a Python process library that handles shared objects gracefully).
Server progress
The server accepts and responds to connections and messages. Right now the client and server both gzip their packets; I’ll probably encrypt them first as well, just because I am a security nut job. The server isn’t terribly complex yet and hasn’t been the focus of development.
Technical Tidbits
Animation, while a slight pain in the ass, turned out to be pretty reasonable (and relatively inexpensive in terms of resources as I’m using sprite sheets and only ever keeping that image in memory, which will make it relatively simple to get the paper doll effect going when I get to that point; yes, that will definitely be part of the game).
Milestone
0.1
Genotype
* User can interface with client through game pad.
* Client encodes and sends requests to server.
* Server receives, decodes and interprets requests.
Phenotype
+ Client can move around and between maps.
+ Client can activate objects on map.
+ Client can view and navigate menus.
The only genotype (back end) item that is not complete is game pad integration, which should be relatively simple with Pygame’s joystick classes; front-end behavior (phenotype) is much more complicated. While moving around a single screen has been implemented, it’s not yet worked into the main client code.
This ‘milestone’ turned out to be… probably a good 30% of the actual work involved in writing the game, so breaking it down further once I had a better idea of how it would be handled would have been a good idea. I’m using trac to build task lists for myself, though, which is accomplishing the same end in a more useful manner.
Stay tuned! I’m hoping to have the multiprocessing library solidly in hand in the next week, and once that happens I will be integrating player motion back into the client and building the map infrastructure.
