Davide Rossetto

LD 42

Couple of hours in, first time in compo

I took the hard way, soloing in only 48h. I had some neat ideas, bad thing I'm just a lonely programmer and my artistic skills are, well, preschool grade.

Anyway, these are my tools

  • Unity
  • Photoshop/Aseprite
  • Bosca Ceoil
  • Frustration relief

My idea is pretty simple (and not very original, I'm thinking about a twist): you are the major of a very tiny village, just a bunch of huts, and you have to upgrade your town in a literal minute. Replace older building with new and shiny new houses and reach net worth limit, you will be elected one again and get a little more space to work!

I had more detailed ideas written in paper, I know this will be a journey to hell to debug and balance, but if it will be so easy where is the fun!

Currently I'm doing part of the art, at least to get things working. Roofs for building are coming pretty well:

houses.png

Time to bed for me, happy daring! :)

Ludum Dare 49

We got the idea!

After a couple of hours of brainstorming we got our unstable idea!

sketch.png

GOLPE will talk about an unstable government, powerlust politician and dangerous mobster knocking at your door. Handle them, decide if you talk gently to them or react fiercely. You are the State, your enemy is the GOLPE.

Ludum Dare 50

Almost ready for the weekend!

Hey friends!

I just moved abroad, so I have a lot of time to spend. What best opportunity to partecipate to LD50? This is the fourth time over the years I will partecipate to the jam, but I never delivered, mostly because those factors:

  • Overscoping: I have to marry the idea that I can't create a masterpiece in two days. Keep the game simple and self-contained, don't overthink it and be aware to scope creep.
  • Theme drift: sometimes I get so attached to a specific mechanic that I ram the theme into it until they fit, creating a game with a compromised mechanic and out of theme. I should start with the theme, then extrapolate a good mechanic from it.
  • Lack of motivation: the tools you use could not collaborate, it happens. In that case I have to fix (or go around) the problem instead of giving up.
  • Burnout: working for two day straight is not good for you: you will be energy deprived and unmotivated very soon. Instead plan your sleep, your meals and maybe also a walk. It's very useful when you are stuck!

I'm defining the tools I will use this time, I already use them and I trust them (don't betray me please):

  • Engine: Unity, the swiss army knife for me. I would like to go for Godot, but I haven't really the know-how on the latter.
  • Text Editor: the one and only Visual Studio Code. For notes I think I will use Notion or Obsidian.
  • Image Editing: Photoshop, Krita and Tiled. Wanna try Tilemancer, looks really cool.
  • 3D Modeling: Blender with Substance Painter for textures. I don't really want to do 3D stuff, but you never know.
  • Sounds: BFXR or my voice and Audacity filters.

The big hole is the music. I know about Bosca Ceoil, but I'm not really a composer and I don't want to waste too much time on making music. I think I saw a tool that generates loooong and eerie ambient sound, and if it does not exists, someone should create it :joy:

Guys and gals, if you have any suggestion about music generation, I'm all ears! :v:

I managed to deliver a game in time

Despite being a professional game developer, for the first time I managed to complete my game. That's kinda big for me, because the development of a game in a jam is really different to the one I do in my daily job.

Only two days to make a game was challenging for me not because the technical obstacle I had to overcome, I'm working on Unity since 5.3, but in a motivation point of view: I was exhausted sunday morning, and I wanted to throw everything and take a nap. Got convinced to power through bad thoughts, and at the end the result really paid off.

Watching people playing your game and giving feedback, praises and criticism is worth the struggle in the last two days. And this is why I will partecipate also to LD51, LD52 and the others to come. Thanks to you, people!

Hader.png

In just 25h of work, BLACKSUN is born. It's not really pretty: I'm a developer, not an artist, but it's mine, and I'm really proud of it.

Don't know yet if I will continue the project: the code is in a pretty bad shape due the time constraint, but I don't mind rewrite it from the ground up. The UI and the general touch needs a real artist touch.

In the meanwhile, you can try it in your browser here:

https://davideross.itch.io/blacksun

Thank again guys and gals, that's the first time for me interacting with the LD community and it's a pleasure. Keep up the good work! :v:

Technical Postmortem - BLACKSUN

Hey guys and gals, Davide here! :v:

I partecipated to LD50 with BLACKSUN, a resource management game based on the Aztec myth of the Fifth Sun and the subsequencial destruction of the Earth.

Cover-pm.png

The postmortem will be a little more on the technical side, mainly because I am a developer by myself and my art skills suck :robot:

I will talk about Unity, C# and shaders (just a little). There is also a little chapter on the release, matter I'm not really expert, but during the compo I got some knowledge worth sharing.

