Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Brak płynności programu

Ostatnio zmodyfikowano 2019-01-29 23:37
Autor Wiadomość
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:
C/C++
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:

C/C++
#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"; //gora
    else if( key == 304 ) direct = "down"; //dol
    else if( key == 299 ) direct = "left"; //lewo
    else if( key == 301 ) direct = "right"; //prawo
   
}

//nadpisanie ekranu
void idzdoxy( int x, int y )
{
    HANDLE hCon;
    COORD dwPos;
    dwPos.X = x;
    dwPos.Y = y;
    hCon = GetStdHandle( STD_OUTPUT_HANDLE );
    SetConsoleCursorPosition( hCon, dwPos );
}

//rysowanie planszy
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;
    }
}

//generowanie punktu
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;
}




//zachowanie weza
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++;
   
    //poruszanie
    if( direct == "up" )
    {
        snakeCordX--;
    }
    else if( direct == "down" )
    {
        snakeCordX++;
    }
    else if( direct == "left" )
    {
        snakeCordY--;
    }
    else if( direct == "right" )
    {
        snakeCordY++;
    }
    //zdobycie punktu
    if( board[ snakeCordX ][ snakeCordY ] == pointTex )
    {
        size++;
        pointExist = 0;
    }
    //koniec gry
   
   
   
   
}

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;
   
    //dziwne
    string ** board = new string *[ boardHeight ];
   
    for( int i = 0; i < boardHeight; i++ )
         board[ i ] = new string[ boardWidth ];
   
   
    //pusta tablica
    for( int i = 0; i < boardHeight; i++ )
    {
        for( int j = 0; j < boardWidth; j++ ) board[ i ][ j ] = "  ";
       
        cout << endl;
    }
    //snake generator
   
    board[ snakeCordX ][ snakeCordY ] = snakeTex;
   
    //ramka
    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;
}
P-173790
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.
P-173791
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ść :/
P-173792
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?
P-173793
jankowalski25
» 2019-01-29 22:29:12
C/C++
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”.
P-173794
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.
P-173795
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ą.
P-173796
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 ;)
P-173798
« 1 »
  Strona 1 z 1