Woop woop, I'm doing one of these too.
You can play it at https://alakajam.com/3rd-alakajam/308/infinite-potential/
(Post-mortem also on https://iris-xiii.tumblr.com/post/175512643353/infinite-potential-post-mortem)
Apparently there's a few mac bugs regarding fullscreen. I'm going to be ignoring them from the time being, since I can't test on mac (oops) and that looks hard to fix. Nothing game breaking, thankfully.
Being made during 48 hours, and not being used to such a short time limit myself, it's obviously nothing to drop your jaw at. Still, I think it manages to be fun sometimes, or at least it's definitely fun for a while for some people, which is great enough to me for the time being. Now, time to delve into its issues!
First off, spawning. I don't think only allowing powerups or enemies to spawn when they're off screen was a great idea. While it punishes staying in the same area for too long, it punishes with boredom, which isn't exactly good. Also, while having powerups spawn only when you can't seem them worked out alright on my computer, it gets rather messy with different screen and window sizes. If your screen is just large enough, nothing will spawn, ever. The spawning system was a bit rushed over, but I failed to consider these issues and I will have to be more careful next time I add anything which depends on the size of the window you're playing on.
Weapon balance issues: There's a few, even though it used to be even worse. The sword (2nd wepaon) is widely regarded as useless and too risky to use, and many agree that it needs a longer range or something among these lines. Although its hitbox was increased to be twice as large during development, it was clearly not enough, and dealing only twice as much damage as a fireball does, it's usually not worth the risk. Regarding the fireballs and bombs, I think they're fairly good myself. Some people have complained about the bombs being on a way too large cooldown, and taking too long to go off, but considering they do way more damage than anything else in the game (Unless you've managed to gather a serious amount of powerups) I think it's pretty balanced. Even if it takes 4 bombs to get rid of some creatures, you can usually outrun them by getting one or two powerups: So they're not as dangerous as they might seem, they're just a bag of extra points, or a punishment if you happen not to be careful enough.
Controls: I think I've done way better in this game than in the past, and so far only one person has complained about them. While you can stick to ceilings during a jump and that shouldn't happen, it's the only thing that doesn't feel quite right (to me). Could definitely be improved on, but they're reliable and good enough.
AI: I've gotten all kinds of feedback on this one. It's a hacked together mess, and fairly dumb, I acknowledge it. However given how basic it is, it doesn't work too bad. While the completely random jump allows enemies to get stuck for longer than they should, it also makes it impossible to predict when they'll decide to jump, leading to some situations in which they'll jump at the same time you do while you try to jump over them, and thus end up smacking right into the creature. During those moments it seems much less dumb than it really is. AI is definitely something to improve on, but it turned out just as you'd expect given the amount of time I spent on it (very little).
Map design: Another hacked together mess. If you were to know how the map actually works, you'd puke. Its design itself has a few serious issues: The right half of the map seems more enjoyable, mostly because there's platforms allowing you to move freely, while it's much harder to stay on the move on the left side. There's also a few spots in which you're completely safe, forever, and it might break the flow of the game, along with a couple of 'cheese spots' you can throw bombs off from, and farm for a high score with 0 risk. Balancing is hard, okay?
Powerups: Could definitely be improved on. Some kind of UI showing how many powerups you've picked up so far, and of which kind, would allow the player to keep track of its progress more easily. I admittedly wish I would've had more time to throw in a few powerups more. The damage increasing powerup is particularly bad, in that there's no way for the player to tell the difference most of the time. On the other hand, the jump and speed powerups feel rather great and it's very easy to notice that you've taken them. In regards to the health powerup, I'm feeling lukewarm about it. It's very much necessary, but it feels too weak sometimes.
Creatures: Again, could be improved on. For those of you unaware, there's three: The first one is a spider-like, small creature which deals an also small amount of damage, and is fairly easy to dispose of. However it's capable of jumping, and there's plenty of it. I believe this one is fairly well balanced, even if the AI needs quite a bit of love.
The second creature is tanky in all senses of the word. It's a big triangle, and while it doesn't jump it deals considerably more damage than the previous creature, and has a lot of health. Easy to outrun, there's very few of them, and unless you've managed to gather a lot of power-ups throwing quite a few bombs at it is usually the answer. Final thoughts: The amount of points it drops isn't worth how boring it can be.
The third and last creature is a hand. If any fireballs touch it, they will bounce back towards the player and damage it. They always try to stay at the same height you are to be able to do this better, and until you've collected a few health powerups, they insta-kill on touch. This is definitely a creature the game needed: Fireballs go through everything, except these hands, which make them bounce back and towards the player. It serves to keep the player from mindlessly spamming fireballs too often. Although it's 'weakness' was supposed to be the sword, it's not worth the risk and throwing a couple of bombs on it works just right.
What a ride, I think this covers most points and feedback, phew! There's clearly a lot that could be better, but it's far from awful and at least it can be fun.
A massive thanks to everbody who played and commented on my game!
For my first game jam this has been an amazing experience. I'm so proud I managed to put something together in time, although it could have done with a lot more added in.
I've loved playing everyone's games. Every single one was fun and creative. Can't believe how talented everyone is.
My favourite part was seeing everyone's individual take on the theme.
Well done everyone and thanks for everything!
I've put together a timelapse of how I created the art for my entry, Dirt.
Thanks to everybody who has played and commented on my game so far, the feedback has been really helpful. I've played almost all the entries that I can for the moment (Mac/web), but I will be borrowing some time on a Windows machine over the weekend to play the rest and really looking forward to it!
Our entry A.G. Hope has been updated! The original jam version has been patched with a couple major bugfixes, but we also took the time to make a post-compo of the game.
This new version is still far from our the original, way too ambitious goals, but brings the game on par with how we pictured it on the Sunday morning after refining the game design:
Big thanks in passing to all who already reviewed our game! We're super happy with the game reception so far, and would love to hear thoughts on the new version.
You can watch the highlight of the games here:
Another Alakajam Stream is happening Saturday! follow me on twitch for notifications and check the schedule for your local time on the channel page below the video player https://www.twitch.tv/tiger_j
Yeah so it turns out one of the reasons this game SUCKED (one of) was this code:
def update(self): if hour <= 12: self.average_temperature = self.base_temperature-self.fluctuation+(self.fluctuation*2*(hour/12)) else: self.average_temperature = self.base_temperature+self.fluctuation-(self.fluctuation*2*((hour-12)/12)) #for tile in tiles: # difference = self.average_temperature-tile.temperature # change = difference*self.movement # tile.temperature += change wind.active = self.average_temperature <= -15
notice how some of the lines are commented (#)? Well those happen to be the very, very important lines for changing the average temperature of tiles throughout the day. Don't know how I didn't catch this. Oh wait, it's because I'm an idiot. Anyway it's fixed and everything but I just wanted to make a post explaining everything as well as the new jam/post jam version numbers (according to the rules, post-jam bugfixes are allowed so long as they are really broken, which counts in this case)
This is the second part of this postmortem. Catch up on the first part here.
We have fire, we have buckets of water, we can get the buckets to the fire… now what? Throw 'em, of course! So if a peep in state
PASSING sees that its
destination cell is not manned, but rather flammable, it will throw the water onto the fire. (It will also do this if there is no fire. I played with the thought of keeping houses wet to prevent them from catching fire, but didn't get round to implementing this.)
The throw animation is similar to the bucket-passing animation: simply move the bucket in the direction of the destination tile. However, it moves a lot faster to make it look like it's being thrown. Also, the bucket is rotated in the direction of movement.
When the bucket reaches the edge of the tile, the peep destroys it and emits a
throwing signal that the
level_base.gd script listens for. Upon receiving this signal, a water animation sprite is added to the
objects node, and the fire in the tile (if any) has its size reduced by 1.
I also changed the control scheme slightly, to allow the player to arbitrarily change the direction in which peeps pass buckets. This meant that changes are no longer triggered by dragging on a tile, but by dragging from one tile to the next. At the moment the mouse cursor crosses the border between two tiles, the
destination of the source tile is set to the target tile, and peeps are summoned as described before. This allows for any change in bucket routing.
Unfortunately, it doesn't allow the player to liberate peeps for deploying them elsewhere. Clicking or dragging with the right mouse button might have been a logical gesture for this, but I wanted this to be workable on mobile devices as well, so I went with the slightly unintuitive "drag from unmanned cells into manned cells" instead. It's not great, but it works well once you understand it.
Now I had an actual game! While playtesting, I quickly realised that it had a major flaw: either you need to start off with a huge number of available peeps, or you lose quickly when the fire outgrows your tiny army. My quick and dirty solution was to add some windows to the houses:
A house with light behind its windows contains one peep. As soon as the house catches fire, the peep runs outside and is available for the player to deploy in fighting said fire. This works well, because it gives me a way to control difficulty by balancing the number of occupied and unoccupied houses. (I didn't do much of such balancing, so in the later levels, all houses are occupied.) Also, the new peep is spawned close to the location where it's likely to be needed, leading to a minimum of player frustration.
By "chrome" I mean all the window dressing that isn't part of the game proper, but is needed anyway. Things like menus, intros, game-over screens, level switchers and a HUD.
The first step was to detect when all fires were put out, and throw up a win screen. By counting how much of the houses were still standing, I could even assign a score. High scores are being kept in a simple INI-like file, read and written by Godot's built-in
On the win screen, I put a "next level" button, so I had to make sure there actually was a next level. While I was at it, I also put level switching buttons on the main game screen. I didn't bother locking future levels, because any level can be completed (albeit with a terrible score) just by waiting for the entire city to burn down.
I also added a pause button. I don't usually bother with this during game jams, but in this case, I saw it as a core gameplay feature. It gives the player a chance to catch their breath, and give new instructions to their peeps at leisure. Adding pause functionality was a learning opportunity for me, but Godot's built-in pause functionality turned out to be exactly what I needed. You can simply tell the entire scene tree to pause and unpause. Each individual node can be configured to be processed or not while the tree is paused, so fire stops spreading and your peeps stop moving, but the GUI continues to be responsive.
This was also when the intro text was added. Godot's built-in
AnimationPlayer is absolutely wonderful for making and tweaking these sorts of transitions. Any property can be animated, including user-defined ones. Animations can call functions on cue. And all this is going to get even better in the 3.1 release.
So far, I'd used only one, static sprite for peeps:
This was in the category of "good enough for now, maybe polish later". I should have done sound effects first, but I'm always a bit hesitant because I'm inexperienced with them (and hate Audacity), so I wanted to improve the way the peeps look and feel.
I started by splitting them into a head and a body, and colouring the body grey:
By modulating (multiplying) the body with another colour, I could achieve a varied looking population with very little effort. For more variation, I also added a second head shape, based on what a quick Google image search led me to believe was appropriate headwear for women in 17th century London:
I didn't bother with a separate body sprite for women, figuring that the generic coat was sufficiently unisex. And finally, I duplicated all these and used them as a basis for sprites facing left, right and up:
It's worth noting that all these sprites are still 16×16 pixels, so I can just put them directly on top of each other without having to bother with positioning and alignment.
Implementing all these sprites in the game was easy, because
peep.tscn was already its own scene, decoupled from the rest of the code. So I could just add a
head sprite node, as well as a
set_direction function to point the peep left, right, up or down.
A slight difficulty arose with the orientation of peeps passing buckets: I wanted them to pass buckets from side to side (left to right), but didn't want them to stand with their back to the player and obscure the water buckets. My current solution for this isn't perfect, and will sometimes cause peeps to stand clumsily with their back to the peep who's passing them a bucket. But it's good enough. I also added an offset so that peeps would stand back slightly, and pass buckets in front of them rather than through the middle of their sprite.
Then for the final sprite, the star of the show, these 4 pixels:
The peeps' hands are actually two separate sprite nodes, and they're being moved around depending on the state the peep is in:
All this is rather hacky, last-minute code, but we were nearing the last minute, so this was entirely allowed. Fun fact: to hide the right hand when the peep is facing left and vice versa, I don't call
hide(), because that would mean I have to remember to call
show() again later on. Instead, I simply set its position to
99999, 99999 so the hand is drawn offscreen.
I realised that the control scheme wasn't extremely intuitive, and would need some explanation. What better way to convey this than having people learn while playing the first level? So I drew some arrows and slapped them onto a separate bunch of tile maps, which are only present in
The way the game detects when to proceed to the next tutorial instruction is rather horrible. It checks after every drag operation whether this ended up in a tile containing a tutorial arrowhead. These arrowheads don't have consistent naming, so it's just a hardcoded list of tile names and directions:
match [tile_name, to_cell.coord - from_cell.coord]: ['tutorial_5', Vector2(0, -1)], ['tutorial_7', Vector2(1, 0)], ['tutorial_8', Vector2(-1, 0)]: tutorials.pop_front().queue_free() $tutorial_timer.start()
This system is probably broken in a fair number of ways, but as long as the player does as they're told, they won't notice. And if they do differently, they probably already know how to play anyway.
Less than two hours to go until the deadline, and the game was still completely silent. I let a mute game happen to me last time, but not again! Unfortunately I lack even a basic standalone microphone, so I used the mic in my webcam to record everything.
The fun part was, of course, the yelling voices. Six variants of "aaah" for panicking peeps (three of which contributed by my girlfriend, but I didn't deem this enough of a contribution to switch to the "team" category), and several "fire!"s for peeps being driven out of their house by the fire. I used the Equalize filter in Audacity to cut the bass tones, which gives these sounds a more "outdoors" quality. In the Godot engine, I randomly changed the pitch plus or minus 20% to get some extra variety.
The alarm bell sound was made by hitting a steel pot lid with a wooden spoon. It was difficult to make this loud enough while preventing clipping. I tried with a Compressor filter, but that didn't help much. But the perfect is the enemy of the good enough, so I moved on.
The splashing sound was just me making funny noises, with the pitch shifted down to more closely resemble a bucket full of water rather than a mouth full of tongue and saliva (you're welcome).
The hissing sound that you get when water hits fire (actually, come to think of it, also when hitting a non-burning house…) involved actual fire to make. I heated up an empty pan on the stove, carried it over to the webcam on my desk, and poured cold water into it to make it sizzle. It didn't sound nearly the way I had imagined, but with some more pitch shifting I think it turned out quite well.
The crackling sound that the fire makes is just me crumpling up a page from a newspaper. In context, it's surprisingly effective. To make it loop, I didn't even bother to do any kind of crossfade; it turned out that the loop point in a sound full of clicks, pops and crackle is undetectable anyway. In the engine, this sound is continuously looped, but its volume is changed based on how much fire there is on the screen.
Finally, two of the sounds were created entirely inside the computer. The "ta-daa" sound you hear when you win a level was made in LMMS. It's just a C major chord played over two octaves on a brass-like synthesizer instrument.
For the music that plays during the intro, I was orinigally looking for a moody droning instrument. But while browsing the LMMS instrument library, I found this deep bell sound that seemed fitting. I started experimenting with simple melodies, and soon it clicked: it had to play the Westminster Quarters. This is the melody played every hour, on the hour, by Big Ben in London. Admittedly, the tune hadn't been written yet in 1666, but I'll allow for this anachronism for the sake of awesomeness.
This has turned into a pretty long read, but I hope it's given you an idea of what went into making The Great Fire. And maybe you even learned something. I certainly did!
This article was cross-posted from my blog.