About any suggestion, critique or challenge to a duel to the death, please write them in the comment section. Happy reading you all! :v:

P.S.: you can find the complete source code at https://github.com/DavideRoss/BLACKSUN!

Singleton Pattern

The singleton pattern is a very diffuse software pattern that let you instantiate a specific class (MonoBehaviour in our case) once, like it is a global variable. This is often seen as anti-pattern (something to avoid because prone to problems later in the project), but I find it very useful in Unity.

In practical usage let you access a MonoBehaviour object almost as static, so you don't have to link the object around the scene. Usually I have a block of important objects I use frequently called managers, like in my case the GameManager, the ResourceManager and the AltarManager.

There are different ways to create a singleton in Unity, each one with its bonus and malus, personally I use this one:

```csharp using UnityEngine;

public class GameManager : MonoBehaviour { static GameManager instance; public static GameManager Instance { get { if (instance == null) _instance = FindObjectOfType(); return _instance; } }

// Public variables
public bool IsPlaying;

} ```

The script declare a static property of the GameManager object returning the non-static _instance variable. If _instance does not exists yet, then search for it. That means if also you put two GameObject in your scene, both with the GameManager component attached, GameManager.Instance will refer to only one of these two. Then, if I want to get the IsPlaying variable from anywhere in the project, I just have to write GameManager.Instance.IsPlaying.

The theory behind a generic singleton pattern is not really intuitive to get in the beginning, but trying the pattern on Unity really shows how it's used and why. Give it a try!

Defining the ticks per second

In the beginning there was nothing, then Unity created Start and Update. But Update has a problem! It runs every frame, not caring if the game is running at 5 or 500 FPS, and I cannot calculate the duration of a job based on Update!

(small trivia: a lot of games from 80s/90s cannot be played without a proper support because modern CPU are much faster. This problem is still present nowadays: a famous Doom 2016 speedrun strategy depends a lot by the FPS. And about the speedrun: do you know that speedrunners prefer running on NTSC SNES instead of a PAL one because has a higher refresh rate?)

Yes, I could have used FixedUpdate, running on a fixed physics engine timeframe, but it's not really meant for that and I wanted more granular control. So I went for writing a tick clock by myself!

The system is actually pretty easy, it consists of three components: the interface, the registration and the propagator (not real computer science name, I like to be a little dramatic).

The interface is barely a couple of lines: its job is define a method that a class must have when it's inherited. The benefits of this method is that I can inherit the interface on multiple objects, and still I can fit them all into a single List. This is the code for the interface:

csharp public interface IOnTickHandler { public abstract void OnTick(); }

Pretty simple, huh? The interface just defines the signature of the method that must be implemented later in the class. Every class can implement the method as needed, like this:

```csharp using UnityEngine;

public class JobView : MonoBehaviour, IOnTickHandler { private void Start() { GameManager.Instance.Register(this); }

public void OnTick()
{
    // Do stuff here
}

} ```

This script do three things: inheriting the interface, implementing the method and registering the object. But why the registration is needed? You can find the solution on the GameManager code:

```csharp using System.Collections.Generic; using UnityEngine;

public class GameManager : MonoBehaviour { // Singleton implementation, see above

public float TickPerSecond = 20f;

float _time;
long _ticks = 0;

List<IOnTickHandler> _jobs = new List<IOnTickHandler>();

private void Update()
{
    if (_playing)
    {
        _time += Time.deltaTime;
        if (_time > 1f / TickPerSecond)
        {
            _ticks++;
            _time -= 1f/ TickPerSecond;

            foreach (IOnTickHandler jv in _jobs.ToArray()) jv.OnTick();
        }
    }
}

} ```

The object with the interface inherited is added to a List<IOnTickHandler>, then in the Update function I sum Time.deltaTime (the time past from the last time Update is called) and check for a new tick. If the new tick has happened, cycle every object that inherit the interface and basically propagate the information that there is a new tick.

And that's conclude the whole lap. It's a little convoluted and probably overengineered for a game jam, but in this way I can control from the GameManager component the speed of the game during the game itself, and it could be extremely useful!

Difficulty ramp

I am not a game designer, and resource management games needs a lot of balancing, because there is the risk that a skilled player can manage to gather enough resources to keep playing the game indefinitely.

To solve this problem I've implemented an incrementing difficulty ramp. The variable is defined in the GameManager script:

```csharp using UnityEngine;

public class GameManager : MonoBehaviour { public float Difficulty = 1f;

private void Update()
{
    // ...

    if (_time > 1f / TickPerSecond)
    {
        // ...

        Difficulty += .0001f;

        // ...
    }
}

} ```

