top of page
image (100)_edited.jpg

TALKIE TOWN

Talkie Town is a turn-based city building game where players compete to develop the best city. Our client for this project was Embeteco, a german company that wanted to give their stakeholders an insight into developing a smart city. My biggest contribution to this project was being the main programmer, but I also helped out with 3D modeling, user research & testing, and giving my input on design decisions.

PROJECT DETAILS

Platform: PC

Tools used: Unity, Blender

Client: Embeteco

Team size: 4

Project started: 13-02-2023

Project finished: 13-06-2023

Main roles: Programmer, game designer

Talkie Town was made as a semester-long school project, together with 3 other students. Our client for this project was Embeteco, who asked us to develop an applied game that demonstrates the complexity of developing a smart city to their stakeholders. The process of developing smart cities often becomes a game of politics, and as such we decided to reflect this in the gameplay.

In our game, players take turns to each build their own city which then get scored based on their welbeing, economy and impact on the environment. These scores then get combined, and the player who has the highest combined score wins the game after a certain amount of rounds. What makes this game more interesting however is that resources such as money and manpower which are needed for construction, are shared across all players. Combine this with unexpected events such as changing economies and natural disasters, and all sorts of dilemma's start arising.

During the project I've fulfilled different roles from game design and 3D modeling to concepting research and user testing, but by far my largest contribution to the project has been the programming. I implemented all mechanics necessary for constructing buildings, using resources, tracking scores and many other things. As such, it was very important that my code solutions were clean and scaleable. Below one of the core scripts of the game can be seen, which handles the placement of buildings:

public class PromptManager : MonoBehaviour
{
    public List<GameObject> prompts = new List<GameObject>();

    public int selectedPrompt;
    public bool demolishMode;

    [SerializeField] private int demolishMoney;
    [SerializeField] private int demolishManpower;

    public List<int> promptChoice = new List<int>();

    [SerializeField] private GameObject promptUI;

    [SerializeField] private List<Text> promptChoiceTextName = new List<Text>();
    [SerializeField] private List<Text> promptChoiceTextMoney = new List<Text>();
    [SerializeField] private List<Text> promptChoiceTextManpower = new List<Text>();
    [SerializeField] private List<Text> promptChoiceTextRounds = new List<Text>();

    private GameManager gameManager;
    private RandomEvents randomEvents;


    async void GetAnalytics()
    {
        try
        {
            await UnityServices.InitializeAsync();
            List<string> consentIdentifiers = await AnalyticsService.Instance.CheckForRequiredConsents();
        }
        catch (ConsentCheckException e)
        {
            // Something went wrong when checking the GeoIP, check the e.Reason and handle appropriately.
        }
    }


    private void Start()
    {
        GetAnalytics();
        gameManager = FindObjectOfType<GameManager>();
        randomEvents = FindObjectOfType<RandomEvents>();
    }

    private void Update()
    {
        // If any options are the same, reroll

        if (promptChoice[0] != 0)
        {
            if (promptChoice[0] == promptChoice[1] || promptChoice[1] == promptChoice[2] || promptChoice[2] == promptChoice[0]
            || promptChoice[0] == promptChoice[1] && promptChoice[0] == promptChoice[2])
            {
                RandomizePrompts();
            }
        }
    }

    public void RandomizePrompts()
    {
        promptUI.SetActive(true);

        // Select random prompt from list and update UI for all 3 options

        for (int x = 0; x <= promptChoice.Count; x++)
        {
            for (int i = Random.Range(1, prompts.Count); i <= prompts.Count; i++)
            {
                Prompt prompt = prompts[i].GetComponent<Prompt>();
                string promptName = prompt.promptName;
                string neededMoney = prompt.neededMoney.ToString();
                string neededManpower = prompt.neededManpower.ToString();
                string neededRounds = prompt.neededRounds.ToString();
                promptChoice[x] = i;
                promptChoiceTextName[x].text = promptName;
                promptChoiceTextMoney[x].text = neededMoney;
                promptChoiceTextManpower[x].text = neededManpower;
                promptChoiceTextRounds[x].text = neededRounds;
                break;
            }
        }
    }

    public void ChoosePrompt(int promptIndex)
    {
        selectedPrompt = promptChoice[promptIndex];
        promptUI.SetActive(false);
    }

    public void ChooseDemolish()
    {
        demolishMode = true;
        promptUI.SetActive(false);
    }
    public void ChooseSkip()
    {
        promptUI.SetActive(false);
        if (randomEvents.counterClockedTurns)
            gameManager.DecreaseTurn();
        else
            gameManager.IncreaseTurn();
    }

    public void ChangePromptNumber()
    {
        // Toggle between the prompts in the list

        if (selectedPrompt < prompts.Count - 1)
        {
            selectedPrompt += 1;
        }
        else
        {
            selectedPrompt = 0;
        }
    }

    public void PlacePrompt(Transform location)
    {
        // Place down the prompt selected from the list on the tile that called the function

        if (!promptUI.activeInHierarchy)
        {
            Dictionary<string, object> parameters = new Dictionary<string, object>()
            {
                { "placedPrompts", + 1 },
            };
            AnalyticsService.Instance.CustomData("countPlacedPrompts", parameters);

            GameObject prompt = Instantiate(prompts[selectedPrompt], location.position, Quaternion.identity);
            prompt.transform.parent = location;

            location.GetComponent<Tile>().prompt = prompt;
            location.GetComponent<Tile>().hasPrompt = true;

            selectedPrompt = 0;
            demolishMode = false;

            if (randomEvents.counterClockedTurns)
                gameManager.DecreaseTurn();
            else
                gameManager.IncreaseTurn();
        }
    }

    public void DemolishPrompt(GameObject prompt)
    {
        // Demolish the prompt selected by the tile that called the function

        if (!promptUI.activeInHierarchy)
        {
            if (!demolishMode || gameManager.money >= demolishMoney && gameManager.manpower >= demolishManpower)
            {
                if (demolishMode)
                {
                    gameManager.money = gameManager.money -= demolishMoney;
                    gameManager.manpower = gameManager.manpower -= demolishManpower;
                }
                Dictionary<string, object> parameters = new Dictionary<string, object>()
                {
                    { "demolishedPrompts", + 1 },
                };
                AnalyticsService.Instance.CustomData("countDemolishedPrompts", parameters);
                
                prompt.GetComponent<Prompt>().DestroyPrompt();

                selectedPrompt = 0;
                demolishMode = false;

                if (randomEvents.counterClockedTurns)
                    gameManager.DecreaseTurn();
                else
                    gameManager.IncreaseTurn();
            }
        }
    }
}

 

bottom of page