walkorn Temat założony przez niniejszego użytkownika |
Brak płynności programu » 2019-01-29 21:50:09 Witam, otóż napisałem grę "snake", w której za pomocą funckcji: void idzdoxy( int x, int y ) { HANDLE hCon; COORD dwPos; dwPos.X = x; dwPos.Y = y; hCon = GetStdHandle( STD_OUTPUT_HANDLE ); SetConsoleCursorPosition( hCon, dwPos ); } przenoszę kursor na początek konsoli i wyświetlam planszę na planszy. Problem pojawia się gdy wybieram rozmiar planszy oraz szybkość. Kiedy wybiorę najmniejszy możliwy rozmiar planszy(10/10)oraz najwyższą szybkość (10) to gra działa płynnie, natomiast kiedy rozmiar planszy zmienię np. na 30/30 przy tej samej prędkości wąż porusza się bardzo wolno. Czym jest to dokładnie spowodowane i czy istnieje jakiś sposób aby rozwiązać ten problem? Poniżej wklejam cały kod programu: #include <iostream> #include <cstdlib> #include <conio.h> #include <time.h> #include <windows.h> #include <cmath> using namespace std;
void consoleSize() { HWND console = GetConsoleWindow(); RECT r; GetWindowRect( console, & r ); MoveWindow( console, r.left, r.top, 1000, 800, TRUE ); }
bool gameover( string ** board, int & snakeCordX, int & snakeCordY ) { string border = " "; border[ 0 ] =( char ) 205; border[ 1 ] =( char ) 205; string borderr = " "; borderr[ 0 ] =( char ) 186; string snakeTex = " "; snakeTex[ 0 ] =( char ) 219; snakeTex[ 1 ] =( char ) 219; if( board[ snakeCordX ][ snakeCordY ] == border || board[ snakeCordX ][ snakeCordY ] == borderr || board[ snakeCordX ][ snakeCordY ] == snakeTex ) return true; return false; }
void direction( string & direct ) { int key = getch(); key += getch(); if( key == 296 ) direct = "up"; else if( key == 304 ) direct = "down"; else if( key == 299 ) direct = "left"; else if( key == 301 ) direct = "right"; }
void idzdoxy( int x, int y ) { HANDLE hCon; COORD dwPos; dwPos.X = x; dwPos.Y = y; hCon = GetStdHandle( STD_OUTPUT_HANDLE ); SetConsoleCursorPosition( hCon, dwPos ); }
void boardDraw( string ** board, int boardWidth, int boardHeight ) { for( int i = 0; i < boardHeight; i++ ) { for( int j = 0; j < boardWidth; j++ ) cout << board[ i ][ j ]; cout << endl; } }
void pointGenerator( string ** board, bool & pointExist, int boardWidth, int boardHeight ) { string pointTex = " "; pointTex[ 0 ] =( char ) 176; pointTex[ 1 ] =( char ) 176; int x, y; do { x = rand() %( boardHeight - 2 ) + 1; y = rand() %( boardWidth - 2 ) + 1; } while( board[ x ][ y ] != " " ); board[ x ][ y ] = pointTex; pointExist = 1; }
void snake( string ** board, string & direct, int & snakeCordX, int & snakeCordY, int & size, int XHistory[ 100000 ], int YHistory[ 100000 ], int & nmb, bool & pointExist, int & stop ) { string pointTex = " "; pointTex[ 0 ] =( char ) 176; pointTex[ 1 ] =( char ) 176; string snakeTex = " "; snakeTex[ 0 ] =( char ) 219; snakeTex[ 1 ] =( char ) 219; if( stop == 0 ) { cout << "select the starting direction..." << endl; direction( direct ); cout << "press any button to continue..."; system( "pause > nul" ); system( "cls" ); } stop = 1; XHistory[ nmb ] = snakeCordX; YHistory[ nmb ] = snakeCordY; nmb++; if( direct == "up" ) { snakeCordX--; } else if( direct == "down" ) { snakeCordX++; } else if( direct == "left" ) { snakeCordY--; } else if( direct == "right" ) { snakeCordY++; } if( board[ snakeCordX ][ snakeCordY ] == pointTex ) { size++; pointExist = 0; } }
void hidecursor() { CONSOLE_CURSOR_INFO cci; cci.dwSize = 80; cci.bVisible = FALSE; SetConsoleCursorInfo( GetStdHandle( STD_OUTPUT_HANDLE ), & cci ); }
int main() { string snakeTex = " "; snakeTex[ 0 ] =( char ) 219; snakeTex[ 1 ] =( char ) 219; srand( time( NULL ) ); consoleSize(); string direct = "up"; bool pointExist = 0; int nmb = 0; int size = 1; int XHistory[ 100000 ]; int YHistory[ 100000 ]; int boardWidth; int boardHeight; int gameSpeed; cout << "Podaj szerokosc planszy(10-30): "; cin >> boardWidth; while( boardWidth < 10 || boardWidth > 30 || cin.fail() ) { cin.clear(); cin.ignore(); cout << "Podaj poprawna szerokosc planszy(10-30): "; cin >> boardWidth; } cout << "Podaj wysokosc planszy(10-30): "; cin >> boardHeight; while( boardHeight < 10 || boardHeight > 30 || cin.fail() ) { cin.clear(); cin.ignore(); cout << "Podaj poprawna wysokosc planszy(10-30): "; cin >> boardHeight; } cout << "Podaj predkosc weza(1-10): "; cin >> gameSpeed; while( gameSpeed < 1 || gameSpeed > 10 || cin.fail() ) { cin.clear(); cin.ignore(); cout << "Podaj poprawna predkosc weza(1-10): "; cin >> gameSpeed; } int snakeCordX = rand() %( boardHeight - 2 ) + 1; int snakeCordY = rand() %( boardWidth - 2 ) + 1; string ** board = new string *[ boardHeight ]; for( int i = 0; i < boardHeight; i++ ) board[ i ] = new string[ boardWidth ]; for( int i = 0; i < boardHeight; i++ ) { for( int j = 0; j < boardWidth; j++ ) board[ i ][ j ] = " "; cout << endl; } board[ snakeCordX ][ snakeCordY ] = snakeTex; string border = " "; border[ 0 ] =( char ) 205; border[ 1 ] =( char ) 205; for( int i = 0; i < boardWidth; i++ ) board[ 0 ][ i ] = border; for( int i = 0; i < boardWidth; i++ ) board[ boardHeight - 1 ][ i ] = border; for( int i = 0; i < boardHeight; i++ ) board[ i ][ 0 ] =( char ) 186; for( int i = 0; i < boardHeight; i++ ) board[ i ][ boardWidth - 1 ] =( char ) 186; board[ 0 ][ 0 ] =( char ) 201; board[ boardHeight - 1 ][ boardWidth - 1 ] =( char ) 188; board[ boardHeight - 1 ][ 0 ] =( char ) 200; board[ 0 ][ boardWidth - 1 ] =( char ) 187; hidecursor(); int stop = 0; for(;; ) { idzdoxy( 0, 0 ); boardDraw( board, boardWidth, boardHeight ); Sleep( 1000 / gameSpeed ); if( kbhit() ) direction( direct ); snake( board, direct, snakeCordX, snakeCordY, size, XHistory, YHistory, nmb, pointExist, stop ); if( gameover( board, snakeCordX, snakeCordY ) ) { cout << endl << "Game over score - " << size << endl; break; } board[ snakeCordX ][ snakeCordY ] = snakeTex; board[ XHistory[ nmb - size ] ][ YHistory[ nmb - size ] ] = " "; if( !pointExist ) pointGenerator( board, pointExist, boardWidth, boardHeight ); } return 0; } |
|
YooSy |
» 2019-01-29 22:01:55 Konsola jest wolna.
Jeśli już narysujesz ramki itd. Nic już z nimi nie rób. Poruszaj samym wężem. Przy ruchu węża nadpisuj ogon pustym polem i dodawaj element do głowy we wskazanym kierunku. Gdy coś zje, dodajesz element do głowy i nie ruszasz ogona.
|
|
walkorn Temat założony przez niniejszego użytkownika |
» 2019-01-29 22:17:03 Tylko nie wiem w jaki sposób miałbym wyświetlać jedynie zmienione elementy, skoro całość jest w tablicy i aby poprawnie się wyświetliła muszę wypisać jej całość :/ |
|
YooSy |
» 2019-01-29 22:22:49 Zapamiętuj jakoś sam ogon i głowę i w zależności od sytuacji odpowiednio modyfikuj ich wartości. Masz już funkcję do skakania kursorem po konsoli.
Ruch: 1. Jeśli wąż nie zjadł smakołyka, ustaw kursor na ogon i nadpisz pustym polem. 2. Przesuń głowę o jeden w zadanym kierunku. 3. Resztę węża pozostawiasz bez zmian.
Tablica jest potrzebna do sprawdzania kolizji głowy z tułowiem.
Dlaczego idzdoxy gdy reszta kodu jest z angielska? |
|
jankowalski25 |
» 2019-01-29 22:29:12 do { x = rand() %( boardHeight - 2 ) + 1; y = rand() %( boardWidth - 2 ) + 1; } while( board[ x ][ y ] != " " );
|
Ta pętla jest potencjalnie nieskończona. Jeśli gracz będzie ciągle unikał kolizji, to w końcu ciało węża wypełni całą planszę, a wtedy nie będzie istniało żadne wolne pole, w którym można umieścić owoc i program się tutaj zawiesi. Jednym z rozwiązań jest potraktowanie tego szczególnego przypadku jako „wygranej”. |
|
walkorn Temat założony przez niniejszego użytkownika |
» 2019-01-29 22:43:25 Yoosy - racja, tak chyba zrobię. Co do nazwy to przyznam, że funkcję znalazłem i zapomniałem zmienić jej nazwy. jankowalski25 - dzięki za zwrócenie uwagi, faktycznie o tym nie pomyślałem ;)
Dzięki wielkie wszystkim za pomoc, pozdrawiam.
|
|
pekfos |
» 2019-01-29 23:11:50 Nie zrobisz płynnej gry w konsoli bez niskopoziomowych funkcji z WinAPI, lub innych bibliotek. Zwykłe wypisywanie przez std::cout jest po prostu za wolne na to. Musiałbyś przepisać większość kodu, ale z drugiej strony, dużo tego kodu to nie masz. w końcu ciało węża wypełni całą planszę, a wtedy nie będzie istniało żadne wolne pole, w którym można umieścić owoc i program się tutaj zawiesi. |
Pewnie zawiesi się jeszcze wcześniej. Taki kod wymaga dobrego generatora losowego, a rand() jest tragiczny. Lepiej jest zapisać wszystkie możliwe pozycje dla owoców w tablicy i wylosować jedną z nich. Tylko nie wiem w jaki sposób miałbym wyświetlać jedynie zmienione elementy, skoro całość jest w tablicy i aby poprawnie się wyświetliła muszę wypisać jej całość :/ |
Możesz mieć dwie tablice, a potem wypisywać tylko miejsca, w których się różnią. |
|
walkorn Temat założony przez niniejszego użytkownika |
» 2019-01-29 23:37:20 Nowych bibliotek będę się niebawem uczył, póki co celem tego programu było utrwalenie obecnej wiedzy :). Dzięki za wskazówki co do programu ;) |
|
« 1 » |