Wednesday, February 28, 2024

Stacker for Vita

Alright, this entry comes after the release of the game, again. So, why bother?
Easy, it adds flavour and meaning to some design decissions, and it helps to understand and improve or reuse the code and/or the methods found. In addition, you cam see here a few of the problems during the developement, and how they were overcome (when/if they did).

First of all, a bit of history:

The idea of making this homebrew comes from 2 or so years ago, more or less before the hiatus. I was thinking about some options that weren't too difficult, so I can practice a bit. Then I remember playing this game https://en.wikipedia.org/wiki/Stacker_(arcade_game) , however, at that time, I didn't remember the name and I had some of the core mechanics foggy. I put it in the wardrobe, and just after the D&D sheet, I saw out of the blue a youtube recomendation of someone playing exactly this, and it came the domino effect.

So, I was able to review what I have and the parts I was lacking. At first, I was going to make it like another 2D platformer game (your usual 2d platformer controls, with gravity and stuff). Luckily, talking with a friend of mine, he asked me about the design ideas referencing the snake game among other options, which lead me to the easier and logical (proper) way to do this: An array with pairs to contain the position of the image and the type of block (empty or full). [Thanks for that, you know who you are]

The idea is as you see below:

The array is a list of the elements stacked.
1: full block
0: empty block
(I knew I was going to need the id of each instance for later use with the images, but at first I just filled the array with one element per position. I simply printed the array on screen for the testing purposes.)

If you have any background on computer science, you might have guessed what comes next, scroll through elements as if you were to store a matrix. Count the elements, every X number is a row, each Position is a column. With that, you have the full stacker idea ready to be implemented.

Since I didn't write any of this process down properly (too many times doing this kind of matrix arrangements prior), I will print_debug one or two iteration of the game's code and explain it:

```
Number of columns: 7 | Number of blocks: 3
Array: [[1, 1578], [1, 1581], [1, 1584], [0, 1587], [0, 1589], [0, 1591], [0, 1593]]
```


As you can see, there is a list of 7 elements. This composes a line or row, with each pair of elements being "a column".  (take each pair as a block: full/empty and its Identification number)

After the idea of using an array, and the obvious variables, comes the code for the new row function:


```
    for i in (cols):
        if numNewBlocks > 0: # Add an Draw blocks to the row
            numNewBlocks = numNewBlocks - 1 # Update the num of blocks left to add
            # Draw block on screen, according to raw an column
            var newOcupy = ocupiedSquares.instance()
            add_child(newOcupy)
            newOcupy.position = Vector2((900-bCoordinates.x) - (line * bCoordinates.x), i * bCoordinates.y + 48)
            newOcupy.set_visible(true)
            gameWindow.push_back([1,newOcupy.get_instance_id()])
        else: # fill the rest of the row with empty spaces
```




You can see, it's just a loop appending one element each time. To make it efficient, It starts adding the full blocks left, leaving the remaining blocks empty until a row is completed, instead of juggling with numbers.

As soon as we have the new row, the next step is making the row blocks shift.

```
Array before the shift: [[1, 1535], [1, 1538], [1, 1541], [0, 1544], [0, 1546], [0, 1548], [0, 1550]]

Array after the shift: [[0, 1550], [1, 1535], [1, 1538], [1, 1541], [0, 1544], [0, 1546], [0, 1548]]
```



This time, the cols are shift/moved one position to the right, if it's the last one of the row, it goes back to the beginning of the row. I decided to go with circular shifting because it's easier to deal with and godot's methods to work with arrays felt more like a stack than an array, which meant, using pure iterators and side changing directions could make the complexity skyrocket. (if you want to try that, you need to track the head of the full block string/snake and the size, number of blocks, of the snake/string. then you use those to see where is shifting to).


