Thursday, 7 November 2013

My games - Snake

"Snake" was the first game I created with C++ and Allegro 4, back in 2008. I was then still learning the basics of programming, and today going through the source code is in itself a adventure in both shame and nostalgy.

It's a fairly straightforward Centipede clone, heavily inspired by playing the eponymous Snake on a Nokia 3310 (so oldschool!). Here in Brasil this mobile phone is called the "Tijolão", literally the "Big brick".


If you want to experience this piece of nostalgic beauty, this piece of C++ genius, this piece of art in monochromatic graphics, download the game here. Package includes both source code and binaries for 32-bit Windows and 64-bit Linux.

When you first open the game, you are given the option of which difficulty level to play. The menu below isn't the one I originally created for the game in MS Paint back in 2008. I lost that file when I formatted my computer some years ago. This is mostly fortunate: the old "menu.bmp" had quite doubtful "aesthetics".


After selecting the difficulty you are presented to state-of-the-art technology in game GFX consisting of blue squares over black background.


Points are displayed on the top left corner, and you are given 5 points for each food (blue dot) you eat, until you collide either with yourself or the walls. Basic stuff.

Through not so basic to someone learning C++ from a badly-written PDF hastily downloaded with a 56kbps dial-up connection. Looking through the source code, we can find many jewels of WOP (Workaround-oriented programming).

Here I shall present them, for both my great shame and as a monument to the better programming skills I have today.


Both the foods and the snake itself are represented through the coordinate structure below (please don't mind the comments in portuguese):

struct coord          // struct com coordenadas x e y
{
       int x, y;
};

In this fashion, the snake is simply defined as an array of coords, and the head of the snake is the first element in the array. You'd think I would use something like std::vector or even std::list to create this array. However, 2008 me had no knowledge of such sorcery, so I just declared an static, laaaarge array.

     coord snake[10000];                     // array da cobrinha

You'd also think I would directly use the primitive-drawing Allegro functions to draw the graphics. However, 2008 me managed the unthinkable. I created a 25x25 BITMAP, drew a rectangle onto it and then drew this BITMAP where each coord was, instead of simply drawing the rectangle directly onto the screen.

     BITMAP *ponto;                         // imagem do corpo da cobra e da comida (food and snake's body image)
     ponto = create_bitmap(8, 8);                   // cria a imagem (creates the image)
     rectfill(ponto, 0, 0, 7, 7, 25); // desenha o ponto (draw the dot)
                      [...]
                         for(i = tam; i > 0; i--)    // desenha a cobra (draws the snake)
                         {
                                     draw_sprite(tela, ponto, snake[i].x, snake[i].y);
                         }
                         draw_sprite(tela, ponto, comida.x, comida.y); // desenha a comida (draw the food)

Also, even more surprisingly, I used this BITMAP to draw the walls!

                         for(i = 0; i <= 79; i++)     // desenha a parede de cima (draw the top wall)
                         {
                                draw_sprite(tela, ponto, i * 8, 8);
                         }
                         for(i = 0; i <= 79; i++)    // desenha a parede de baixo (draw the bottom wall)
                         {
                                draw_sprite(tela, ponto, i * 8, 472);
                         }
                         for(i = 1; i <= 59; i++)    // desenha a parede da esquerda (draw the left wall)
                         {
                                draw_sprite(tela, ponto, 0, i * 8);  
                         }
                         for(i = 1; i <= 59; i++)     // desenha a parede da direita (draw the right wall)
                         {
                                draw_sprite(tela, ponto, 632, i * 8);
                         }

This is actually much more complicated than the obvious solution. I can't remember why I thought this was a good idea.

Not only were my programming skills limited, but also my english-language skills. Here's an original anglophone snippet from 2008 me:

                         go = 0;                // now not wented

These and other abysmal thoughts populate the code. Now, I know what you are expecting (or should be expecting). There's something that always lies in the core of all beginner programmers code (at least beginners programming in languages that allow it)

http://xkcd.com/292/

Yes. The shameful, dreaded, "goto". Bringer of spaghetti-code and much despair.

                         if(go == 1)       // se já foi vai para o fim da checagem de teclas pressionadas (if done already jump to the end of input treatment)
                         { 
                               goto input_end;    
                         }
                         if((key[KEY_RIGHT]) && (dir != 4))
                         {
                                        dir = 2;
                                        go = 1;
                         }
                         if(go == 1)
                         {
                               goto input_end;
                         }                         
                         if((key[KEY_DOWN]) && (dir != 1))
                         {
                                        dir = 3;
                                        go = 1;
                         }
                         if(go == 1)
                         {
                               goto input_end;
                         }                         
                         if((key[KEY_LEFT]) && (dir != 2))
                         {
                                        dir = 4;
                                        go = 1;
                         }
                         if(go == 1)
                         {
                               goto input_end;
                         }                         
                         input_end:
But enough of this monstrosity. I conclude here my travel back in time, and I hope you can share similar, intriguing experiences of a newbie past in the world of game development.

No comments:

Post a Comment