And now to add a boss fight!
Ludum Dare 30
Ludum Dare 28
Ludum Dare 26
Ludum Dare 25
Ludum Dare 25 Warmup
Ludum Dare 23
Ludum Dare 23 Warmup
Ludum Dare 22
Ludum Dare 22 Warmup
And now to add a boss fight!
Yeah, it’s not Ludum Dare related, but it’s still game-jam related, and I DO WHAT I WANT!
Hello! This is the post-mortem for Pulley Planet, which will discuss the process behind making the entry and the thought that went into it.
Yes. There was a day -1. Usually I go to Mati & Itamar’s house one day before LD. This time I accidentally went 2 days ahead of time.
We set up our workstations and downloaded the correct tools, but as night dawned Itamar decided to look at the countdown at the top of the compo website. After indulging in some serious CSI “enhance!” type investigation, we concluded that we had indeed miscalculated our time.
I had no choice but to go home. Ashamed.
There was no way I was wrong in my timing this time, right? I showed up at their house again and we started wasting our final hours of the night playing spooky horror games and watching some videos.
We all woke up at around 7, saw the theme and immediately felt disappointed. It’s not a good theme. I’ve written my stance on what sort of theme is good and what sort is bad in the past. We promised ourselves we’d go get some Burekas and sit and think – but the supermarket had none left! We bought some cereal and orange juice and headed to the park to start our brainstorming session. Lo and behold – no Burekas, no brain juice. We weren’t able to come up with anything.
Our first idea consisted of an alien floating in space and connecting planets to itself to become a huge space-craft and fight off invaders. It seemed cool at first, we ran some prototype tests, but eventually we stepped off the idea when we realised it wasn’t fun enough to make.
It came to lunchtime and it had been 5 hours since we woke up and we still hadn’t started. Thinks were starting to look grim when Mati suddenly came up with a saver; ameliorating a previous idea Itamar came up with, this new idea involved pulling planets and beating up baddies. We instantly loved it.
I started work on a basic platformer engine and Itamar started design our main guy – Paulie. In around 3 hours of work, we had our player character who could move around:
Fun fact: Paulie is not a single sprite. He is infact three independent sprites moving together at different layers;
This helped a bunch with making pretty animations. With each hand being independent of the body, we can basically make them play one animation (running/punching) while the body plays another (idle, running, jumping). And thus Paulie’s symbolic ATATATATA attack was born:
More work hours down the pipe, and we had a complete bath of animations and basic hit-boxes.
As you can see, at this point we already had two different running animations: one for running right and one for running left. The reason we went with two different animations is to help convey Paulie’s character: running head low towards enemies, ready to punch some faces, while running stressed towards the pulley, under pressure.
Meanwhile Mati was hard at work at trying to come up with a tileset.
With the day close to being over, Mati finished his work and we implemented the tileset to see how it looks.
Content and tired, we hit the bed.
This day mainly revolved around enemy design, particles, game world and sound. Mati was in charge of designing the enemies while Itamar was in charge of animating them. I took the job of making pretty particles and effects.
I also started working on environmental effects.
Mati drew some clouds which are randomly spawned on the screen:
I had a pretty solid idea of what we wanted for each planet:
Water planet: rain drops and splashes
Fire planet: everything is burning and smoking, Paulie sweats twice as much when running
Ice planet: snowing, freezing screen effect, everything’s just a bit brighter
Storm planet: dark ambient light, random electric discharges, layered storm clouds
Here is the final result:
Note that this was made in the latest build, so some Day 3 stuff is present (such as score).
With the elementals done and environmental effects in place, Mati & Itamar started working on the game world while I worked on plenty of more effects.
We wrapped up for the day knowing we had most of the assets done and much of the engine complete.
Day 3 was mainly for, well, making the game playable. Until now there was no wave system or an enemy spawning algorithm. You could only spawn enemies by right clicking.
We woke up with a fresh new soundtrack Jason had composed over night:
Fun fact: a fastened version of this song plays when you’re below 4 hits left. Try it in-game!
Work on the ‘director’ AI has started. Basically, the director’s job is to spawn enemies in an ordered fashion with increasing difficulty without cluttering the game (aka keeping the screen tidy!).
The director has a bunch of variables it keeps track of: wave type, dominant percentage, dominant type, wave quota, streaks. Here is the step for constructing and spawning a single wave:
1. Choose a wave type (runner or casual). Runner waves are shorter, but enemies run at you, while casual waves are, well, casual.
2. Run some math to determine wave quota, dominant percentage, enemy walk speed and distance between each enemy in pixels – all according to wave type.
3. Create an empty list the size of our quota. Choose a random enemy type to be this wave’s dominant type, and fill the list with that type for the dominant percentage (p*quota).
4. Fill the rest of the list with random enemy types.
5. Shuffle the list.
6. Create streaks: for every 10 enemies in the quota, a streak is created. A streak is 3-4 consecutive enemies of the same type in the list. The director chooses a random position in the list, chooses a type which is NOT the dominant type and replaces all enemies from the random position to random position+(3 or 4) to the new selected enemy types. This is one streak.
We now know what the wave will consist of before it even starts. Some notes about game progression:
* In casual waves, the dominant percentage starts at 60% and decreases by 2.5% for every wave – down to a minimum of 30%.
* In runner waves, the dominant percentage starts at 90% and decreases by 1.5% for every wave – down to a minimum of 40%.
* In casual waves, enemies move at 0.2 + (wave/300) pixels per frame.
* In runner waves, enemies move at 0.5 + (wave/300) pixels per frame.
* In casual waves, enemies spawn with a space of (45-wave) pixels between each other, down to a minimum of 30.
* In runner waves, enemies spawn with a space of (100-wave*1.5) pixels between each other, down to a minimum of 60.
* In casual waves, the enemy quota is wave*2.
* In runner waves, the enemy quota is simply the number of the wave.
And that’s the directory. Aside from that, we worked on polishing the game (which we love doing), making sure it works properly on HTML5, tweaking some effects and adding a main menu.
We added a sleek combo system:
Mati drew a PUNCHTASTIC batch of flavor pictures for combos:
Itamar drew a logo which was tragically deleted TWICE before being remade and properly saved the third time:
We also worked on some more visual feedback, such as planets in the background being swapped to represent what defeats what:
And after slapping a half assed menu, Pulley Planet was finished at around 3 hours before the submission deadline. “:D
What went right
What went wrong
All in all, developing Pulley Planet was a solid, fun experience for all of us. Although some of the games’ potential was blown, we’re still very proud of it, and we hope you’ll like it.
- Lonebot ♥ (our website’s faster now! check it out)
P.S: This is my 100th post on Ludum Dare! Party!
And we’re done! What a ride.
We’re almost done! Just need a menu now. We didn’t manage to implement highscores though
End of day 2! A lot of visual and sound work done today. Good luck to everyone submitting for the compo and good night!
And we have tiles! What a busy first day. See you in 7 hours!
Finally got around to programming my (least) favorite part of a game’s development cycle: collision checking.