```
func shiftRow(row):
    for i in refreshTime: pass # This is a hacky way to control the refreshing times, so it can be played by a human
    var rowStart = row * cols
    var elem1 = gameWindow.pop_at(rowStart) # current elem in check
    gameWindow.insert(rowStart, elem1)
    var elem2 = 0 # To avoid error (wrong element checked) with insertions
    for i in (cols):
        # Uptdate the array
        if (rowStart + i) < (rowStart + cols -1): # If we haven't reached the end of the row
            elem2 = gameWindow.pop_at(rowStart + i + 1) # after the first pop the same "i" is the next elem
            instance_from_id(elem1[1]).position = Vector2((900-bCoordinates.x) - (line * bCoordinates.x), (i + 1) * bCoordinates.y + 48)
            gameWindow.insert(rowStart + i + 1, elem1)
            elem1 = elem2
        else: # if this was the last element of the row
            elem2 = gameWindow.pop_at(rowStart) # first element of the row is the next elem
            instance_from_id(elem1[1]).position = Vector2((900-bCoordinates.x) - (line * bCoordinates.x), 0 * bCoordinates.y + 48)
            gameWindow.insert(rowStart, elem1)
            elem1 = elem2
```



So far it looks easy right? That's because it' already done haha. It's not rare to do silly mistakes like put one element
"front" when should be "back" and viceversa. Same for making comparisons with the id instead of the 1/0 for full/empty block. That's why debugging helps a lot, it makes you find and fix those mistakes.

Once we have the row filling and shifting, we can start with the big league, the stacking code. To make things easier to test and develope, we start making this synchronous and secuencial to the main process. This means, that any part of the mechanics done prior would be inside and at the end of this code snippet, so you can test the secuence step by step, instead of all at once.

Below it's an example of the results of making the stack row function once. The first array is composed by the first two original rows, the second is how the blocks changed according to the location they were then the button was pressed.

```
Array after the 1st stack: [[1, 1605], [0, 1608], [0, 1610], [0, 1612], [0, 1614], [1, 1599], [1, 1602]]

   pressToStack()
Array after the 2nd stack: [[1, 1605], [0, 1608], [0, 1610], [0, 1612], [0, 1614], [1, 1599], [1, 1602], [0, 1654], [0, 1656], [0, 1658], [0, 1660], [0, 1645], [1, 1648], [1, 1651]]

   pressToStack()
Array after the 3rd stack:[[1, 1605], [0, 1608], [0, 1610], [0, 1612], [0, 1614], [1, 1599], [1, 1602], [0, 1654], [0, 1656], [0, 1658], [0, 1660], [0, 1645], [1, 1648], [1, 1651], [0, 1690], [0, 1693], [0, 1696], [0, 1698], [0, 1700], [0, 1702], [0, 1704]]

```


See how those who fell are now 0s, and those stacked are still 1s? (the number of remaining full blocks has reduced accordingly too)


Let's see the code snippet now. However, since I am using the final version, you'll see only the finalized function code. In any case, this is how you decide what stacks or falls. (The part about new instances and drawing would have come after the comparisons are properly working to avoid confusion).


```
    if line != 0: # The first line always stacks
        # Compare previous and current row to see what blocks that stack and update accordingly
        var lineStart = line * cols
        var prevLineStart = (line - 1) * cols
        for i in (cols): # Compare the elements of both rows one by one
            var elem1 = gameWindow.pop_at(prevLineStart + i) # grab and save the elem to compare
            gameWindow.insert(prevLineStart + i, elem1) # but don't modify the array
            var elem2 = gameWindow.pop_at(lineStart + i) # grab and save the elem to compare
            # COMPARE FIRST ELEMENT OF THE PAIR, THE 2 ONE ARE ALWAYS DIFFERENT IMAGE INSTANCES
            if elem1[0] == elem2[0]: # elem was either empty or stack, so reinsert in same place
                gameWindow.insert(lineStart + i, elem2)
            if elem1[0] != elem2[0]: # always empty if they are different
                if elem2[0] == 1: # If it was a block falling,
                    soundOFF()
                    if !$Sounds/BGM.is_playing():
                        $Sounds/BGM.stream = falling
                        $Sounds/BGM.play()
                    blocks = blocks - 1 # update the counter
                    elem2[0] = 0
                    instance_from_id(elem2[1]).get_node("Image").set_visible(false)
                    instance_from_id(elem2[1]).get_node("Image2").set_visible(true)
                # Insert the empty block in the row
                gameWindow.insert(lineStart + i, elem2)
```



