Code:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <termios.h>
#include <unistd.h>
#include <sys/select.h>
int mygetch ( void )
{
int ch = 0;
struct termios oldt, newt;
struct timeval tmo;
fd_set rfd;
FD_ZERO(&rfd);
FD_SET(0,&rfd);
tmo.tv_sec = 0;
tmo.tv_usec = 500000; // 1/2 second
tcgetattr ( STDIN_FILENO, &oldt );
newt = oldt;
newt.c_lflag &= ~( ICANON | ECHO );
tcsetattr ( STDIN_FILENO, TCSANOW, &newt );
int result = select(1,&rfd,NULL,NULL,&tmo);
if ( result > 0 ) {
ch = getchar();
}
tcsetattr ( STDIN_FILENO, TCSANOW, &oldt );
return ch;
}
#define TOTAL_FRAMES 3
struct animate {
int drawable;
int numFrames;
char *frames[TOTAL_FRAMES];
int xCoord;
int yCoord;
int xMove;
int yMove;
int currentFrame;
};
#define N_FRAMES 4
struct animate npc[N_FRAMES] = {
{
1,
3,
{ "Ll", "Ls", "Lr" }, // Left, left-foot, standing, right-foot
20, 20,
-1, 0, // moving left, add -1 to x, add 0 to y
0
},
{
0,
3,
{ "Rl", "Rs", "Rr" }, // Right, left-foot, standing, right-foot
0, 0,
+1, 0, // moving right, add +1 to x, add 0 to y
0
},
{
0,
3,
{ "Ul", "Us", "Ur" },
0, 0,
0, -1, // moving up, add 0 to x, add -1 to y
0
},
{
0,
3,
{ "Dl", "Ds", "Dr" },
0, 0,
0, +1, // moving down, add 0 to x, add +1 to y
0
},
};
void animate ( void ) {
for ( int i = 0 ; i < N_FRAMES ; i++ ) {
if ( !npc[i].drawable ) continue;
printf("(%02d,%02d)%s ",
npc[i].xCoord, npc[i].yCoord,
npc[i].frames[npc[i].currentFrame] );
fflush(stdout);
if ( ++npc[i].currentFrame == npc[i].numFrames ) {
npc[i].currentFrame = 0; // back to the start of the animation sequence
}
// move the character
npc[i].xCoord += npc[i].xMove;
npc[i].yCoord += npc[i].yMove;
}
}
int main(void)
{
int ch;
int oldDir = 0, newDir = 0;
do {
ch = mygetch();
if ( ch != 0 ) {
ch = toupper(ch);
switch ( ch ) {
case 'L':
newDir = 0;
break;
case 'R':
newDir = 1;
break;
case 'U':
newDir = 2;
break;
case 'D':
newDir = 3;
break;
}
}
if ( oldDir != newDir ) {
// start off new direction from last old position
npc[newDir].xCoord = npc[oldDir].xCoord;
npc[newDir].yCoord = npc[oldDir].yCoord;
// make respective directions not drawable and drawable
npc[oldDir].drawable = 0;
npc[newDir].drawable = 1;
// make sure animation starts in a known state
npc[newDir].currentFrame = 0;
// now heading in this direction
oldDir = newDir;
printf("\n");
}
animate();
} while ( ch != 'Q' );
return 0;
}
$ gcc -std=c99 foo.c
$ ./a.out
(20,20)Ll (19,20)Ls (18,20)Lr (17,20)Ll (16,20)Ls (15,20)Lr (14,20)Ll (13,20)Ls (12,20)Lr (11,20)Ll (10,20)Ls
(09,20)Rl (10,20)Rs (11,20)Rr (12,20)Rl (13,20)Rs (14,20)Rr (15,20)Rl (16,20)Rs (17,20)Rr (18,20)Rl (19,20)Rs
(20,20)Dl (20,21)Ds (20,22)Dr (20,23)Dl (20,24)Ds
(20,25)Ul (20,24)Us (20,23)Ur (20,22)Ul (20,21)Us (20,20)Ur (20,19)Ul (20,18)Us (20,17)Ur (20,16)Ul (20,15)Us (20,14)Ur (20,13)Ul (20,12)Us
(20,11)Ll (19,11)Ls (18,11)Lr (17,11)Ll (16,11)Ls (15,11)Lr
(14,11)Dl (14,12)Ds (14,13)Dr (14,14)Dl (14,15)Ds (14,16)Dr (14,17)Dl
(14,18)Rl (15,18)Rs
(16,18)Dl (16,19)Ds (16,20)Dr (16,21)Dl (16,22)Ds