Ludum Dare 45My second time around.
Phew! Ludum Dare 45 is over!
This was my second participation in a game jam. I had a lot of fun and learned a bunch of new things I will share with you. In 48 hours the game Sheep Keep came to life which you can play in your browser here. You can also visit the page on Ludum Dare.
The theme was You start with nothing and to say it nicely: I did not like the theme. But it seems to be a common trope that the theme always sucks. However, Ringo taught me how to prepare for the worst.
Here is the obligatory timelapse. 48 hours compressed to 2.5 minutes:
- Physic2D.Simulate() is great.
- Krita is awesome if you get used to it.
- Unity animation clips are dead easy.
- Cleaning up procedurally generated levels is hard.
- Always go to the extreme if you add difficulty levels to your game.
- I need to dig into Unity sprite ordering.
→ WebGL Release (Runs in your browser)
→ Windows Release (Download, 20MB)
→ Linux Release (Download, 21MB)
→ Source Code on Github
Things which worked
If you disable Physic2D.autoSimulation and manually invoke a physic step through Physic.Simulate(), you never have to use FixedUpdate() again. It's just awesome and should be the default in my opinion. You can read more about it in my previous blog post.
In the forefront I decided to use Krita to create all my assets, which was a good choice. It offers everything I could dream of while drawing with a pen tablet, maybe even a bit too much. What I mostly need works quite well tough, mainly drawing with stabilizer and layer groups. Alpha inheritance is also awesome even though I have to look up how it works each time I need to use it... I even tried out the sprite animation tool in the week before the jam. How to use it properly is still a mistery to me and luckily I decided to create all animations in Unity during the event.
I also learned that I need to rework each sprite at least once, even if this is quite time consuming. This can be useful though if you plan for it in your schedule. The goal is to create something workable fast with roughly drawn sprites and rework them later on. This way, even if you run out of time, you can provide something shippable.
All map sprites are 256x256 pixels wide which worked well for authoring. However, I also added tiny details, like subtle shading or blades of grass, much too small to make a visual impact.
And let me warn you about drawing fences for procedural generated areas... I spent a considerable amount of time on fence variations for all sides and all different corner pieces to connect them. My relationship status with fences turned to It's complicated.
Pre-made color palettes
What helped me immensely was checking out some color palettes, which can be imported into Krita. There are not many things in this world which bore me more than choosing colors and creating color ramps. That is why I have nothing but the highest appreciation for the nice people posting color palettees at lospec.com. Simply download the Gimp (gpl) file for the palettes you like most and import them into Krita. I went for vines flexible linear ramps which is fairly simple to use. So thank you Vine 2D! (His twitter account is worth a look!)
Unity animation clips
I'm not an experienced animator and still got some decent animations into the game. Well for my standards at least... Everything done with Unity animation clips and the Unity animation controller. This was new to me. On other instances I already tried to animate in blender, Puppet2D and DragonBones and that's where I learned to loath any kind of export / import step or third-party animation library in Unity. It's just adds an additional place where things can go wrong.
Should you decide to use Unity animation clips keep in mind that you cannot easily rename or move around sprites in the hierarchy of your character prefabs. The transforms are referenced by the clips through a path relative to the animator component. Therefore you need to be careful to create a flexible and possibly extendable hierarchy while you create your characters.
I also need to mention that my animations do not feature any kind of sprite deformation, skeleton-based animations or inverse kinematics, but arguably this would be overkill for a game jam. But maybe I should look into Anima2D for a free alternative.
First let me tell you, that I love ProcGen. I believe that most games should at least add some elements which are generated. It increases replayability and releases a tiny bit of dopamine in the player's brain whenever he or she encounters a new level. Additionally you will be able to save time later on, because you won't need to create levels manually.
But let me also tell you that adding procedural code is time consuming and error-prone. You need to make sure that the player can be spawned in a safe spot, that every corner of the map is reachable and that all your sprites are compatible with an ever changing layout. Creating a map is actually quite simple, just the clean-it-up-through-code part can be daunting.
In Sheep Keep I used a simple algorithm to create maps which increase in size and difficulty. It starts with a map of unwalkable tiles and a fixed-size square of walkable spawn tiles in the center which won't be occupied by any other elements except the player. Then random rectangles of walkable tiles are added at the outer edge which must overlap an already walkable tile. This way I can be certain, that each tile is reachable by the player. The map boundary increases in complexity if you repeat the last step, which can be used to increase the difficulty in later levels. Finally unwalkable rocks and sheep are randomly spawned.
There are 2 problems with this approach. First, by adding unwalkable tiles, like rocks, near the end of the generation process, there's always a chance, that small passages are inadvertently being closed. This breaks the game, if there's something behind the rock which the player must reach. Second, the map creation can introduce small unwalkable areas which are one tile wide or even islands of unwalkable tiles. It can look odd if you add a fence there, but I did not have time to clean up those cases. In the map above, on the bottom left, there is a single fence tile only connected to the south, looking out of place.
If you want to know more about cleaning up such tilemaps I recommend you this article. It's about creating a cave with cellullar automata, but some strategies could also work for Sheep Keep.
Things which did not work
I decided to add three difficulty levels early on. On easy, sheep start running, when another sheep nearby dies. On medium, sheep start running, as soon as the player strikes his weapon nearby. On hard, sheep will always run around. The plan was, that I wanted to let my kids play the game on the easiest level without feeling frustrated. But that did not work out, because they were not used to the fast character movement and the small hitbox of the player. In my view the game is much too easy, even on the hardest level.
Takeaway: Make easy really easy. And make hard really hard. You need to go to the extreme to please all kinds of players. This requires a fair amount of playtesting.
Not enough juice
It's the magical ingredient which turns a so-so game into an unforgettable, epic experience featured on Steam. I recommend blackthornprod for a simple Unity-related explanation and the art of screenshake which is an entertaining must-see in my view. Sheep Keep falls flat in this regard due to bad planning on my part. A reviewer pointed out to me, that I should add vignette and color grading which made realize that I completely forgot to enable post-processing effects! I completely lost it and broke down laughing frantically on the floor...
Never postpone unnecessary effects. They are essential and increase your morale while you are testing your soon-to-be rockstar game. So enable that amazing bloom shader, add a ton of particle effects and make your screen shake physically on every hit!
As an example, in the last few hours I added two effects which alone add so much to an otherwise bland game: Blob shadows and weapon trails. Probably nobody noticed them, however I'm proud of it anyway.
This is a topic which I expect to be quite simple, but reality seems to indicate the opposite.
What I want is specifying a sprite order within a single prefab, like draw the head of a sheep in front of its body. Additionally I want to order all instantiated objects in the scene, like draw objects deeper down the screen in front of objects higher up. I also want to properly handle the case, where two characters overlap and occupy the same y-position. I haven't found an easy and performant way to fullfill all these requirements, but I admit that I haven't dug deeply into this topic, yet. I still believe that this should be such a common request, that there must be a single switch in Unity which solves sprite ordering for different genres, no?