After that, as you see, you use the current line, the screen size, and the blocks size to calculate the coordinates to draw the selected block for each iteration of the loop. Then you use the 0 or 1 to decide which type of node (ocupied, empty), and which image of them display (full, falls, empty)


When I finished that part, It was time for betatesting. Besides, I was lucky and I had a meeting with a few friends, who were kind and eager to try the game (betatesters, yay!). Me and them played the game and came to conclusion that it was unclear what each block was, hence why the 3 blocks had to be named in a screen prior to the game.



Here, the code for the game's algorithym was done. However the program can have a bit more. We can put some of the variables as global, so they can be autoloaded and accessed through the settings menu. This lets the player or dev create an editor for the game, which you can use to select how many columns and blocks you want, and/or how much speed you want them to move.


```
extends Node


# Global variables, to make them editable via settings
var cols = 7
var blocks = 3 # number of currently moving blocks
# Time for the shift refresh (hacky method I had to come up with), I know it eats resources
var refreshTime = 900000 # use refreshTime = 300000 for the vita
```



Each var will be updated with 2 buttons, one for up and another for down. Here's the cols example:


```
func _on_ColsUP_pressed():
    if cols < 7:
        cols += 1
        get_node("/root/Autoload").cols = cols
        get_node("RectangleCols/Cols").text = "COLUMNS\n" + str(cols)


func _on_ColsDOWN_pressed():
    if cols > 2:
        cols -= 1
        get_node("/root/Autoload").cols = cols
        get_node("RectangleCols/Cols").text = "COLUMNS\n" + str(cols)
# Fix block limits after cols edits, for limit cases
    if blocks >= cols:
        blocks = cols -1
        get_node("/root/Autoload").blocks = blocks
        get_node("RectangleBlocks/Blocks").text = "FULL BLOCKS\n" + str(blocks)
```



And that summarized the project of the stacker. You can go to the github to read and try the full projects code, and also play the released game.


Gihub's link to the full project (and releases): https://github.com/Bunkai9448/StackerVitaGodot

Tuesday, February 27, 2024

web browser

I've released the other games in itch.io to be playable in as many platforms as possible. This also gives people an easy way to test the game before downloading it. So, the stacker wasn't going to be different. This entry is about that step.

Why?
Because making an EXE means only Windows user can test it. However, making it html/browser playable lets any person with a computer or with a phone play it.

What is different? And what relation has with the blog?
The HTML zip is not runnable within browsers without extra programs. This helps to avoid people expecting to do so out of a lack of knowledge. The relation with the blog is like I explained before, for people to try before installing (besides exporting it for other system, deletes the preset of the
vita for said project, and you have to add it again. So, another heads up from this blog to you)

With that out of the way, let's start with the process. There are a few ways to do it:
* The official documentation is this https://docs.godotengine.org/en/3.5/tutorials/export/exporting_for_web.html
But after googling a bit, you can find three easier methods:

- Through Godot's web editor https://editor.godotengine.org/releases/latest/

- Through a program working as web server, example with PHP here: https://www.youtube.com/watch?v=foXI2uJMEhQ

- Through itch.io (it requires you to make an account, but as I said before, I happen to have one from the previous ones). I'm going to use this as an aid: https://www.youtube.com/watch?v=6DVJIlYr7QE

> I am going to put here a few pictures, and bullet points, about using godot to make the game playable throught itch.io website. Take this as a way to get visibility for the game if you need a greedy reason.

First, we need to export the game, obviously:

Be sure to go to "resources", and select "Export all resources in the project"


Be sure to go to "Script", and select "Compiled Bytecode (Faster Loading)".


Be sure to press the "Export all" button when you're ready, you don't want the folder missing important files of your game.


