martes, 31 de marzo de 2015

Nonogram Generator

What’s up!!  So I was the other day watching my friend Marta playing some game about a cat. My first thought was that “Oh yeah, a game about a cat, what’s next?” I kept watching her (and the game as well) and I noticed that It was a nonogram game with colors, a Picross!!. Now that is cool.
What if I make a prototype like that? a simple nonogram game without all that colors and cats, just black and white… It’s possible… –Hey hey hey slow down smart ass, what the hell is a nonogram?. You’re right I haven’t told anything about them, let’s start from there.

You know… I could try to explain what a Nonogram is without success, then you are going to think that I’m stupid and you’re going to open Wikipedia and search for it, so I’m gonna save you the trouble Here you have it.

Now that we’re masters of all Japanese puzzle we shall continue. To create a nonogram we need to visualize the end, for example we want to create this nonogram designed by my friend Chema (Great friend, better person).
 level13
This 5x5 nonogram may be easy to manually generate and create the desired game board right? but what if we want to make 50? 100? or 8x8 nonograms? The problem starts to complicate quickly, very quickly so why don’t we just design the final image of the nonogram and let a program generate the board for us? That would be great, we just have to open GIMP or Photoshop or any other image editor program and start painting. Oh yes, I like that.

The next step is to design the serialized file for each nonogram, would it be a XML? JSON? plain text? SQL? (Really? are you even evaluating SQL?). XML and JSON are just plain text with some improvements that would help in a bigger project or serialization. In this approach I decided to use plan text because it would be easier to serialize and deserialize, each file would start with the size of the nonogram and then a list for each row and column with the numbers that the board should show. This is the serialized text for the nonogram from above:
5x5
row:2
row:4
row:1 1
row:1 2
row:2
col:2
col:1 2
col:2 1
col:2 1
col:2
Now that we’ve defined our serialized text we need to reverse from the final image to the text, here’s the thing!! We’re gonna analyze the image, pixel by pixel and generate the desired output. For my example I’ve asked Chema (Do you remember him? he’s my friend hahahaha) to use GIMP and create a 5x5 image, design his nonogram and export it as bitmap. We’re gonna open the image from a C# program and look if each pixel is black or white to generate the output.

First, we need some attributes and a constructor, I decided that each object will process just one image, so I open the image in the constructor. Like this:

private Bitmap image;
private int tileSize;
private string imageRoute;

public ImageProcessor(int tileSize, string imageRoute)
{
    this.tileSize = tileSize;
    image = (Bitmap) Bitmap.FromFile(imageRoute).Clone();
    this.imageRoute= imageRoute;
}

Then we need a method that converts the rows and columns to a string[]. This could be the ugliest part of the code and if anyone has a better solution please let me know.


public string[] GenerateAxis(int mainAxisSize, int auxAxisSize, bool swapIndex)
{
    string[] cols = new string[mainAxisSize / tileSize];
    for (int i = 0; i < mainAxisSize / tileSize; i++)//Iterate over the main axis Col|row
    {
        int consecutiveNumbers = 0;//counter for consecutive black pixels
        StringBuilder sb = new StringBuilder();
        for (int j = 0; j < auxAxisSize / tileSize; j++)
        {
            //We store the index in a local copy because if we have to swap the index
            //we could modify those values and generate an infinite loop
            int a = i;
            int b = j;
            int aux = 0;
            if (swapIndex)
            {
                aux = a;
                a = b;
                b = aux;
            }
            //Get the color of the pixel
            Color pixel = image.Get Pixel(a,b);
            //The image is in black and white so we look for one component to be almost black (It can be R|G|B)
            if (pixel.R < 10)
                consecutiveNumbers++;
            else
            {
                if (consecutiveNumbers > 0)
                {
                    sb.Append(consecutiveNumbers.ToString()).Append(" ");
                    consecutiveNumbers = 0;
                }
            }
        }

        if (consecutiveNumbers > 0)
            sb.Append(consecutiveNumbers.ToString()).Append(" ");
        //Trim the result to delete any whitespace, tab or extra line
        cols[i] = sb.ToString().Trim();
    }
    return cols;
}

Now we have to call this method for the rows and columns, then format the output string and write it to a .txt file.

public void SerializeNonogram()
{
    string[] cols = GenerateAxis(image.Width, image.Height, false);
    string[] rows = GenerateAxis(image.Height, image.Width, true);
    StringBuilder sb = new StringBuilder();
    sb.AppendLine(rows.Length + "x" + cols.Length);
    //If any row or column should be left blank then
    //we print a "0"
    foreach (string row in rows)
    {
        if (row == "")
            sb.AppendLine("row:0");
        else
            sb.AppendLine("row:" + row);
    }

    foreach (string col in cols)
    {
        if (col == "")
            sb.AppendLine("row:0");
        else
            sb.AppendLine("col:" + col);
    }

    File.WriteAllText("TextLevels\\"+imageRoute.Replace(".bmp", ".txt"), sb.ToString());
}
And that’s it!! It should generate a .txt with the same name as the input BitMap. I made a little bulk convert to generate all the levels of my game but that’s up to you :3

So I finally ended my first serious post, please be comprehensive about my writing style and if you have any doubt, comment or flame just write it below.

miércoles, 25 de marzo de 2015

Every start is tough

You know.... There comes a time in the life of every person when you want to show the world what you have achieved. To shout and demonstrate that you're worth. Well.... Fuck It, I'm not gonna get philosophical.

But yes, I want to try at least to share my stuff and to have a place to drop all my code and thoughts.

You, dear reader (if there's any...), may ask yourself what are you gonna find here, well... As I said before I want a place to share my ideas and my recent knowledge so this is what this is about: me, trying to learn something new, or just trying to tweak something, an idea, an algorithm or a design and then explaining my solution even if it is not the best.

Here I'm gonna follow the EYOS principle, named by Alejandro, my companion of programming ideas and mostly the reason of every thing that I'm gonna put here.

The EYOS principle means basically Eat Your Own Shit. No, it's not literal (thank God). This means is that I love to learn how things works from the very inside, and I will try to replicate it's functionality from scratch just for fun.

My dear reader, if you managed to read all this first post and not to fall asleep in the process let me make a last request:

Stay tuned because there's a series of tutorials coming about creating your own cpu-based render engine. I just don't know of I'm gonna write it in English or Spanish.....

Anyway... Thank you for reading.