Qwerty War released

It’s actually been up for a while now at http://www.qwertywar.com/.

As is typical of software, final cleanup took me longer than expected, a week perhaps. One problem still irks me: it’s too slow. While it runs reasonably well on my desktop machines, not so much on my my high-resolution devices. And this after already spending a day or two profiling and optimizing.

Poor performance on the tablets and phones doesn’t bother me too much, since it’s a typing game, and who would play with a touchscreen anyway? My high-dpi Lenovo laptop, however, also does badly. I suspect the problem is partly thanks to poor Nvidia support on Linux.

Still, the performance problems surprised me because it just doesn’t seem like there really is all that much happening on the screen. The game draws a few shapes and renders a handful of different 32×32 sprites in maybe a few dozen different positions.

Sometimes, though, you just need to call something good enough and go play Qwerty War.

Qwerty War: day 5

On day five, I plan to get the leaderboard persistence built and deployed: the only part of the project that requires a database back end. I figure that I’ll build this with Django and deploy on Heroku.

So I switch from JavaScript to Python and naturally this requires that I instate my traditional key customization that maps shift+space to underscore. Previously, I’ve used xmodmap, but the going wisdom around the Internet is that xkb is the newer, better way to do things.

hours pass

I can finally type underscores without over-extending my pinky, so I turn back to the problem of Django. Django normally uses a great many subdirectories to organize things and make them portable, which is great for medium to large applications, but annoying for something as small as Qwerty War. The article Django as a micro-framework is a good start to really stripping Django down, but it’s significantly out of date. To bring it up to date with Django latest, the main thing to realize is the django-admin command line should now read thus:

django-admin runserver --settings settings --pythonpath .

From there, you’ll find there are a series of errors that are all pretty self-explanatory and easily fixed. I skip most middleware, but keep the csrf and clickjacking parts.

Soon enough, Django is serving up my static files: I haven’t built any database stuff yet, but I figure I should try deplying the static bits on Heroku. First hurdle: Heroku wants me to install its command-line tool by piping stuff from wget into a shell. The script would install Heroku’s apt repository and go from there.

Isn’t the whole deployment done with git anyway? Why do I need the heroku command line interface? Much less another dpkg repo. It turns out this is easy enough, if undocumented

  1. Add an ssh public key to your account via the Web gui
  2. Use the Web gui to create a project
  3. Push to the project using the funky-looking location git@heroku.com:[appname].git

Mercurial, of course, does not speak Git natively, so I decide to try to the hg-git extension. Its homepage says to install via the old easy_install. Not an auspicious start, but ok, I just try pip instead, and in Pythonic fashion, it just works.

So far, so good. The first push via hg-git succeeds, but naturally, the app fails to start on Heroku, as I haven’t yet created a Procfile or wsgi.py. I add them, push again, and… nothing. Mercurial reports there are no changes to push. Did my first push really work at all? I figure I’ll try cloning the repo from Heroku to check, using actual Git…. time passes (but much less than spent on xkb) …I figure the problem is that either hg-git or Heroku or both dislike that I pushed some rather large files. In particular, I included a full history of my edits to the binary blobs that are audio files, plus the originals in .wav and .flac format.

Fair enough, pushing all that stuff is pretty wasteful anyway. I abandon the hg-git extension and opt for a simple shell script that deploys via Git proper. It works, so on day five, I at least have a deployable application, if still very much in development mode and without a database.

Qwerty War: day 4

On day four, I add sound effects. There are only a two essential types of sounds:

  • Gunshot when the player fires
  • Explosion when an enemy blows up

I could add some other effects, such as bullets whizzing by; a sound when powerups appear would be nice and maybe an alarm when health gets low. The original has music, but I think that is over-achieving for this little project.

There are a plenty of free explosion and gunshot sounds online; I pick some from freesound.org, and tweak and cut them in Audacity.

I’m playing all sounds with the Web Audio api. To make them interesting, I add a few variations that may actually be more trouble then they are worth: decreasing volume and delay depending on distance from the player.

What does turn out to be important is not playing too many explosions at once; many simultaneous explosions cause clipping and many very close together just sound like noise, so I introduce a brief delay between explosions when the player hits a bomb. This turns out to be a nice effect. Even with this, though, many explosions simply add up to too loud and still clip, so I use Web Audio to insert a compressor and that mostly gets levels under control.

Next problem is that the gunshots contain some hissing noise as they fade out; it is barely noticeable for a single shot, but becomes irritating when many shots are happening close together. A low-pass filter on the tail of the sounds cleans it up.