Now that you have a folder with your files, it should look like this:


Be sure to name your main HTML as "index.html" or it won't run.

After that, zip the whole folder, and go to itch.io for the upload (don't forget to do it with the "playable in browser" option).


Don't forget to update your project's "viewport dimensions" (with the vita's resolution, in our case).

Let the orientation as "default" (In our case being 'rotated' from source it could mess up with some automatic rotation in phones and tablets).

I've also selected "full screen" "scroll bars" and "mobile friendly" to avoid people from being able to play in some screens sizes.


The next step should be released it, but you'll find the "Public" option grayed out. Don't worry, you must save it first as
a draft. You can test it works, and/or directly go back and select public and save after that.


Boom! It's done! https://bunkai.itch.io/stacker-for-vita-browser

Next entry is about this stacker game, and how it was done, with code and everything. Stay tuned!

Thursday, February 22, 2024

Visual Novel with renpy

Another engine, again...

I wanted to test out a Visual Novel Demo. Which means: "Different goals, different methods".

Let me assure you, I am not leaving behind the samples with SDL from the beginning of this blog, I am also not going to stop using Godot for many of my projects (at least for now). This is "only" another extra tool for my bag.

Question: Why now?
Answer: Now, because Ren'Py, like Godot, is in active development. In future iterations compatibility might break, with this Demo I can write down the version that works for the vita before it's too late (you don't want to keep trying versions in the future to find one that can export without crashing).
If a new one works, go ahead and use it, if they don't, you have this one as a back-up.

Question: Why Ren'Py?
Answer: Because Ren'Py is open source and free for commercial use. This engine is also one of the most widely known and used for Visual Novels. It works nicely for PS Vita (loading times aside), and It's easy to use.


With that explained, it's time to get our hands dirty. I decided to call this Demo "Conociendo Hokkaido" to make a somewhat nice presentation of the place in the future and, at the same time, present the Ren'Py
basics too. This time (entry) however, will be mostly about how to set everything up, and make a sample VPK build for the vita. [At the end of the entry, you will find a link to a GitHub repo with this project]

To be fair, most of the engine is pretty straightforward or is explained in their quick start guide https://www.renpy.org/doc/html/quickstart.html (in addition to the whole documentation). However, a few adjustments are necessary to make them work with the PS Vita. Besides, some features (like input) may crash the PS Vita.

The first we need is the engine and the means to export for the vita, to do that, I've used:
Ren'Py Version used: Ren'Py 7.3.5.606 ( https://www.renpy.org/release/7.3.5 )
Ren'Py PSVita Distribution Tool: (crash report says) 7.4.9 Ou ( https://github.com/SonicMastr/renpy-vita )

With that out of hands, let's boot up Ren'Py and create our project:

Since we are making the project to play in the vita, we'll use the console resolution (960, 544). Other than that, just create your project normally:

> 'Create New Project' > Project Name > 'Custom. The GUI is optimized for a 16:9 aspect ratio.'
> WIDTH: 960 > HEIGHT: 544 > Select Accent and Background Colors.

You can see an example in the image below:


When it finishes, it creates a new folder with all the default files. We can now edit them to make our Visual Novel.


We will need to have PS Vita livearea files eventually, I put them here too so they can be found easily.


Besides, I added a few files for my Demo to make it more personal (If we were making a full project, this is how you add them too). [You can omit this step if you are just setting up the engine]

Conociendo Hokkaido > Game > images
Conociendo Hokkaido > Game > audio
Conociendo Hokkaido > Game > gui

Something like the following image:


Back to Ren'Py, if you have received an already created project, and it doesn't show on your project list, you can press on refresh to make them appear.


The basic GUI of the engine displays the following:

> Edit file (it has the code for your game):
    It is useful to say that you can open all rpy files with any text editor of your likeness.
    [This may be worth it to check (or ask) things without opening the whole Ren'Py launcher]


    # options.rpy contains options that can be changed to customize your game.

    # script.rpy contains the actual script for your game

    # gui.rpy contains the GUI Configuration

    # screens.rpy contains the configurations for the screens used to display dialogue to the player.


> Actions (it has some autoconfigurations to check your game's files to look for potential problems)

> Build distributions (is what you expect)
    * The vita export doesn't show here because the tools for it are unofficial.
    

To summarize, in this demo: I've added music, a scene with two minibranches, and one common ending.

* I've also tried to use the input method with the vita keyboard:

```
    $ pName = renpy.input("Write your name and press enter to start the game.", length=10) or "Bunkai"
```

At first, it saves the input (or the lack of it). After that, it glitches out and prompts the keyboard again (this second time the input is not used). As a result, the dialogue for the input prompt and the dialogue right after your first input will be hidden by the keyboard screen.
[None of this happens in the PC version. That resulted in me commenting the input for the time being]


With the basic features somehow finished, and being myself from Spain, I also wanted to have the demo translated (or at least to make the option easy). I used the official documentation for it,
https://www.renpy.org/doc/html/translation.html . However, for me, these explanations were a bit confusing in some parts, and I had to make some trial and error. As a result, I think it's a good idea to share a step by step here with screenshots.

First, we need to know where the default language is stored (it will help us to avoid headaches later):
 `This is called the None language, regardless of what language it actually is.`
We can find the files at: Conociendo Hokkaido > Game > tl


Now it's time to go back to the launcher and generate the translation/localization files.
To do that, go to the 'Generate Translations' section:



A bit overwhelming menu will be displayed, but don't get discouraged, this is what we need to know:


> Language: This is the name of the target language of your translation files.

> Generate empty strings for translations: as the name implies, you will see your Localized lines empty or filled with the original text. (This difference will be shown in the print screen with the translations, where it is the clearest)
 
When the settings are done, press on 'Generate Translations' and the new files will be created.

Before actually translating the sentences, we also want the language option to show in our game. This part is pretty important, and the instructions in the guide could be easily overlooked (or difficult to follow) for a beginner, making a quest to find were the new code goes. To fix this, here's another example:
 
`The Language action can be used to add a language preference to the preferences screen:`

> The path is as follows: 'Project's name' > Game > screens.rpy

Scroll down, until you see something like this:

```
## Preferences screen ##########################################################
##
## The preferences screen allows the player to configure the game to better suit
## themselves.
##
## https://www.renpy.org/doc/html/screen_special.html#preferences
```


Then add/edit this block there:

```
                vbox:
                    style_prefix "pref"
                    label _("Language")
                    textbutton "English" action Language(None)
                    textbutton "EspaƱol" action Language("es_es")
```

[you can put as many extra languages as you want the same way, just add more textbuttons)]


It's time to launch the game within the engine and see the results:
(a new language option has been added)


Now it's time to really translate/localize the game, the files to do that are in the following path:
'Project's name' > Game > tl > 'the previously input name for the new language'
You can see a comparison with the default language from the script in the image below:



'screens.rpy' for menus and preferences
'script.rpy' for the story text
'common.rpy' for prompt messages


The last step is to export our project to play in our beloved PS Vita. To do that, We need to copy the whole project folder from Ren'Py directory to the Ren'Py PS Vita Distribution Tool. It will look like this:


Here, run the 'Ren'Py PS Vita Distribution Tool.exe' and the export config window will be displayed:


The 'Build VPK0' button will not activate until you have filled the blankets, so don't worry. Extra notes to have into account:
 
> write the version parameter with the '00.00' format, or the VPK installation will fail.
> include your 'sce_sys' folder inside your project's folder (like I did in 'Ren'Py)


With that, you have a working Visual Novel Demo for your PS Vita. If you want to try the one from this entry, or use it as the starting point for yours, here's the link to the GitHub repo:
https://github.com/Bunkai9448/ConociendoHokkaido_renpyVita


---

Aditional notes: 

- No self-voicing, as the vita doesn't have TTS

- Load times can be pretty long due to hardware limitation.

- Video playback will not work

- Quiting by the menu will crash the app, but 
doesn't affect anything else.