For each tick, increment the Difficulty variable a little. Then this variable is used in various places around the game, like in the AltarManager script to pick the amount of resources to demand:

```csharp using UnityEngine;

public class AltarManager : MonoBehaviour { public void SpawnHead() { // ...

    int count = Mathf.RoundToInt(Random.Range(1, 3) * GameManager.Instance.Difficulty * (Random.value < .5f ? 3 : 5));

    // ...
}

} ```

In this way the amount of resources is not only dependent from a random value, but it's also biased by the difficulty of the game. In the end some players managed to survive basically forever, but this method shoud have worked for most of the games.

The names of the gods

This is a last moment addition, only for giggles: on the tooltip for the god head you can found the god's name and his/her domain. This elements are generated randomly, you can find the code in the GodHead script:

```csharp using System.Collections.Generic; using UnityEngine;

public class GodHead : MonoBehaviour { public static List Names = new List() { "Macuilcozcacuauhtli", "Macuilcuetzpalin", "Macuilmalinalli", "Macuiltochtli", "Macuilxochitl", "Cuahuitlicac", "Patecatl", "Ixtlilton", "Ometochtli", "Tezcatzoncatl", "Tlilhua", "Toltecatl", "Tepoztecatl", "Texcatzonatl", "Colhuatzincatl", "Macuiltochtli", "Iztacuhca", "Tlatlauhca", "Cozauhca", "Yayauhca", "Cipactonal", "Huehuecoyotl", "Huehueteotl", "Mictlanpachecatl", "Cihuatecayotl", "Tlalocayotl", "Huitztlampaehecatl", "Quetzalcoatl", "Xiuhtecuhtli", "Mictlantecuhtli", "Acolmiztli", "Techlotl", "Nextepeua", "Iixpuzteque", "Tzontemoc", "Xolotl", "Cuaxolotl", "Tloque-Nahuaque", "Ometeotl", "Ometecuhtli", "Tonacatecuhtli", "Piltzintecuhtli", "Citlalatonac", "Tonatiuh", "Nanauatzin", "Tecciztecatl", "Tlahuizcalpantecuhtli", "Xolotl", "Xocotl", "Tezcatlipoca", "Quetzalcoatl", "Xipe-Totec", "Huitzilopochtli", "Painal", "Tlacahuepan", "Tepeyollotl", "Itzcaque", "Chalchiutotolin", "Ixquitecatl", "Itztlacoliuhqui", "Macuiltotec", "Itztli", "Amapan", "Uappatzin", "Itzpapalotltotec", "Miquiztlitecuhtli", "Tlaloc", "Tlaloque", "Chalchiuhtlatonal", "Atlaua", "Opochtli", "Teoyaomiqui", "Tlaltecayoa", "Cipactli", "Itztapaltotec", "Cinteotl", "Ppillimtec", "Omacatl", "Chicomexochtli", "Chiconahuiehecatl", "Coyotlinahual", "Xoaltecuhtli", "Xippilli", "Xochipilli" };

public static List<string> Domains = new List<string>() {
    "stars", "medicine", "fertility", "underworld", "ballgame", "sacrifice", "earth", "art", "excess", "pleasure", "gluttony", "music", "gambling",
    "healing", "peyote", "maize", "astrology", "old-age", "deception", "wisdom", "winds", "light", "fire"
};

public string Name;
public string Domain;

public void Initialize()
{
    Name = GodHead.Names.PickRandom();
    Domain = Random.value < .5f ? "Goddess of " : "God of ";
    Domain += GodHead.Domains.PickRandom();
}

} ```

It's not really remarkable, if not for the PickRandom() method: this method is not native of the List<string> object, instead is added by the developer using what's called an extension method. You can find them on the EnumerableExtension script:

```csharp using System; using System.Collections.Generic; using System.Linq;

public static class EnumerableExtension { public static T PickRandom(this IEnumerable source) { return source.PickRandom(1).Single(); }

public static IEnumerable<T> PickRandom<T>(this IEnumerable<T> source, int count)
{
    return source.Shuffle().Take(count);
}

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
{
    return source.OrderBy(x => Guid.NewGuid());
}

} ```

Those methods are using generics and LINQ queries, but the gist of it is that returns the first element of a shuffled list.

Pretty neat, huh? You can achieve the same result using a static method asking the list as parameter, but I'm a sucker for syntactic sugar, hence the expansion :stuckouttonguewinkingeye:

Clicking on the elements

