Thursday, January 3, 2013

Creating moving shapes in ncurses

If you followed the couple of my previous posts on ncurses programs, I think you can manage with creating any shape in it colorfully. Think it's time to move the shapes you create (give them a little life :p)

But make sure you can create the shapes easily before going through this post because I won't be explaining the creation of shapes ncurses here.


Moving a triangle down

















The above images show two screenshots that are taken of the running program. All what you can see is a simple triangle printed but moves from top to bottom during run time. What do you think is happening?  Is there anyway to automate the object to move. But what I have done here is very simple as shown below.


  1. have a function to print a triangle
  2. have a function to erase the printed triangle
  3. call the printing method
  4. refresh the screen
  5. call the erasing method
  6. do the task 3, 4 and 5 repeatedly.

I think the concept is simple to understand. observe the below source code for further clarification.

#include<ncurses.h>
void print_triangle(int startRow,int startCol,int height);      //function declaration to print triangle
void erase_triangle(int startRow,int startCol,int height);     //function declaration to erase triangle

int main()

{
int sr=10;                                        //variable which holds the starting row value
initscr();
for(int m=1;m<=15;m++)                //this loop decides how many times we need to move the triangle
{
print_triangle(sr,45,4);             //print triangle
refresh();                                 //refresh the screen

for(int s=1;s<=500000000;s++);   //loop which controls the speed of the moving triangle

erase_triangle(sr,45,4);           //erase the triangle which is drawn before
refresh();                                //refresh the screen
sr++;                                             //increment the starting row by one
}
getch();
endwin();
return 0;
}

//----------------------------------------------------------------------------------
void print_triangle(int startRow,int startCol,int height)
{
int x=startCol;
for(int r=startRow;r>=startRow-height;r--)
{
for(int c=startCol;c<=x;c++)
{
move(r,c);
printw("*");
}
x++;
startCol--;
}

}

//----------------------------------------------------------------------------------
void erase_triangle(int startRow,int startCol,int height)
{
        int x=startCol;
        for(int r=startRow;r>=startRow-height;r--)
        {
                for(int c=startCol;c<=x;c++)
                {
                        move(r,c);
                        printw(" ");
                }
                x++;
                startCol--;
        }

}

think what you need to do to,
  1. move the triangle faster
  2. move the triangle slower
It's really simple. note the line of code below,

for(int s=1;s<=500000000;s++);   

by increasing the highlighted value (in blue), you can slow down the triangle's movement and by decreasing it, you can move the triangle faster. Also note that the above loop is like the Thread.sleep() method in other languages like c# and java which pauses the program between two actions to keep it idle for sometimes.

Moving an upside down 'T' shape horizontally

















It's again the combination of two rectangles that are moving together.we need to increment the starting column here to move it horizontally.

Source Code :


#include<ncurses.h>
void printbox(int startrow,int startcolumn,int height,int width);
void erasebox(int startrow,int startcolumn,int height,int width);
int main()
{
initscr();

int col1=45,w1=3,col2=42,w2=9;
for(int x=1;x<=10;x++)
{
printbox(5,col1,3,w1);
printbox(9,col2,1,w2);
refresh();

for(int s=1;s<=500000000;s++);

erasebox(5,col1,3,w1);
erasebox(9,col2,1,w2);
refresh();

col1++;
col2++;


}

getch();
endwin();
return 0;
}

//----------------------------------------------------------------------------------
void printbox(int startrow,int startcolumn,int height,int width)
{
for(int r=startrow;r<=startrow+height;r++)
{
for(int c=startcolumn;c<=startcolumn+width;c++)
{
move(r,c);
printw("*");
}

}

}

//----------------------------------------------------------------------------------
void erasebox(int startrow,int startcolumn,int height,int width)
{
for(int r=startrow;r<=startrow+height;r++)
        {
                for(int c=startcolumn;c<=startcolumn+width;c++)
                {       
                        move(r,c);
                        printw(" ");
                }

        }

}

Moving an upside down 'T' shape vertically




Source code :

#include<ncurses.h>
void printbox(int startrow,int startcolumn,int height,int width);
void erasebox(int startrow,int startcolumn,int height,int width);
int main()
{
initscr();

int row1=5,h1=3,row2=9,h2=1;
for(int x=1;x<=10;x++)
{
printbox(row1,45,h1,3);
printbox(row2,42,h2,9);
refresh();

for(int s=1;s<=500000000;s++);

erasebox(row1,45,h1,3);
erasebox(row2,42,h2,9);
refresh();

row1++;
row2++;


}

getch();
endwin();
return 0;
}