Once all the explosion sounds are working, I realize I have a performance problem. At first, I think that Web Audio is causing it, but a few minutes with a profiler tell me that it actually is drawing all the explosion animations when a large bomb goes off. I hadn’t noticed it before only because I did not have so many enemies on the screen at once.

Well, optimization will be a problem for day five.

Qwerty War: days 2 and 3

For day 2 of the Qwerty War project, I wanted to get all the visuals roughed in, though without final sprites for the player and enemies. It turns out this actually took two days.

I considered doing the whole thing by moving divs about the screen, or even svg everywhere, but the obvious choice is canvas, so best not to overthink it.

User controls – word input, health meter and score – are still regular html elements overlaid on the canvas. At first, I thought I would do the same with the enemy words: reposition the table cells from day one’s text-only version to follow sprites around, but soon decided drawing the text with canvas api would be simpler.

More structural changes came from the rework necessary to allow for delay while bullets reached the targets. This may not have been strictly necessary: originally, I planned to keep reactions instantaneous. When the player shoots, for example, the enemy would explode immediately. I would then animate the bullet motion toward the enemy. Since the bullet would whiz over in less than a tenth of second, the delay would not be noticeable.

As I was starting, though, this felt wrong. The code made more sense if I associated the explosion with a bullet impact, rather than the shot. If I’m inclined in the future, this should allow features like slow motion.

Bullets are the only effect not built with sprites: they are just lines with gradients to fade out toward the shooter. The “collision detection”, if you can call it that, is easy. Since every moving element is arranged radially from the player, it’s a simple matter of checking whether the bullet traveled far enough to hit its target, which causes the target to explode.

Explosions, of course, are the fun part. The nifty http://explosiongenerator.com/ gives me the look I want. There are three levels of enemies in the game, from words length three up to five, so I just need an explosion per enemy type. Stopping the explosion a few frames from the end gives a nice debris and blood splatter to paint on the background. By randomizing the rotation of each explosion and its ending frame, just three explosions look pretty organic.

Explosion generator gives you a download full of .png images; I used ImageMagick to combine them into a single image suitable for animation:

montage images/explosion0{000..191..4}.png -geometry +0+0 -tile 12x4 -background none explosion1.png

That squirly brace stuff is a handy shell trick to pick every fourth image from a desired range. From there I just use JavaScript to animate these frames.

So far, the game on day 3 looks pretty good, but a few details bother me:

  • Enemies run over each other, sometimes obscuring the words you need to see. This also happens in the original Qwerty Warriors. It’s not too much of a problem – you could even say it makes you think a little more strategically about who to shoot – but it seems unpolished. Would be nice to put in collision detection so enemies don’t run each other over.
  • The end is abrupt. It might be a neat effect to finish animating all bullets in flight and explosions after the player dies.
  • Bullet animations are not entirely satisfying. They are functional, but not exciting.
  • As I was testing, I realized muzzle flashes are a nice feature to show you who is shooting at you. I put them in as just one extra sprite for each of the player and enemy types, flash on or off, but there probably should be a few frames to that animation.
  • The bullet trail extends through the shooter. I mentally justify that by saying it’s the stuff coming out of the rear of a rocket or something, but actually it just looks odd.

Nonetheless, it looks decent and is becoming fun to play. Day four will be for sound effects.

Qwerty War: day 1

“Qwerty War” is what I’m calling a small typing game inspired by Qwerty Warriors.

The concept is that you are a keyboard-slinging warrior surrounded by never-ending waves of enemies. There is no escape, but you’ll take as many of them down with you as you can. Qwerty Warriors is my favorite typing game; since it surrounds you with enemies, it has an intensity that other typing games lack. Its remake, Qwerty Warriors 2, by contrast, only sends enemies in from the top, typical for typing games, and boring.

The original is built in Flash and often syndicated on shady sites who make their money via ads for scareware and other garbage. So my own Qwerty War will be an open source JavaScript only game.

On day one of this project, my goal is to get a text-only version working with all components. In the text only version, a table of “word” and “range to enemy” replaces the visual of enemies encircling the player, but it contains all the actual gameplay components. There is no reason for a typing game not to be accessible to the blind, so the text only version will remain as a fallback to the final graphical version, build on html canvas.

The final version will include a server-side component for saving the leaderboard, but the game itself runs entirely in the front end. After day 1, it is playable, if a bland. Source is on Bitbucket.