A little background...

You know, these days, Every time i want to implement new functionality from my To Do list. I decided to not immediately jump into my code editor.

I've learnt from my past mistake, when i tried to implement one small thing where i thought it would make my game a little bit more polished. But i can't figure out how to implement it. How i did it was through a series of trial and error.

I should've only worked on that specific code related to text animation. But at the same time, ideas form in my mind and i quickly try to make them exist. The result is messy code and a lot of technical debt. I ended up messing with a huge part of my code because i was modifying lot of things at the same time just to see if my idea would work.

For context, It was about adding a small pause to the text animation whenever my character use a certain punctuation like comma or period. In my prototype visual novel game:

text animation showcase from my visual novel prototype

This time i tried something different. So i was trying to implement new functionality, right. Just like usual. But now before i touched my code, i wrote a note to try and conceptualize my implementation before turning it into a code.

Like this:

(Don't worry if u can't comprehend some part, it might be my fault. Because i wrote for myself without adding much clarity. You can skim through)

LOG.md

GOAL:
Display ending scene (can be a dark screen with text showing ending title)

Detail:
There will be 2 ending scene. First one is good ending and the second one is the bad ending. The former is called "We are still friends" and the latter is called "Are we still friends?". The good ending is obtained if Andre (main character) at least said yes once to his friend after getting invited. Opposingly, the bad ending will show up if Andre refused all invitations from his friend.

Implementation detail:
It is possible to track how many times player agreed to the invitations. For example, if the decision to accept is at button id number 1, we append 1 to an array when the player presses it. That way, we keep track of what buttons the player have pressed.

Say for example the first time player is making a decision, the accept button is button id number 1 (the topmost button), and the second time player is making the decision, the accept button is button id number 2 (the second button from the top). Then it is harder to differentiate the meaning of each button the player pressed, when inside the code. Say we have an array with value: [1, 2, 2, 1], we know that in the first decision the player pressed the button 1 but we don't know what is button 1 unless we go to the data structure to see it. Honestly i don't even know if this is a problem or not. I'd say it's not harmful for now.

Only UI object can know which button the user presses, but it's not acceptable to put logic code inside UI object (which only responsible for updating UI, obviously). So the UI must emit signal to send the information to another object that implement the logic. But who is that?

I think to answer that question we first need to know what's the logic doing. The code first check the array, using Array.count() method, it'll return how many times a value is within the array, for example [3, 3, 3].count(3) will return 3 because there are three 3s inside that array (bad example i know).

But first we need to know, what buttons is for acceptation. We somehow have to know when we're inside the code. If there's 3 decisions to make then we got to know what each button implies for every decision the player make. In the first decision the first button might say yes but in the second decision the first button might say no. How do we handle that??

Potential solution:
We can ask the data, send an inquiry, ask it: At the first decision, what the first button imply? what the second button imply?

but that doesn't work i think. Because the code doesn't understand a word. Hold, let's put that aside.

I think I've arrived at the core problem, i need to ask and answer this question first. Does the logic need to be done in the data structure (the CSV file). Or inside the code? When we need to decide what ending we get, is it decided by the data or by the code? I don't think the former is possible. It is only possible to determine that in the code. So i think it's plausible. I just need to make one main script that dictates how the game run. For example, like main.cpp in raylib or like script.js in zonelets. And it must be easy to implement logic there.

I'm thinking to make two scripts called input script and logic script.

Let's see what the logic script does.

It receives signal from UI every time the player pressed a decision button.

then it receives button index and store it inside an array.

To determine the ending. We simply check the array. If array.count(2) is equal to 3 (the player chose the second button three times), that means the player has rejected every invitations, bad ending is obtained. Else then give the player the good ending.

YOO PROBLEM SOLVED ✅✅✅?

I think i just need to imagine what code is inside the logic.gd. For now, that script file only consisted of a single method connected to a signal (button pressed signal). It must be pretty overkill to make an object that only does that. But at the same time, i feel like that's a different responsibility from input handling. Wait, honestly that might be the job for Dialogue Manager Object, perfect.

But i got another problem. Currently, it is my game object (which is the root object) that handle input. The game object holds a lot of reference to other objects so that it can start a chain of behavior whenever the player give input. I'm thinking to delete game object and instead give that responsibility to input handler object. But that gives us the problem, should an input handler object holds references to many other objects (UI, Dialogue Manager, Camera, Etc)?

To be honest, i don't really think it is a problem. It's just that, the input handler should be clear and readable. Because the order of operation is important. I can't think of any harm from doing it. So i guess I'm doing it.

I got another problem. Once dialogue manager know what ending to get, how to store that value?

Okay never mind that, i solved it. Just make constants:


      const ENDING_1 = 0
      const ENDING_2 = 1

      #and then

      func _on_ui_choice_chosen(index : int, jump_to: int) -> void:
        #keep a log of which buttons the player chose
        player_choice.append(index)
        
        #the problem is checking this every time where it can be unnecessary.
        if player_choice.count(2) == 3:
          ending = ENDING_2
        else:
          ending = ENDING_1

      

I just need to tackle another problem: displaying ending scene.

It can be done multiple way, one is by making a Godot scene for each ending that exist.

But i don't think that's efficient

But I'll answer that tomorrow. imma sleep now

In the end

After evaluating the result. I think the process is pretty slow, might be even slower than the usual way i implement stuff. But less stress, less error message, and more vibe. Honestly the problem I'm dealing with isn't solved yet. But i got to post something.

So how do you think?

Do you have another approach to plan out before you start coding? If so, please let me know!