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.
Rendering woes
Yeesh.
Since I’m running the client itself in a single process, anything that has to go from one to the other has to be serializable, since it’s being run through pipes… well, that means I can’t really use some of the pygame types in my basic game objects.
So I’ve started a rendering ‘engine’ that’s pretty much just a set of wrapper classes; each one takes a certain game object (maps and panels right now, I think they’re generic enough that it won’t grow much beyond that), updates its internals with sprites as necessary, and provides update/draw methods (they’re extending pygame.sprite.Group for this purpose).
The problem is that these rendering objects aren’t persistent… they’re regenerated every frame. This might cause performance issues, but the thing I’m more concerned with is animation… I might have to track the position of an actor within the actor model itself rather than within a rendering object, which I didn’t particularly want to do, but if that’s what I can depend on being persistent, I might just have to settle for that little breach of my arbitrary protocol.
I’m not too sure I like the way this whole client method is going anyway… I guess we’ll see. Damn you, Unladen Swallow, hurry up and kill the GIL so I can just use threads!
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.
Pondering multi-tile actors.
Well, I haven’t put any time into this lately, partially because I just quit my job and have been in limbo (have I posted about that? I guess I should read my own blog).
Anyway, one of the things I always wanted to support in the game was characters of different sizes — so instead of fixed-size playable characters and NPC’s, I could define a set of dimensions and a larger sprite that the engine would handle correctly.
I’m pretty sure I’m going to update the motion processing to handle it… I just don’t know how I’m going to handle it in the rendering engine. The real problem is how to handle things like doorways. If I allow two-tile-wide characters, I either have to make sure all movement happens in one-tile increments or (if movement increments are equal to the size of the character, which is what I intended to do), that all doorways are wide enough to accomodate all character sizes.
Now, that seems simple until you consider that I wanted to build map rendering in such a way that where you start determines where your map view is… it just feels more dynamic. The implication here is that a 2×2 character won’t always fit onto a 2×2 grid, but a 1×1 grid — so the door would have to account for that character’s offset if he could move by any increment other than 1 tile at a time.
I’m not sure if that clearly illustrates the problem, but I think after typing this I may just go with limiting the movement distance to a single basic tile. It’ll feel slower for large characters, but that kind of makes sense, and it’ll keep doorway width predictable.
Um… thanks for listening!
Inter-map movement!
Nice! It took longer to get around to working on this bad boy again, but I put in a few hours today and managed to get adjacent maps associated with each other and teach the engine how to handle movement around and between them.
One thing I’m wrestling with is how to make player object handling generic. At the least, a payer is just an instance of Actor that the client understands it needs to follow; however, as far as the client, I’m kind of stuck sending the player directly to the map on instantiation, otherwise it’ll get lost in the shuffle of inter-process communication.
This may not actually be a problem, since the server should not have to track a special player object, just generic actor objects, which I believe won’t be problem with the existing code; the necessary methods should work fine with actors that aren’t passed as players. I’ve moved most of the necessary instantiation code out of test blocks and put it closer to where it should be, which is encouraging and went pretty well.
A little bonus is that by dumping an actor into the map separately from a player while experimenting with the movement showed that my tracking model seems to be sane — the actors could exist on the same tile (this is intentional), were tracked correctly, and did not interfere with one another.
Freaking brilliant.
No, really, that’s not sarcastic. Freaking BRILLIANT!
Thanks to the Queue class in processing (which I’m now using instead of multiprocessing… for no particular reason, other than it’s in Portage, and I have an aversion to using anything that isn’t in my package manager), my client is now happily passing user input to a queue which will contain the map and an arbitrary number of menus.
It’s terribly embarassing now that I was attempting to simulate a queue with a list and labelling it as an ‘execution stack’ (an ugly misnomer which helped me delude myself) when I really should have been doing this from the beginning.
Anyway, the locking I was using with the ‘stack’ was a bit counterintuitive for that implementation, but works ideally for this one.
Good stuff!
Woohoo! Map movement!

Yeah, I know, it doesn’t look like much… ;)
This is just a unit test to ensure that movement between map tiles is being handled correctly. Tiles you can walk on are labeled as []; tiles you can’t are marked as //. The tile the actor (player object) is on is marked with the number. This is a really simple way to make sure the map is only allowing the player to walk on the right tiles (earlier on it successfully keeps the player from walking off the map, which is good, but will be handled slightly differently for multiple maps).
It (purposefully) ignores animation and view (the subset of this map that should be displayed on screen); separating these things is something I needed to accomplish anyway, since my previous ‘tech demos’ had them tied together, which is not acceptable for the actual client.
Multiprocess command input
Well, this multiprocessing crap ROCKS, but man does it make things… interesting.
After wrestling with a serialization issue, I realized I can’t keep a lock as an instance variable on an object I need to pass between processes; I should have figure that out sooner, but I had written it to work with threading, which doesn’t have this particular quirk.
Now I’m working on getting a sensible method of passing events out of the input thread and determining where best to process them; I knew it’d be a little hairy, but it looks like I either made some questionable decisions early on about where to implement things or just did so with the (now forgotten) intention of moving them later on, because I’m left wondering whether actor movement should really be handled by actors themselves or by the maps they are associated with, and how much graphical information the actor should keep about itself — it needs to track its own sprite sheet, but as far as rendering, I think I need to introduce a generic processor in the GUI thread to handle this.
So at this point I’m largely working on juggling code to put things in places that make sense, with the objective of successfully passing commands from the input thread to the GUI thread in a way that correctly and efficiently invokes the required functionality, and (when necessary) passes it back to the server as well.
Multiprocessing is a go!
After a whole lot of on-and-off frustration with this problem, I FINALLY figured this one out (after reading the same documentation about thirty times, but oh well).
So now I’ll be able to handle processes not only on the server, which is pretty much necessary for keeping many concurrent users happy, but also on the client, so that I can run graphics, networking, and input handling in separate processes.
I had written them in threads before; while that was fine and all, Python (the C implementation, anyway, which is the standard) has a global interpreter lock, meaning that even if you’re running multiple threads, only one can ever actually be executing at a time. Which really sucks if you want actual concurrency, since, you know, that doesn’t qualify at all.
Next step: Folding this into the current client code! It’ll require a little reworking architecturally, but even with that, soon I’ll be able to start putting my GUI and input code back in the mix together.
Exciting stuff!
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.
