Back in 1983 Sirius Software released Wavy Navy by Rodney McAuley for the Apple II, C64, and Atari 800. It was an obvious Space Invaders/Galaga takeoff, but the simple mechanism of having your ship carried around by large waves completely changed the dynamics. It was great - this was one of the Apple II games I played to death (along with Dino Eggs, Boulderdash, Bolo, Choplifter, and a bunch of RPGs).
So here we are 20 years later and I'm finally motivated to write a game in Python (my favorite language for getting stuff done fast and maintainably) and Pygame. What's my first game going to be, my proof of concept? Well obviously Wavy Navy.
This was completely done in three weeks, in my spare time (I've got a day job). About a week of that was creating and futzing with art, sound, and music. Python is so easy to prototype and write games with I'm looking forward to doing more. It's really the resource side (making art and sounds) that kills me.
The zip file should contain everything you need. Just unpack it somewhere then run wavy.exe from the bin\ directory or wavy.bat in the main directory.
If you already have pygame and sdl, then just untar this, 'cd wavy', './wavy'.
You'll need at least Python 2.3, though it works fine with version 2.4 as well.
Then go to Pygame's Install Page. From the box on the right side of the screen you'll need SDL:
Then install pygame itself from the top of the page:
These might be more easily available as packages if you're running something like debian.
My art skills are awful. So are my sound editing skills (my only tool is the Windows Recorder accessory). I drew the sprites painstakingly by hand, and am not overly happy with them. All sounds were scavenged from the web. Please forgive this, I think the play is still fun. If you would like to make better sprites or sounds please see Customizing below - the game is almost entirely skinnable.
Yes, my jet fighter diving sound is actually a Cessna (prop) plane.
Pygame doesn't easily support midi. I'm not going to make you install Timidity and 14 MB of patches, so all the music files are 100k wav files instead of being 2k .mid files. D'oh!
I was worried about performance, but it seems to run okay on a 3Ghz P4 Windows XP box and on an ancient dual 450Mhz P2 Slackware linux box. Let me know your system specs if it bogs down, though it's probably going to be a video card driver issue.
Your ship is at the bottom of the screen, riding the large waves. The waves will lift you helpessly up and down, which means there's a vertical factor to worry about. But they can also shield you from bullets. Move left and right, fire your SAM (Surface to Air Missile), dodge things.
Idling waves of Copters and Fighters at the top of the screen will decide to make attack runs. Fighters will loop around and occasionally drop a bomb - they will crash into the waves as well. This does not get rid of them, a new one will replace it from the top! You must shoot them to keep them dead. Copters are much nastier. They'll come down, look around, and fire a stream of bullets at you. Then maybe do it again.
On certain levels there are other enemies: Cruise Missiles, Bombers, and Mines. Mines just slowly float at the bottom of the waves. Cruise Missiles shoot across the top of the screen, then the tops of the waves. All you have to do with these is not hit them. Bombers will fly across the screen and drop a huge number of bombs - but in theory there's enough room between them for you to live!
The game never really ends, but when your rank ceases to go up you've effectively beaten that difficulty level. The game will let you know when this happens, though you can keep playing and the toughness of the enemies will keep increasing. Try a higher difficulty level! You'll get more points, and I think you'll find level 3 extremely challenging. If you beat that, I guess I'll have to add difficulty level 4.
You can configure the defaults for various menu items (Clouds, Display,
Difficulty, Music) in user_config.txt
.
You can change the ship control keys - see the [keys]
section
in user_config.txt
.
Wavy Navy is almost completely skinnable, since the
sprites and sounds are mostly data driven. The
[directories]
section in skin_config.txt
lets you specify the directory names for the sprites, sounds,
music, and level configurations.
I know my art is awful - please email me your better sprites/sounds, or even your entire upgraded themes if you're so motivated, and I'll put them up - with full credit given, of course.
All the sprite image files in sprites/
and wavs in
sounds/
and music/
are replacable by
your own files (or just edited versions). See
CONFIG.txt
in the sprites/
and
sounds/
for more info.
Things you can't change: I haven't given you any way to change the WAVY NAVY title in the upper right corner, the score beneath it, or the count of extra ships. If anyone really wants to put that much work into it I am very amenable to adding extra config support. Otherwise it's not really worth my effort for such a small project.
I'm considering adding C64 and Apple II skins for nostalgia factor.
Midi Fragments arranged by: Drunken Sailor - Barry Taylor Blow the Man Down - Barry Taylor The Handsome Cabin Boy - Ron Clarke Sailor's Hornpipe - Bynum Braden Popeye the Sailor Man - Anonymous
Yo Ho Ho - http://ingeb.org/songs/fifteenm.html
Anchors Aweigh - http://www.contemplator.com/america/aweigh.html
Marine's Hymn - http://www.instantknowledgenews.com/marine.htm
The midi files for 'Row Row Row Your Boat' and 'Sailing, Sailing' were scattered anonymously all over the web (the same one or two .mids on every site) with no credit given - if I knew who to credit I would!
As I was programming this, I often compared it to what the process would be like on an Apple ][ or C64. In 6502 assembly language with about 40K of memory to play with - I've been there!
In favor of the old way, there's something to be said for the purity and economy of the assembly language. If you need to hold x/y positions for 30 planes, you just reserve that much space in the header and bang on them directly using the X register as an array index with the plane ID. Compare this to the way I do it here - A Plane class (which is a Sprite subclass ) has further Subclasses: Fighter and Copter. These objects are created as needed, positions and speeds are tuples and bounding rectangle positions, and of course all all movement is done somewhat indirectly.
Graphics were not so much an issue - when they're so crude almost anything is good enough for a small sprit; though doing larger graphics for backgrounds or title screens was still beyond me. Having more resolution and colors (and full multichannel wave sound cards) to work with for the new game is rather a bad situation for someone who's bad at making the art like I am. This definitely ate up a lot more of my time than I'd budgeted.
You didn't have to worry about writing an installer, cross-platform compatability, or much in the way of system configuration. And most humbling of all, the entire original Wavy Navy executable is smaller than one of my sound effects files!
The New WayOoooon the other hand, I wrote this game entirely from scratch (except for the Pygame/SDL libraries ) in three weeks of spare time work, including creating all the art and finding and converting sounds, writing the docs, etc. Python's a dream language for doing quick revisions, adding functionality by slowly fleshing out the framework towards your overarching design, so you always have working code of some sort. What they're calling Agile Programming now. And not having a noticable compile step is wonderful - just edit and go. I can't imagine getting this done anywhere near that fast in the old days - even Nasir didn't turn out games quite that quickly.
Furthermore, the flexibility and ease of refactoring are incredible. In the old way, if you wanted to change how the plane x/y positions were handled (as described above), you'd be in biiiig trouble. Say you decided you needed another byte per coordinate to handle subpixel positions. You now have to rewrite every section of code that looks at the x/y positions. In Python, though this isn't Python specific of course, all that was just internal to the Plane class anyhow, and is handled by switching the positions from an int to a float. And that's all done implicitly since variable types are dynamic.
PerformancePerformance was a worry - Python is interpreted bytecode and I really don't worry too much about speed when coding in Python other than not doing dumb algorithmic things (like making a string by adding one char at a time - that's 8000 allocate and copies). That wave sprite is huge (and there's three of them), and there are quite a few planes and bombs on screen at once.
I shouldn't have worried - it runs smooth on my 3Ghz P4 XP machine, as expected. But it also runs smooth on my cruddy ancient 250 MHz Pentium 2 Slackware box. In fact at 4-6x the resolution and 16 times as many bits per pixel (32 vs 2) to move around, the frame rate is better than it is on the original game - if you play it you'll notice he used some tricks like only updating a plane every so often if it was idling. And I'm not really doing anything to optimize it, though Pygame and SDL have a few built in boosts like using update bounding rectangles. I'm not disparaging the original game doing what it had to do to make things work at 1Mhz, just noting that if it the Pygame version runs that well on a 250 MHz P2 and old graphics card that performance is not really an issue.
PortabilityThis was the real corker. I developed the game entirely on Windows since it's what I have for a game/dev machine at home. I gave no consideration at all to porting other than using os.path functions to split/join path names instead of hardcoding 'foo\bar'. When v0.90 was done I copied it over to my slackware machine, installed SDL and Pygame on it, and ran the game.
It ran perfectly. And it looked and behaved exactly as it did on Windows with no changes. I didn't have to go back and add 'if unix: blah elif windows: blah' anywhere in the code. I just had to add a small package maker script. Real write once, run anywhere. Now that chokes me up. Of course I haven't heard of anyone getting this to work on OSX yet.
HmmmmFor me, writing games in Python/Pygame is the way to go. There are only three concerns I have, though none of them are big enough to put me off it.
First, the lack of midi support is a bit disappointing. It'll work under *nix if you install timidity and have a Gravis Ultrasound, but that's not really acceptable. So I can't use .mids for music, which would hide my lack of skill at this and also make the music files 1/100th of the size. Perhaps I need to use the sndarray stuff to fake my own FM synth.
Second, Pygame seems to be languishing a bit. It works great as it is, but nobody's heard from Pete in a while. That's a bit troubling, even though there're noises among the user community about taking over the 1.7 release.
Finally, it really isn't quite as write once run anywhere as doing it in Flash is - and Flash (usually) doesn't require your user to install anything special like Pygame and the SDL libs. They've already got the plugin, so Flash gives you a larger audience. On the other hand, programming in Flash is so hellish in comparison that I pretty much consider that an 'Oh WELL.'