For the next few days I will be working on a multiplayer snake game for the browser.
Snake seems the easier of the two to design, so I’ve started on that game first. I’m hosting the game on GitHub, here.
Snake is a game in which a user directs a string of blocks around the screen and attempts to “eat” a randomly placed food object, which will make the string grow longer, while avoiding crashing the snake’s head into its body or one of the four walls.
High Level Implementation:
- Blocks: Rectangular blocks form the basis for most of this game; they are given a color, size, and location coordinates, and then empowered to show or hide themselves to the viewer, depending on certain circumstances. The snake, board, and food items will all be made up of these blocks.
- Snake: the snake is composed of an array of blocks, with a few extra methods to make my life easier, including the ability to move itself around the board and grow when it needs to (ie when it “eats” something). Every time the game cycles, the snake’s tail disappears, and is replaced by a new block at the snake’s head. The old block is deleted from memory, and its visual counterpart is erased from the screen, and the new one is added to the snake’s “model”, and painted onto the screen. This makes moving the snake an absolute pleasure. The idea of figuring out where each new block would go each time the snake moved had scared the crap out of me previously, and this way all I have to figure out is where two blocks were (the head and the tail) and where one new one needs to be relative to one of those. It’s insanely simple, and it works nicely.
- Grid: the board on which the snake moves is composed of a grid, which is held in memory as an array of arrays of objects with location and occupancy status information embedded in them. This makes collision testing relatively straightforward: to check whether the snake hit something, all we have to check is whether its head is in the same x and y coordinates as our other occupied blocks; these are for the most part simply the outer edge of grid-squares, the snake’s body itself, and whatever food square we place on the map. This makes collision detection easier and more efficient than scanning the entire board and checking for overlapping spaces. In fairness, this only works because we’re using a grid; objects of arbitrary shape and size would have to be scanned for using a more sophisticated system.
- View: the board view is an object with extremely simple behavior. It’s sole purpose in life is refreshing the canvas for our viewers, to make sure it reflects the models we’ve established earlier. It’s really good at doing that. Like, really good at it. Nice job Board View.
- Controller: This is where things get hairy. The game’s controller should be relatively straightforward to reason about, and eventually it will be implemented correctly. As of now however the implementation is imperfect, and so I will first describe the Controller as it should be, and then as it currently is.
- Controller (proper): the controller’s job in life is to take user inputs and modify the game’s model, and then alert the view that it needs to update the model, which the view will then take care of doing. Imagine the controller as a middle manager at a newspaper, who’s job is to take the pictures and stories his journalists created and feed them to the people who will handle their layout and printing. The controller is also responsible for taking in information from the newspaper’s owners, so he can tell his journalists what stories to create. The controller’s job then is to control the intake and processing, and response flow of information from and back to users. That’s quite a mouthful, but a simple idea. The Controller takes things in, and tells different parts of the application what to do with them. Cool.
- Controller (as it is now): The controller as of now is blown all to hell. I’m racing to finish a first draft of the game, and so I’ve decided to keep the deep internals of the game working correctly while fudging the implementation of its high-level machinery to just get things working. As of now, that means basically that I’m the controller. Kind of makes sense, no? Until I have time to properly think through how the game should flow, I’m building those pieces piecemeal and as needed. This is not the end of the world, and from the user’s perspective, if my coding is good enough, there should be no difference. But it is problematic for several reasons (one being my coding may not be good enough – we’ll see), which will be discussed in depth in my MVC post – if it ever gets written. So for now, think of the game as being architected on the MVM pattern – Model-View-Moshe. Awesome, now you know how the program works! What fun!!!
The game is not yet published, since the first prototype isn’t yet complete. It will be by tomorrow though, and I will publish a working link to a basic version of the game, probably hosted through heroku.
Not enough for you? Fine, here’s a teaser: I also spent some of last week building a realtime chat server using Python, the code for which is also up on GitHub here. My plan is to finish implementing the Snake game, and before I get to Tetris to port Snake to a multiplayer version, coordinated in real time through the server. You’ll know when it’s ready. Especially if you’re sitting next to me. But also if you continue reading this blog. If you’ve read this far in this post, I’m guessing you’ll see that one when it comes out too.
Thanks for listening!