//----------------------------------------------------------------------------------
void printbox(int startrow,int startcolumn,int height,int width)
{
for(int r=startrow;r<=startrow+height;r++)
{
for(int c=startcolumn;c<=startcolumn+width;c++)
{
move(r,c);
printw("*");
}

}

}

//----------------------------------------------------------------------------------
void erasebox(int startrow,int startcolumn,int height,int width)
{
for(int r=startrow;r<=startrow+height;r++)
        {
                for(int c=startcolumn;c<=startcolumn+width;c++)
                {       
                        move(r,c);
                        printw(" ");
                }

        }

}



Moving a fish horizontally















Source Code :

#include<ncurses.h>
void print_triangle(int startRow,int startCol,int width);
void erase__triangle(int startRow,int startCol,int width);
int main()
{
int sc1=15,w1=3,sc2=21,w2=5;
initscr();
start_color();
init_pair(1,COLOR_RED,COLOR_WHITE);
init_pair(2,COLOR_MAGENTA,COLOR_BLUE);
init_pair(3,COLOR_BLACK,COLOR_BLACK);
for(int m=1;m<=20;m++)
{ attrset(COLOR_PAIR(1)); print_triangle(10,sc1,w1);
attrset(COLOR_PAIR(2));
print_triangle(10,sc2,w2);
refresh();
for(int s=1;s<=300000000;s++);
attrset(COLOR_PAIR(3));
erase__triangle(10,sc1,w1);
attrset(COLOR_PAIR(3));
erase__triangle(10,sc2,w2);
refresh();
sc1=sc1+2;
sc2=sc2+2;
}
getch();
endwin();
return 0;
}
//----------------------------------------------------------------------------------
void print_triangle(int startRow,int startCol,int width)
{
int x=startRow;
for(int c=startCol;c>=startCol-width;c--)
{
for(int r=startRow;r<=x;r++)
{
move(r,c);
printw("*");
}
x++;
startRow--;
}
}

//----------------------------------------------------------------------------------
void erase__triangle(int startRow,int startCol,int width)
{
int x=startRow;
        for(int c=startCol;c>=startCol-width;c--)
        {
                for(int r=startRow;r<=x;r++)
                {
                        move(r,c);
                        printw(" ");
                }
        x++;
        startRow--;
        }
}


Moving multiple objects to different directions simultaneously

Here the blue color frame moves horizontally, Cyan colored frame moves vertically and the magenta colored frame moves diagonally. Observe the code carefully.














Source Code :

#include<ncurses.h>
void print_boxes(int startrow,int startcol,int height,int width);
void erase_boxes(int startrow,int startcol,int height,int width);

int main()
{
int sr1=10,sr2=1,sr3=5;
int sc1=10,sc2=3,sc3=7;
initscr();
start_color();
init_pair(1,0,6);
init_pair(2,0,4);
init_pair(3,0,5);
init_pair(4,0,0);
for(int m=1;m<=20;m++)
{
attrset(COLOR_PAIR(1));
print_boxes(sr1,sc1,5,20);

attrset(COLOR_PAIR(2));
print_boxes(sr2,sc2,12,5);

attrset(COLOR_PAIR(3));
print_boxes(sr3,sc3,10,20);
refresh();

for(int s=1;s<=400000000;s++);
attrset(COLOR_PAIR(4));
                erase_boxes(sr1,sc1,5,20);
attrset(COLOR_PAIR(4));
                erase_boxes(sr2,sc2,12,5);

attrset(COLOR_PAIR(4));
                erase_boxes(sr3,sc3,10,20);
                refresh();

sr1++;
sc2++;
sr3++;
sc3=sc3+2;
}
getch();
endwin();
return 0;

}

//----------------------------------------------------------------------------------
void print_boxes(int startrow,int startcol,int height,int width)
{
for(int r=startrow;r<=startrow+height;r++)
{
for(int c=startcol;c<=startcol+width;c=c+width)
{
move(r,c);
printw("*");
}
}

for(int c=startcol;c<=startcol+width;c++)
{
for(int r=startrow;r<=startrow+height;r=r+height)
{
move(r,c);
printw("*");
}
}

}

//----------------------------------------------------------------------------------
void erase_boxes(int startrow,int startcol,int height,int width)
{
        for(int r=startrow;r<=startrow+height;r++)
        {
                for(int c=startcol;c<=startcol+width;c=c+width)
                {
                        move(r,c);
                        printw(" ");
                }
        }

        for(int c=startcol;c<=startcol+width;c++)
        {
                for(int r=startrow;r<=startrow+height;r=r+height)
                {
                        move(r,c);
                        printw(" ");
                }
        }

}