Automatyczny ruch w prostej grze.

0

Witam. Piszę prostą gierkę w trybie tekstowym. Coś na wzór Pacmana. Mam jednak problem z poruszaniem postacią. Otóż powinna ona poruszać się w określonym kierunku i zmieniać go jedynie w przypadku wciśnięcia klawisza. Ma ktoś jakieś sugestie, jak to skomponować?

Przykład:

while(ch != 27)
{
	usleep(1);
	ch = getch();
	movePlayer(ch);
	refresh();	
}

Gra nie jest skończona, więc póki co jedyną opcją zakończenia jest wciśnięcie przycisku Esc. Problem jest w tym, że program się zatrzymuje na getch(); i nie wiem jak to pominąć w przypadku jeśli użytkownik nic nie zrobi przez np. 0.1sec.
Dodam jeszcze, że korzystam z biblioteki ncurses i kompiluję pod linuxem przy pomocy gcc.

Pozdrawiam! :)

1

tam gdzie jest getch() powinien być kbhit()

0

@_13th_Dragon jak zwykle jesteś niezastąpiony. Działa i "postać" porusza się samoistnie w danym kierunku, dopóki sami go nie zmienimy. Ale poproszę jeszcze o jedną wskazówkę. Mianowicie porusza się niesamowicie szybko. Właściwie to niewidocznie dla oka, a funkcja usleep() wstawiona we wszystkich logicznych dla mnie miejscach nie działa. Albo działa nie tak jakbym chciał. :) Przypominam przykład z Pacmanem. Chodzi mi o podobny ruch. Jakieś sugestie?

Teraz wygląda to tak:

while(ch != 27)
	{
		usleep(10);
		if(kbhit())
		{
         	  ch = getch();
     		}
		movePlayer(ch);
		refresh();	
	}
0

No tak. Po co zajrzeć do dokumentacji, skoro na jakimś tam forum napisali inaczej... ;)
Dziękuję za pomoc. :)

0

Ech... No i kolejną zagwozdkę mam. Jako że pytanie też dotyczy ruchu, choć tym razem komputera to zapytam w tym temacie. Niestety muszę wkleić też cały kod:

Wiem, że nie działa do końca tak jak trzeba, ale nie o to chodzi. Problem polega na tym, że funkcja moveGhost mimo, że umieszczona w tej samej pętli co funkcja movePlayer,
wykonuje się tylko raz. Czyli duszek daje krok w górę i się zatrzymuje, zamiast iść dalej... A na dodatek w dziwny sposób. Jeśli komuś będzie się chciało to skompilować i sprawdzić to proszę zwrócić uwagę, że jeżeli "gracz" przejdzie przez pole w którym duszek się już kiedyś znajdował, to "mignie" w tym momencie. Chociaż nie powinien...

#include <stdio.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <curses.h>

int mapArray[22][36] =
{
	{2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2},
	{2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2},
};

int row, col;

int ch;

int way = 1;

int pY = 16;
int pX = 18;

int g1X = 17;
int g1Y = 10;
int g1Pos = 0;
/*
int g2X = 17;
int g2Y = 10;
int g2Pos = 0;

int g3X = 19;
int g3Y = 10;
int g3Pos = 0;
*/
int score = 0;

//Sprawdza czy w buforze są jakieś nieodczytane znaki
int kbhit (void)
{
  struct timeval tv;
  fd_set rdfs;
 
  tv.tv_sec = 0;
  tv.tv_usec = 0;
 
  FD_ZERO(&rdfs);
  FD_SET (STDIN_FILENO, &rdfs);
 
  select(STDIN_FILENO+1, &rdfs, NULL, NULL, &tv);
  return FD_ISSET(STDIN_FILENO, &rdfs);
 
}

void writeMap()
{
	int i,k;
	char point;
	
	mapArray[pY][pX] = 4;

	mapArray[g1Y][g1X] = 3;

	
	for(i=0; i<=21; i++)
	{
		move(i,0);
		for (k=0 ; k<=35; k++)
		{
			if (mapArray[i][k] == 2)
			{
				addch('#');
			}
			if (mapArray[i][k] == 1)
			{
				addch(ACS_BULLET);
			}
			if (mapArray[i][k] == 0)
			{
				addch(' ');
			}
			if (mapArray[i][k] == 4)
			{
				addch('o');
			}
			if (mapArray[i][k] == 3)
			{
				addch('g');
			}
		}
	}
	move(1,40);
	printw("Score: %d",score);
	refresh();
}

void moveGhost(int X, int Y, int pos)
{
	/*
		1. up
		2. down
		3. left
		4. right
	*/
	
	 // = (rand() % 4)+1;
	
	switch(way)
	{
		case 1:
			if (mapArray[Y-1][X] != 2) 
			{
				if (mapArray[Y-1][X] != 4)
				{
					mapArray[Y][X] = pos;
					pos = mapArray[Y-1][X];
					Y--;
					mapArray[Y][X] = 3;
					move(Y,X);
					addch('g');
					move(Y+1,X);
					if(mapArray[Y+1][X] == 0)
					{
						addch(' ');
					}
					else
					{
						addch(ACS_BULLET);
					}
				}
			}
		break;	
	}	
}