I have doing UI stuff. I really despise it. And of course my games are heavily UI based, guess I hate myself a little too. Making the player interact with UI, but still keeping a GameObject is boring: you can create a canvas for each GameObject that needs UI elements, or you can set your UI in world space and move GameObject and UI element together, and both methods seems a little hacky.

I need that the player can click on a GameObject, but usually require casting a ray from the camera to the mouse position, but converted in world space and not in screen space. Then the method that shoots the ray should propagate the event to the correct object and make sure that the object handles it. A lot of work, isn't it?

Luckily, Unity ~~warlords~~ developers provide us a couple of useful interfaces: IPointerClickHandler, IPointerEnterHandler and IPointerExitHandler. An explanation about the interface is provided a little above.

This those three interfaces I can handle all mouse events without caring to shooting rays, setting up colliders and propagating things. Thank you Unity devs!

I used them mainly in GodHead and JobView scripts to handle the assignations and the tooltip. The methods provides also an object with a lot of useful informations, like the mouse position and the button clicked. This is the JobView script:

```csharp using UnityEngine; using UnityEngine.EventSystems;

public class JobView : MonoBehaviour, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler { public void OnPointerClick(PointerEventData e) { if (e.button == PointerEventData.InputButton.Left) { // Assign a villager to this job }

    if (e.button == PointerEventData.InputButton.Right)
    {
        // Remove a village from this job
    }
}

public void OnPointerEnter(PointerEventData eventData)
{
    Tooltip.Instance.ShowJob(Job);
}

public void OnPointerExit(PointerEventData eventData)
{
    Tooltip.Instance.Hide();
}

} ```

I found this method straightforward and easy to use. The only thing you have to care about is setting up a Collider2D component (otherwise the events won't trigger) and be careful to not overlapping them with other UI elements blocking the raycasting.

A little take on shading

I didn't used so much shaders for this project: the only one is a shader assigned to the god heads, changing the color of them while the time is running out. The shader itself is pretty basic, plus a couple of lines to make it work with the alpha.

The shader is pretty hacked up together, time was running out, the shader is called GodHead_Shader (here's only the interesting part):

```glsl sampler2D _MainTex;

float _Timer; float _Darken;

fixed4 frag (v2f i) : SVTarget { fixed4 col = tex2D(MainTex, i.uv) * i.color;

float4 alt = col * _Darken;
float blend = step(_Timer, i.uv.y);

clip(col.a - 0.5f);

return lerp(col, alt, blend);

} ```

In the fragment shader I use a step between the UV on the Y axis and an external property to change the color to a darker one. I can control the external property via script, like in the GodHead script:

```csharp using UnityEngine;

public class GodHead : MonoBehaviour { public SpriteRenderer Head; public float TotalTicks;

float _pastTicks = 0f;

public void OnTick()
{
    _pastTicks++;
    Head.material.SetFloat("_Timer", Mathf.Clamp01(1f - (_pastTicks / TotalTicks)));
}

} ```

The clip function on the shader basically skip rendering the pixels when its argument is below zero. Writing the fragment shader this way make a cutout shader, where a pixel can be fully opaque or fully transparent, with to actual transparency.

Building and delivering

That's the part I was not really so expert. And to be honest I'm still not really that expert. I wanted to build the game for Windows and WebGL, so first thing I did is installing the "WebGL Build Support" module through Unity Hub. It took a dozen of minutes, pretty easy.

Second step was changing the Project Settings, specifically the Player section. For the Windows build I just changed a couple of settings, mostly the Fullscreen mode and the Default Screen Width/Height.

ps_2.png

Third step: open Build Settings and add all required scenes to the Scenes in Build box, roughly ordered by the order of loading. I left all the other settings as they are and press Build: after a dozen of seconds it was done, zip the folder and upload it to my Drive. Done!

To build for WebGL the first thing you have to do is to switch platform from Build Settings: grab a snack, it will take a while. With WebGL had a little more problems: the first build I did has the resolution too high and for some users went out of screen, not good. So I limited the resolution and make the UI Canvas adapt the size for good measure.

ps_3.png

Then I had a couple of problems with Itch.io: with the default settings the browser cannot load the game, complaining about decompression issues. I solved disabling the compression from the Publishing Settings: the build is a little more heavier, but still manageable by any modern device.

ps_4.png

Done! Finally I can rest my old and worn body!

Outro

Whoa! That took a good time to write. If you are still reading, thank you very much! I hope that this postmortem can help you in the future. If you want to go deeper down the rabbit hole of game programming you can check the code from the other Compo participants: understading other people code is an awesome tool to learn!

Keep up the good work people, share as much you can without fear or doubt, we are not here to judge, but to help. Davide out!

cover_heads.png