Inspired by J.S. Joust, I recently decided to pick up some Playstation Move controllers and attempt a video-less video game. This meant taking advantage of audio cues generated by the computer, and relying solely on controller input/output for the gameplay itself.
The main motivation behind the project was speed and design 'purity': designing a game like this forces you to make sacrifices and keep things simple. Using the controllers also allows you to design an inherently multiplayer game, removing any need for AI. Most of all though, frankly, I haven't made (read: finished) anything game-related in too long. This was a way to get me inspired. And I think it worked.
The art quality displayed here hopefully explains why I went for video games without visuals
Most of the games I would love to make are complicated. Especially when it comes to multiplayer: I like a layer of depth and complexity that lends itself to replay and also post-game discussion. Sometimes talking about how events unfolded is actually more interesting than the game itself - and for that to happen there has to be something a bit 'deeper' to the strategy of the game. Unfortunately, aiming for this type of game immediately seemed like a bad idea - after all, I was chasing quick-fire execution to get me inspired: I didn't want to get bogged down in designing and tuning complex strategy.
So, I pursued a far more simplistic idea: shooting people. Everybody understands that. It's quite brain-dead and incredibly unoriginal, but it was a good starting point for testing the capabilities of the controllers.
The game I devised as a prototype is that of a 1 vs. 1 western-style shoot-out:
There are a few things to note about this idea that may not be wholly obvious from the above:
Without the use of a camera, it doesn't seen possible to establish an accurate 'absolute' orientation for the controller. The PSMoveAPI can give a very good approximate orientation as a quaternion (through fusion of accelerometer and gryo data) but this is subject to a great deal of drift. If the player twists the controller, the planes of the reported values also remain relative to the controller's orientation, rather than to the player or the ground. This makes a great deal of sense, but it makes it difficult to establish whether the controller is indeed flat (horizontal) or not. Note: Obviously you can use the accelerometer to determine if the controller is flat - but the accelerometer does not 'recover' quickly enough to be of any use in this kind of game (given that the player will probably move the controller very quickly when the signal is heard).
The joys of calibration
For the sake of simplicity, the quaternion produced by the PSMoveAPI is used as-is, in tandem with frequent orientation resets. The quaternion is converted into an axis-angle vector and finally multiplied through into a standard X/Y/Z rotation vector, allowing more intuitive conditions/checks against the controller's angle in degrees.
Issues with controller twisting and rotation axis are simply ignored: the X axis is always treated as the angle to check for 'horizontal-ness'. If the player twists the controller, obviously this ceases to make sense: but it also makes it harder for the player to get the game to believe the controller is flat. Therefore, twisting the controller is discouraged (both through practical limitation and gameplay disadvantage). Mechanically this does make sense for the game, since twisting guns is generally not a good idea and greatly decreases accuracy.
Before the game starts, the user is expected to calibrate the down angle by pressing the move button of the controller whilst it is pointed down. This resets the orientation, therefore making the horiztonal angle the reset orientation + 90 degrees. [Note that this is very difficult to cheat or work around, since if you fail to point the controller downward, the 'horizontal' angle becomes whatever the cheat angle is + 90 degrees which is unlikely to be any more convenient than laying the controller flat]
In short: The orientation of the controller is detected very naively and is effectively a hack through frequent orientation resets. For future projects a more robust mechanism would be required. It is interesting to consider whether there would be some other way besides simply using the camera or some other fame of reference.
An additional gameplay rule, not mentioned previously, is that of a 'fault': If a player moves the controller much beyond the 'down' angle during the game's countdown (i.e. before the draw is signalled by the train whistle), the player is in fault, and the countdown is cancelled. This is intended to be considered cheating, since otherwise the player could get their controller horizontal and ready before the draw is even signalled. The blue light video in the above video shows this 'fault' rule in action.
A key component of the game is audio, since it is the primary communication form the game has with its players. Although overkill for a such a simple project, Pure Data via libpd was used as a backend for producing sound, and it did not disappoint.
In short: Pure Data is a tool for creating audio by connecting virtual 'wires' together. It has tons of documentation and a cross-platform editor UI. libpd allows files (a.k.a patches) produced by Pure Data to be processed by any arbitrary application. libpd simply produces a buffer of audio data, and from there it's up to the application (i.e. libpd is not capable of actually outputting audio - it only generates the buffer).
In the case of this game, the data was plugged into portaudio for realtime playback. What is brilliant about libpd / Pure Data, is that it is naturally a good fit for event-based systems: the code can send special signals (known as 'bangs') which have string names. The string names can be associated with anything (even >1 thing) inside the patch. This means that if the design of a sound completely changes inside of the patch, the code does not require modifying, provided the bang is still of the same name. This would no doubt be heaven to audio designers working on larger projects, since they can modify their work without requiring programmer intervention.
An additional timesaver is the fact that Pure Data literally handles all audio processing. The result is a single, flattened, stream of audio, meaning there is no need to manage multiple streams inside of the chosen output API.
In summary, despite being slightly clumsy when dealing with WAV samples (which are certainly not its forte), Pure Data was a resounding success, even in this relatively simple game, and will no doubt be reused for future projects.
The prototype's C/C++ code can be found on Github here
The code is an absolute mess. It was written very, very rapidly, and the guts of the game logic are sprawled randomly across different subsystems. You have been warned.
The code currently depends upon the following libraries. The plan is to slim these dependencies down significantly at some point, with a view to having these kinds of games running on the Raspberry Pi alongside the BlueZ bluetooth stack. (Given the quantity of dependencies, the code is really only released as a reference/curiosity at this point).
The control interface of the final product. Some parts are totally unused (e.g. game state) and really the entire interface is vestigial (removing it would remove the need for depending on Qt). But it does provide a useful diagnostic for the state of each controller
First and foremost: It works. It is in fact playable.
The downside: The only live human being I've played against so far is some guy with a beard, so I cannot really draw any solid conclusions from a design point of view. I would love to video some people besides myself playing it, as I imagine it would be very informative.
Despite this though, I have noticed some issues:
Here are some more abstract issues I've noticed:
To conclude: Despite the uninspired concept and poor orientation tracking for controllers, on a basic level, the project has been a success. I enjoyed working within the confines of 'no screen', and I felt it forced me to actually focus on issues of gameplay rather than getting caught up with other concerns.
Specifically, I'm definitely interesting in trying another move-based game, and I particularly want to aim for:
Additionally, Pure data (libpd) is brilliant and I probably need to find better ways of taking advantage of it. One of its strengths is generative/procedural synthesis, so maybe music-making could become part of the game...?
The lack of content here is degree-related: dissertation in full swing and numerous deadlines and exams popping up.
In fact it's pretty likely nothing will appear here until after exams or even after graduation (27th of June)
This post is just a random list of what's happened / happening recently:
I've started work on command-line based personal finance tracker dubbed 'treasury'. It's written in C++ (leveraging Boost) and uses an ultra-simple FS-based database. This is currently on the back-burner now that term has started at Durham, but will be resumed on and off in the meantime
As with the finance application, the puzzle game (which was recently reborn into HTML5) is also on the back-burner.
That's it really - just a run down of what I'm making at the moment. Hopefully next time blog gets updated it will be for linking and demos...
So, my internship at Data Interchange has just come to an end, and quite successfully I think too. Managed to get my project (integrating PDF output into their existing print routines) pretty much complete too, although it felt as though my implementation could have done with a tad more polish and testing - I don't really like leaving 99% complete projects with a bunch of caveats and limitations (which is irritatingly what I had to do).
Now it's the run up to the start of 3rd year, and the following are on the agenda:
Well, my internship at Data Interchange starts on Monday and I'm kind of stressed trying to sort out:
One good thing this week has been getting a 1st in my 2nd year though. Oh, and having crazy random late night pizzas (although it feels as though I've eaten enough junk food now to possibly kill myself several times over)
This week seems to have been Microsoft's not-invented-here week: First they announce an intentional fragmentation of GPGPU programming by creating an OpenCL competitor and now they're dishing out dirt at WebGL.
All I can say is that I'm back to disliking MS a lot. Things were looking up with the Windows 8 preview: They looked as though they would stop the childish reinventing of everything and actually compete based on quality with the same technologies as everyone else. Rather than trying to fragment platforms. But no. They've returned to their normal, idiotic selves. Every time things look up, they quickly swerve back into their age-old behaviour. This may not have hurt them yet, but it will. Each time they do this they alienate more and more developers, and it will come back to bite them. A platform without developers is a platform without software: a platform without software is dead.
So... wordpress is gone. And in its place an extremely simplistic blogging platform. Why did I give Wordpress the boot?
What have I actually replaced it with then?
Cool, huh? I think so, mainly because it was quite simple to cobble together, and hopefully means I'll actually update my blog more frequently. I've kept the database of the old wordpress install just in case I can salvage content from it, but for the time being this a fresh start.
Here's the roadmap for the blog:
That's all for now, but at least the site now has more than just a "Oh crud we've been attacked" message