void movePlayer(int ch)
{	
	switch(ch)
	{
		case KEY_LEFT:
			if (mapArray[pY][pX-1] != 2)
			{
				if (mapArray[pY][pX-1] != 3)
				{
					mapArray[pY][pX] = 0;
					move(pY,pX);
					addch(' ');
					pX--;
					move(pY,pX);
					addch('o');
					mapArray[pY][pX] = 4;
					if (mapArray[pY][pX-1] == 1)
					{
						score++;
						move(1,40);
						printw("Score: %d",score);
					}
					refresh();	
				}
				else
				{
					clear();
					move(row,col);
					mvprintw(row,col,"GAME OVER");
				}
			}
		break;
		case KEY_RIGHT:
			if (mapArray[pY][pX+1] != 2)
			{
				if (mapArray[pY][pX+1] != 3)
				{
					mapArray[pY][pX] = 0;
					move(pY,pX);
					addch(' ');
					pX++;
					move(pY,pX);
					addch('o');
					mapArray[pY][pX] = 4;
					if (mapArray[pY][pX+1] == 1)
					{
						score++;
						move(1,40);
						printw("Score: %d",score);
					}
					refresh();	
				}
				else
				{
					clear();
					move(row,col);
					mvprintw(row,col,"GAME OVER");
				}
			}
		break;
		case KEY_UP:
			if (mapArray[pY-1][pX] != 2)
			{
				if (mapArray[pY-1][pX] != 3)
				{
					mapArray[pY][pX] = 0;
					move(pY,pX);
					addch(' ');
					pY--;
					move(pY,pX);
					addch('o');
					mapArray[pY][pX] = 4;
					if (mapArray[pY-1][pX] == 1)
					{
						score++;
						move(1,40);
						printw("Score: %d",score);
					}
					refresh();	
				}
				else
				{
					clear();
					move(row,col);
					mvprintw(row,col,"GAME OVER");
				}
			}
		break;
		case KEY_DOWN:
			if (mapArray[pY+1][pX] != 2)
			{
				if (mapArray[pY+1][pX] != 3)
				{
					mapArray[pY][pX] = 0;
					move(pY,pX);
					addch(' ');
					pY++;
					move(pY,pX);
					addch('o');
					mapArray[pY][pX] = 4;
					if (mapArray[pY+1][pX] == 1)
					{
						score++;
						move(1,40);
						printw("Score: %d",score);
					}
					refresh();	
				}
				else
				{
					clear();
					move(row,col);
					mvprintw(row,col,"GAME OVER");
				}
			}
		break;
	}
}

int main(void)
{
	initscr();
	noecho();
	curs_set(0);
	keypad(stdscr, TRUE);
	
	srand ( time(NULL) );
	
	getmaxyx(stdscr,row,col);
	row = row/2;
	col = col/2 - 4;
	
	writeMap();
	
	while((ch != 27) && score != 256)
	{
		usleep(100000); 
		if(kbhit())
		{
         	  ch = getch();
     		} 
		movePlayer(ch);
		refresh();
		moveGhost(g1X,g1Y,g1Pos);
		refresh();	
	}

	endwin();
	return(0);
}
 

P.S. Ciekawe też jest, że po wyświetleniu GAME OVER (wejściu w duszka) on nadal jest widoczny...

0

skoro korzystasz z ncurses to wystarczy wywołać raw(); na początku programu i wtedy nie potrzebujesz tego kbhit'a
normalnie piszesz ch=getch();

0

Odkopuję temat. Projekt dokończyłem i oddałem. [kod w załączniku, jeśli ktoś chce]
Gnębi mnie jednak jeszcze kilka pytań. Po pierwsze: z tego co rozumiem, przy trybie raw(); program nie powinien czekać przy funkcji getch(); tak jak normalnie, dobrze rozumiem? Jeżeli tak, to dlaczego to u mnie nie działa? ^^ Jeśli można prosić o jakiś przykład - prosty program kilka linijek, gdzie będzie pokazane jak to działa.
Po drugie: przy nauce korzystałem z tego poradnika: http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/
Proszę mi wytłumaczyć dlaczego przykład skopiowany wprost z niego, a chodzi dokładnie o któryś z pierwszych przykładów z rozdziału WINDOWS, nie działa?
A dokładniej kompiluje się, żadnych błędów nie wywala... Ale okna się nie pojawiają. Tak jakby funkcja box() nie działała...

Z góry dziękuję. :)

P.S. Dlaczego nie można do załącznika dodać pliku z rozszerzeniem .c?

1 użytkowników online, w tym zalogowanych: 0, gości: 1