A Cruel Angel Thesis

a cruel angel

It is a 2D top-down video game with RPG elements that collects user information regarding depression symptoms for the generation of reports to assist experts in the field of psychology. The idea was to use projection techniques to recollect user data about depression symptoms.

It was the very first video game that I made. I worked as a Designer, Programmer and Artist for this one.

In the video game, the player embodies a young person in a snowy world trying to reach a town. Along the way, they must help or eliminate certain characters who will obstruct their progress; interactions with these characters will take place through dialogues and/or turn-based combat in the style of games such as Pokémon and Final Fantasy.

You can check out the game here!
DISCLAIMER: If you know Spanish I strongly recommend to try the game in that language!

Gameplay

It is composed of the following sections: the main view, the user interface, and the combat view.

In the main view, the player character, the game world, NPCs, and objects can be observed. The user will be able to interact with each of these, obtaining items, quests, and information for their adventure. Within this view, if the player engages in conversation with an NPC, a dialogue box will appear containing everything that character has to say.

To view items and quests, you can use the inventory, Within it, the information for each item can be viewed, along with options to consume them and obtain their benefits, or to discard them to free up space, since the number of items that can be carried is limited.

And last but not least, the combat, this is where things get interesting. It contains an image of the player and the enemy with their respective health bars and 3 buttons: Act, Attack, and Flee. Pressing Act leads to a menu containing all the responses to comments made by the enemy throughout the battle. Attack contains all the combat options for harming the enemy, which are related to the enemy itself — for example: if the character is a dog, one ability could be “take the ball away,” but if it is a student, it could be “ruin homework.” The Flee option allows the player to exit the battle and return to the main view; however, this will only be available once the user has completed at least one battle with that character.

Combat

Giphy

Remember when I mentioned the physiology? Well… this is where the magic happens!

I created something called Symptomatic Dialogue.

Symptomatic Dialogue

Is a set of selectable phrases whose function is to allow interaction between the player and the characters, encouraging the projection of feelings associated with the symptoms on which said phrases are based. Considerations taken into account for the creation of Dialogues:

  • Each battle or encounter has a different symptomatic dialogue.
  • A single character has different dialogues.
  • Each character has a backstory in order to encourage interaction and maintain gameplay.

The Dialogues where modeled using a tool for the creation of interactive, nonlinear stories Twine

dialogue

And then with the magic of Unity’s ScriptableObjects and Software Engineering those Dialogues where implemented!

ActOption.cs

[CreateAssetMenu(fileName = "New Act", menuName = "Act Option")]
public class ActOption : ScriptableObject
{
    [SerializeField] private new string name;
    [SerializeField] private List nextActOptions;
    [SerializeField] private Dialogue response;
    
    [SerializeField] private int depressionPoints;
    [SerializeField] private Symptom associatedSymptom;

    #region Properties
    
    public string Name
    {
        get => name;
        set => name = value;
    }
    
    public List NextActOptions
    {
        get => nextActOptions;
        set => nextActOptions = value;
    }

    public Dialogue Response
    {
        get => response;
        set => response = value;
    }

    public int DepressionPoints
    {
        get => depressionPoints;
        set => depressionPoints = value;
    }

    public Symptom AssociatedSymptom
    {
        get => associatedSymptom;
        set => associatedSymptom = value;
    }

    #endregion
}
CombatDialogueManager.cs

	public void StartDialogue(Dialogue dialogue, TMP_FontAsset fontAsset)
	{
		DialogueIsActive = true;
		_sentences.Clear();
		foreach (var sentence in dialogue.Sentences)
		{
			_sentences.Enqueue(sentence);
		}
		DisplayNextSentence(fontAsset);
	}

	public void DisplayNextSentence(TMP_FontAsset fontAsset)
	{
		if (_sentences.Count == 0)
		{
			EndDialogue();
			return;
		}

		if (fontAsset)
		{
			dialogText.font = fontAsset;
			dialogText.color = new Color32(255, 255, 255, 255);
		}
		else
		{
			dialogText.color = new Color32(51, 204, 255, 255);
			dialogText.font = combatFont;
		}
		dialogText.text = "";
		var sentence = _sentences.Dequeue();
		StartCoroutine(WriteSentence(sentence));
	}

	public void EndDialogue()
	{
		DialogueIsActive = false;
	}

So as you can see the combat looks more like this

Giphy

Ups! Wrong image… But you get the idea.

combat

Scoring Mechanic

The phrases were classified by an expert (client) according to a determined score. Said score will be based on the frequency of selection of the phrases and determines a value which implies a greater epidemiological probability of depressive symptomatology. Each of the scores refers to the level of projection that the player has when selecting said symptomatic dialogue, with a lower number indicating lower projection. The numerical value assigned to the symptomatic dialogues is not sequential, but rather a value assigned by a subject-matter expert taking into account the severity of each response.

Giphy

Quest System

As I mention before, the main part of the game where the combat, but inside the non-combat part of the game there’s also interesting dialogues and quests!

Some NPCs will ask you to do some favors for them, some are mandatory and some are optional.

dialogue
quest

The quests where implemented like this:

QuestSystem.cs

private void CheckQuest(Quest quest)
    {
        if (quest.Completed)
        {
            GetCurrentToDo();
        }
    }

    private void GetCurrentToDo()
    {
        if (GameManager.Instance.Player.Backpack.Quests.Count <= 0) return;
        foreach (var quest in GameManager.Instance.Player.Backpack.Quests)
        {
            if (quest.Completed) continue;
            CurrentQuest = quest;
            break;
        }
    }
Quest.cs

	private void CheckGoal(Goal goal)
    {
        if (!Completed)
        {
            if (goals.Exists(x => x.Id == goal.Id))
            {
                if (goals.All(g => g.Completed))
                {
                    Completed = true;
                }

                if (Completed)
                {
                    EventManager.OnQuestCompleted?.Invoke(this);
                    GameManager.Instance.Player.Backpack.Quests.Remove(this);
                }
                GameManager.Instance.SaveData();
            }
        }
    }

    public void ResetQuest()
    {
        Completed = false;
    }
Goal.cs

public abstract class Goal: ScriptableObject
{
    public abstract int Id { get; }
    public abstract string Description { get; }
    public abstract bool Completed { get; set; }
    public abstract bool IsGoalActive { get; set; }
    public abstract Reward Reward { get; }
    public abstract void InitializeGoal();
    public abstract void CompletedGoal();
    public abstract void ResetGoal();
}

As you can see, the Goals are an abstract class, because with the OOP inherit magic we can create different types of goals like:

  • Talk to NPCs.
  • Give Items to other characters.
  • And so on!

Results

After the patient completes the game, their corresponding doctor can visualize the symptomps using Microsoft PowerBI.

report
Have Project in Mind?

Let’s turn your dreams
into reality

Scroll to Top