Abbey's Grand Adventure
Queen Baddie has chased the Grand Phoenix from the land. Without the Grand Phoenix's protection the creatures of the land are turned into baddies too! Some of the Phoenix's feathers fell out while it was being chased. If you find them they'll grant you special powers!
This game is written using pyglet (so requires OpenGL), cocos2d and lepton.
Downloads: source, windows exe, OS X app.
Source downloaders will need to install lepton separately.
Awards
Scores
Ratings (show detail)
Overall: 3.5
Fun: 3.5
Production: 4.1
Innovation: 2.9
Respondents: 27
Files
File | Uploader | Date |
---|---|---|
easy-aga-3.1-win32.zip
— final
Windows executable |
richard | 2009/09/06 04:13 |
easy-aga-3.1-osx.dmg
— final
Final source entry; fixed "lockup" |
richard | 2009/09/06 03:43 |
easy-aga-3.1.zip
— final
Final source entry; fixed "lockup" |
richard | 2009/09/06 03:35 |
menu.png
The menu |
richard | 2009/09/04 01:41 |
tree-with-bird.png
In a tree with a rescued bird |
richard | 2009/09/02 12:44 |
game-shot-1.png
First screenshot in level 1 |
richard | 2009/09/01 10:47 |
Picture 2.png
The protagonist |
richard | 2009/08/31 00:41 |
Diary Entries
Right, "Feather" it is
Abbey and I have had a brainstorming session and decided that the game will be:
- about a young witch (think Kiki from Kiki's Delivery Service),
- who leaves home and ventures to a distant land to discover herself,
- who finds the land in trouble - someone's turning the friendly forest creatures into baddies, and
- uses the power of magic found in feathers to help save the land.
- Inkscape for artwork and level design,
- squirtle for rendering the artwork (though modified to handle layers),
- lepton for pretty,
- coroutines for managing everything, and
- pyglet for doing all the messy grunt work.
Off to see a film
We're off to see Ponyo now. I've managed to wrangle Squirtle so it'll load both plain SVG and layered SVG now, and have an initial level loading with the player being placed in the correct position. A good start, I think.
Can haz platformer
Well, I've managed to accomplish a fair bit today:
- created an initial level idea with the action kinda planned out,
- mangled Squirtle to load SVG layers,
- rendered those layers in a meaningful fashion,
- used "data" from a layer as game information (placing the player start position),
- moved the player around in the world, including jumping,
- used the "ground" layer as collision boxes and made the player interact, and
- PARALLAX!!11!111one!11!
Day 2: moar platformey
All up a pretty good day today. I didn't work 100% on the game, but what time I did spend on it was fun. I also spent a while working on the art - why I chose to do a game with such a high art content I will never fathom.
- designed main character, drawing on Kiki of Kiki's Delivery Service (Abbey loves Kiki - we all do ;)
- did more work on level 1, fixing colors, adding more stuff
- first feather pickup item using particle engine
- score & timer; score flashes when score is added
- made level 1 sky a gradient; fixed hacks in squirtle to handle gradients again
- constrain player to the game bounds
- much tweaking of the player physics model
- baddies spawning, roving around following paths
- health; baddies hurt
- baddies are killable
Day 3: smarter baddies :)
I spent most of today at the science museum with my family; my daughter absolutely loved the planetarium show and thought some of the Star Wars exhibit and regular exhibits were cool too. Science!
On the game front though, I managed to get some new code in:
The baddies follow paths properly now (yesterday they just when from point A to point B and back again). The really neat bit is that the code to handle the pathing is:
def cycle_path(path):
path = itertools.cycle(path)
last = euclid.Point2(*path.next())
while 1:
next = euclid.Point2(*path.next())
last = yield euclid.LineSegment2(last, next)
Given a path consisting of (x, y) points. If the path is a loop (path[0] == path[-1]) then I create the path cycler with cycle_path(path[:-1]). If the path is open then I create the cycler with cycle_path(path[:-1] + list(reversed(path))[:-1]) (so bounce from end to end).
I pass in the current position when I ask for the next line segment so that there's no unsightly jump to move the baddie from its current position to the "proper" start position for the next segment. The baddies wobble along their path, you see :)
So not a huge amount of progress today but I'm very happy with how it's progressing regardless.
On the game front though, I managed to get some new code in:
- proper sprites for effects
- using Inkscape's rasterisation for some smaller in-game graphics now
- first tree & house
- added ledges - can move through sides & bottom but not fall through top
- baddies follow complex paths including loops and open paths
- fleshed out the structure of level 1 more
The baddies follow paths properly now (yesterday they just when from point A to point B and back again). The really neat bit is that the code to handle the pathing is:
def cycle_path(path):
path = itertools.cycle(path)
last = euclid.Point2(*path.next())
while 1:
next = euclid.Point2(*path.next())
last = yield euclid.LineSegment2(last, next)
Given a path consisting of (x, y) points. If the path is a loop (path[0] == path[-1]) then I create the path cycler with cycle_path(path[:-1]). If the path is open then I create the cycler with cycle_path(path[:-1] + list(reversed(path))[:-1]) (so bounce from end to end).
I pass in the current position when I ask for the next line segment so that there's no unsightly jump to move the baddie from its current position to the "proper" start position for the next segment. The baddies wobble along their path, you see :)
So not a huge amount of progress today but I'm very happy with how it's progressing regardless.
Day 4: animatilicious!
I spent at least half of today's effort working on animations. This consisted of creating the animation poses in Inkscape (tweaking the character design a little in the process) and saving off the PNGs for the animation frames. I then wrote the animation module for the game which doubled as an editor for figuring out the positioning of each frame. I ended up with quite nice walk animations going left and right.
The problems began when I added them to the game proper. The animations jumped too much from frame to frame (I was using the actual distance travelled for each frame's step to move the player). I tried making it smoother but it only worked going right and not left. Ugh. Eventually I gave in and I now use the same animation technique I've always used in platformers (hell, in anything) - a fixed frame rate of showing the frames and the animation is independent of the speed the player is actually moving. So the player moves smoothly but the character seems to slide across the landscape a little. It bugs me, and I'll be trying to fix it.
Once I got that out of the way I also worked on:
(bigger)
The other animal is a rabbit. I like the bird better. I'm hoping to create more animals.
I also spent way too long debugging the rendering of the yuck pools. My own silly fault, of course.
The problems began when I added them to the game proper. The animations jumped too much from frame to frame (I was using the actual distance travelled for each frame's step to move the player). I tried making it smoother but it only worked going right and not left. Ugh. Eventually I gave in and I now use the same animation technique I've always used in platformers (hell, in anything) - a fixed frame rate of showing the frames and the animation is independent of the speed the player is actually moving. So the player moves smoothly but the character seems to slide across the landscape a little. It bugs me, and I'll be trying to fix it.
Once I got that out of the way I also worked on:
- animals
- yuck pools
- puffs when baddies are done for
- invulnerability after damage
- more level 1 tweakage
(bigger)
The other animal is a rabbit. I like the bird better. I'm hoping to create more animals.
I also spent way too long debugging the rendering of the yuck pools. My own silly fault, of course.
Day 5: boss battle GET!
Not a bad day's effort today. Again I spent a bit of time not actually doing the game which was nice.
When I started the week I used the porygon skeleton which comes with a "mode" system. I thought it was pretty cool, but today when I came to implement the front menu for the game I just decided I didn't want to have to code another bloody menu so I ditched the porygon mode code and swapped in cocos' code. After remarkably little pain I had a working menu :)
I set my sights on finishing the first level today which I almost achieved. All up I added:
I didn't have time to get some stuff done that I wanted to: sketching out the second and third levels, and trying out some music and sfx (though I did play with sfxr to generate some sounds). I have the music selected but I've not actually tried it in-game.
Oh and birds fly away to freedom now instead of just hanging around ;)
No new screenshot today 'cos I'm just too damned tired. I hope to get a playable upload together tomorrow.
When I started the week I used the porygon skeleton which comes with a "mode" system. I thought it was pretty cool, but today when I came to implement the front menu for the game I just decided I didn't want to have to code another bloody menu so I ditched the porygon mode code and swapped in cocos' code. After remarkably little pain I had a working menu :)
I set my sights on finishing the first level today which I almost achieved. All up I added:
- the front menu
- game over handling
- tutorial mode (an alternative playing of level 1 with little help popups)
- the first feather / powerup pickup
- the second spell - the one you start with
- better art for the yuck pool bubbles
- earthquake mode!!1!
- extended level 1 to full length (basically doubling its size)
- level 1 boss battle!!1!!
- refactoring, tweaks and cleanup all over the place
I didn't have time to get some stuff done that I wanted to: sketching out the second and third levels, and trying out some music and sfx (though I did play with sfxr to generate some sounds). I have the music selected but I've not actually tried it in-game.
Oh and birds fly away to freedom now instead of just hanging around ;)
No new screenshot today 'cos I'm just too damned tired. I hope to get a playable upload together tomorrow.
Day 6: the bird arrives!
Today I started with drawing the Grand Phoenix:
(bigger)
Before you all go on about how mad my art skillz are I totally used a step-by-step tutorial to get that image. Came out nicely though, I think :)
I spent bits of today working cocos stuff into the codebase to make scene management work nicer. I spent a frustrating half hour trying to figure out why my damned cocos animations weren't working, only to discover that I'd (intentionally) overridden the cocos layer setup method which schedules the animations. Whups. It's actually something I've been meaning to address in cocos - there's a few places where you have to override a base class method to add behavior where it'd be much, much nicer to be able to just fill out a stub. For example have cocos do its stuff in _on_enter() which invokes a stub on_enter(). Or perhaps a different approach that's more backwards compatible ;)
Anyhoo, the rest of the day saw:
I've still got a bunch to add. Tomorrow is looking to be a short dev day again so I'm not sure how much I'll get done before Sunday. Things I would really like to achieve before then:
(bigger)
Before you all go on about how mad my art skillz are I totally used a step-by-step tutorial to get that image. Came out nicely though, I think :)
I spent bits of today working cocos stuff into the codebase to make scene management work nicer. I spent a frustrating half hour trying to figure out why my damned cocos animations weren't working, only to discover that I'd (intentionally) overridden the cocos layer setup method which schedules the animations. Whups. It's actually something I've been meaning to address in cocos - there's a few places where you have to override a base class method to add behavior where it'd be much, much nicer to be able to just fill out a stub. For example have cocos do its stuff in _on_enter() which invokes a stub on_enter(). Or perhaps a different approach that's more backwards compatible ;)
Anyhoo, the rest of the day saw:
- most of level 2 (town) done
- most of level 3 (castle) done
- make menu prettier
- end of level score tally
- end of level score
- high score table
- level 3 boss
- uploaded first version!
I've still got a bunch to add. Tomorrow is looking to be a short dev day again so I'm not sure how much I'll get done before Sunday. Things I would really like to achieve before then:
- baddies shooting so there's some more variety in the baddies
- queen throwing stuff - at the moment the ultimate baddie doesn't fight back :(
- health pickup or perhaps pickup count allowing N pickups = health
- finish level 2
- finish level 3
- intermediate spell powerup (bouncing)
- secrets? did I say that? shh!
- fix circular baddie paths
- fix the clouds so you can actually see them ;)
- more birds, more powerups
Day 7: the almost day
I spent most of today at a 6-year-old's birthday party. I now know what Ben 10 is all about :)
I got a few hours to work on the game though, and ended up with:
Phew. I'm pooped. Sleep time now. Catch you all at the finish line tomorrow :)
I got a few hours to work on the game though, and ended up with:
- screen resolution "independence" (I give up if you don't have 600 lines to work with)
- some baddies shooting
- a second-level spell
- created (thanks cfxr!) and added sound effects (though some need replacing)
- music - only one track though
- tweaks to level 2
- queen throws stuff at you now though she's still easy to beat ;)
- added notes about opengl, lepton and avbin requirements to the README
Phew. I'm pooped. Sleep time now. Catch you all at the finish line tomorrow :)
Day ... 8 :) the final rush
Well, not for me. I tweaked some of the sound effects, added a story screen, not too much.
Then I edited some of the pyweek.org site code to change a few things (turn off judging until after the 24 hour upload grace period is over).
Then the deadline hit and I put together a source upload package. Which I tried out and got a bus error. Fixed, and finally uploaded my final submission! Yay!
Things I didn't get to do during the week:
Then I edited some of the pyweek.org site code to change a few things (turn off judging until after the 24 hour upload grace period is over).
Then the deadline hit and I put together a source upload package. Which I tried out and got a bus error. Fixed, and finally uploaded my final submission! Yay!
Things I didn't get to do during the week:
- a switch to turn off the music
- much better Queen Baddie battle
- more props / decorations in the second and third levels
- "super jump" powerup which I thought might be fun
- a count of the "coin" pickups to count towards regaining health
- fix sometimes-broken circular baddie paths (sometimes they work, sometimes not so much)
- sloping ground
- some secrets :)
On coroutines
One of my experiments for this pyweek was to make use of Python's new(ish) coroutine support to implement the behavior of the player, baddies and some other scripted things in the game.
In short this looks something like this:
class Player
def update(self):
while 1:
dt = yield
self.x += self.dx * dt
self.y += self.dy * dt
player = Player()
update = player.update()
update.send(None)
...
update.send(dt)
OK, so this is neat in theory. You could have multiple loops in there with multiple entry points (yield statements) depending on the current "state" of the player, and so on. I've seen some nice implementations of byte-chomper network servers using this sort of approach.
Only it didn't seem to work. Eventually I was back at square one with a single yield statement and a really, really long update() code body.
I've just refactored it to use separate update() methods depending on the current state of the player:
class Player
def update(self, dt):
self.current_action(dt)
def do_jump(self, dt):
# do jump stuff
if landed:
self.current_action = self.do_land
player = Player()
player.current_action = player.stand_still
I'll note that the simpler coroutines I implemented for the baddies and other things are still coroutines - but I'll probably re-implement them as regular functions as well.
So, was I just doing it wrong, or are coroutines just not that useful for a time-based player update?
In short this looks something like this:
class Player
def update(self):
while 1:
dt = yield
self.x += self.dx * dt
self.y += self.dy * dt
player = Player()
update = player.update()
update.send(None)
...
update.send(dt)
OK, so this is neat in theory. You could have multiple loops in there with multiple entry points (yield statements) depending on the current "state" of the player, and so on. I've seen some nice implementations of byte-chomper network servers using this sort of approach.
Only it didn't seem to work. Eventually I was back at square one with a single yield statement and a really, really long update() code body.
I've just refactored it to use separate update() methods depending on the current state of the player:
class Player
def update(self, dt):
self.current_action(dt)
def do_jump(self, dt):
# do jump stuff
if landed:
self.current_action = self.do_land
player = Player()
player.current_action = player.stand_still
I'll note that the simpler coroutines I implemented for the baddies and other things are still coroutines - but I'll probably re-implement them as regular functions as well.
So, was I just doing it wrong, or are coroutines just not that useful for a time-based player update?
Continuation...
No, not continuations, but rather where I'm going with the game now :)
I gave a quick off-the-cuff presentation to MPUG last night showing how my game evolved and grew over the week. I used a checkout from my local bzr repository from when I finished each night. I'll be giving a better version of that presentation at this weekend's BarCampMelbourne.
I've been refactoring the player control/update code to clean it up. I'm also planning on writing proper cocos layers for my SVG layer loading using squirtle. This should clean up the game rendering and management.
I've got a couple of other local changes to cocos that I need to check over before committing too.
I wonder whether pyggy could do with being a couple of months shorter?
I gave a quick off-the-cuff presentation to MPUG last night showing how my game evolved and grew over the week. I used a checkout from my local bzr repository from when I finished each night. I'll be giving a better version of that presentation at this weekend's BarCampMelbourne.
I've been refactoring the player control/update code to clean it up. I'm also planning on writing proper cocos layers for my SVG layer loading using squirtle. This should clean up the game rendering and management.
I've got a couple of other local changes to cocos that I need to check over before committing too.
I wonder whether pyggy could do with being a couple of months shorter?
Better controls
Abbey was having a bit of difficulty using the keyboard to play the game. She's not comfortable using multiple keys at once and even then often has to look to find keys.
So I've added WiiMote support :)
Actually it's a bit of a hack at the moment because I couldn't get any of the OS X bluetooth / wiimote libraries to work. I ended up installing DarwiinRemote and configured it to generate keys appropriate for my game (with the remote held sideways and buttons 1 & 2 used for spell & jump).
I'm going to look into PS3 controllers next...
So I've added WiiMote support :)
Actually it's a bit of a hack at the moment because I couldn't get any of the OS X bluetooth / wiimote libraries to work. I ended up installing DarwiinRemote and configured it to generate keys appropriate for my game (with the remote held sideways and buttons 1 & 2 used for spell & jump).
I'm going to look into PS3 controllers next...
Post-mortem presentation video
I presented a post-mortem kinda thing at last weekend's BarCamp in Melbourne. The kind folks there video taped it! So here it is: The 7-day Game.
I'm going to look into putting together a higher-quality video with basically the same content but recorded directly off my laptop. If anyone's got any suggestions for content they'd like to see in the video (except for "less 'um's please") then please comment :)
I'm going to look into putting together a higher-quality video with basically the same content but recorded directly off my laptop. If anyone's got any suggestions for content they'd like to see in the video (except for "less 'um's please") then please comment :)