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

gra ruguelike - jak pozbyć się migotania?

Ostatnio zmodyfikowano 2012-05-11 23:52
Autor Wiadomość
53VD3V
Temat założony przez niniejszego użytkownika
gra ruguelike - jak pozbyć się migotania?
» 2012-05-10 20:43:30
Jestem bardzo początkujący. Nie mam serca do kodowania kalkulatorów, więc jako trening piszę prostą "grę" typu roguelike.
Cała gra jest w pętli:
1. aktualizacja macierzy "świata"
2. rysowanie wszystkiego na ekranie
3. czekanie na klawisz i odpowiednie operacje na zmiennych
I tak na okrągło.

To wszystko jest w oknie konsoli, a za grafikę robią znaki ascii (takie są gry roguelike). Te znaki wyświetlają się chyba za wolno, bo jest efekt migotania przy każdym rysowaniu tego od nowa.
Z pętli usuwałem punkty 1 i 3 i dalej migotało, stąd wiem, że to rysowanie jest problemem.
Wygląda ono tak:
C/C++
void rysujmatrix()
{
    system( "CLS" );
    for( int wysokosc = 0; wysokosc < WYSOKOSC; wysokosc++ )
    {
        for( int szerokosc = 0; szerokosc < SZEROKOSC; szerokosc++ )
        {
            cout << matrix[ szerokosc ][ wysokosc ];
        }
        cout << std::endl;
    }
}
Niby prościej się nie da, a jednak jest za wolne.

Ktoś powiedział mi, że mam rysować z bufora. Szukałem o tym w necie, ale tam znalazłem tylko jakieś niezrozumiałe gotowe kody i to często jeszcze nie na C++. A ja chcę wszystko wklepać sam i muszę rozumieć co wpisuję.
Więc moje pytanie brzmi: jak, mając tylko biblioteki z Code::Blocks, używać tego "bufora" ekranu konsoli? Wydaje mi się to dziwne, że najpierw trzeba coś narysować w buforze, a potem z niego na ekran i że ma to być szybsze.

Mógłbym jeszcze spróbować rozwiązać to inaczej i nie rysować ciągle wszystkego od nowa, a tylko rysować same zmiany. Tylko że wtedy potrzebuję przemieścić kursor. W necie znalazłem polecenia cputsxy() i gotoxy(), ale one u mnie nie działają chociaż mam #include <conio.h>, bo używam getch().
P-56414
Admixior
» 2012-05-10 22:23:59
1. To czy ekran miga w dużej mierze zależy od sprzętu.
2. Spróbuj zamiast wersji debug dać release powinno tak nie mrugać. Wtedy iostream jest szybsze i używa bufora.
3. Zamiast w pętli pisać po jednym elemencie użyj write() czy jakiejś podobnej funkcji... Po jednym elemencie jest baaaardzo wolno.
4. Ogólnie cout jest postrzegany za wolniejsze niż np. printf(); może jest jakaś funkcja na winapi która pisze w konsoli określoną ilość znaków, w której podajesz macierz i ilość znaków.
P-56433
SeaMonster131
» 2012-05-10 22:31:06
Albo możesz zrobić też tak:

C/C++
PlanszaUpdate(); // te rysowanie

while() // petla glowna
{
    if( klawisz w lewo )
    {
        idz_w_lewo();
        system( "cls" );
        PlanszaUpdate();
    }
   
}

Czyli nie rysuj cały czas tego, ale tylko wtedy, kiedy jest potrzebne odrysowanie.
P-56436
ison
» 2012-05-11 00:35:51
ogólnie przy rysowaniu mapy, która zawsze ma taki sam rozmiar możesz zastosować pewien trik, po prostu zamiast czyścić ekran przenieś kursor na początek konsoli i rysuj mapę na poprzedniej http://msdn.microsoft.com/en-us/library/windows/desktop/ms686025%28v=vs.85%29.aspx
P-56451
pekfos
» 2012-05-11 14:15:52
www.google.com (Zapisz sobie na kartce i powieś na monitorze)
O tym były tu już (co najmniej) 2 tematy. Strasznie trudno samemu pomyśleć i poszukać..

//edit:
system( "CLS" );
A o tym w ogóle zapomnij.
1. Powoduje "fałszywe alarmy" w antywirusach
2. Zwiększa miganie
P-56466
53VD3V
Temat założony przez niniejszego użytkownika
» 2012-05-11 16:10:37
"1. To czy ekran miga w dużej mierze zależy od sprzętu."

Ale na pewno da się miganie zlikwidować i to na gorszym sprzęcie. Dowód: wszystkie gry rougelike.

"2. Spróbuj zamiast wersji debug dać release powinno tak nie mrugać. Wtedy iostream jest szybsze i używa bufora."

Nie wiem jak to zrobić. Przeszukałem chyba wszystkie opcje w menu. C::B wszystko mi robi w katalugu debug. W pasku narzędziowym obok przycisków build itd. mam napis "Build target", ale obok jest wszystko nieaktywne, więc został tylko sam napis.

"3. Zamiast w pętli pisać po jednym elemencie użyj write() czy jakiejś podobnej funkcji... Po jednym elemencie jest baaaardzo wolno."

Nie znam write() więc poszukałem i znalazłem to [url]http://www.cplusplus.com/reference/iostream/ostream/write/[/url]. Jak mam rozumieć taki zapis?

"4. Ogólnie cout jest postrzegany za wolniejsze niż np. printf(); może jest jakaś funkcja na winapi która pisze w konsoli określoną ilość znaków, w której podajesz macierz i ilość znaków."

Zmiana na printf() nie dała widocznego efektu. WinAPI jeszcze nie znam, zresztą chce zrobić grę na konsolę tekstową, takie jak powstawały jeszcze jak nie było windowsa.

"Albo możesz zrobić też tak:

C/C++
C/C++
PlanszaUpdate(); // te rysowanie

while() // petla glowna
{
    if( klawisz w lewo )
    {
        idz_w_lewo();
        system( "cls" );
        PlanszaUpdate();
    }
   
}

Czyli nie rysuj cały czas tego, ale tylko wtedy, kiedy jest potrzebne odrysowanie."


Tak właśnie u mnie jest. Rysowanie jest tylko po tym jak wciśnie się jakiś klawisz, czyli wykona jakąś akcję. Gdy nic się nie wciska, to po prostu obraz trwa narysowany i nie miga.


"ogólnie przy rysowaniu mapy, która zawsze ma taki sam rozmiar możesz zastosować pewien trik, po prostu zamiast czyścić ekran przenieś kursor na początek konsoli i rysuj mapę na poprzedniej http://msdn.microsoft.com/en-us/library/windows/desktop/ms686025%28v=vs.85%29.aspx"

Dobry pomysł. Tylko potrzebuję przemieścić kursor, a u mnie (Code::Blocks 10.5 instalacja full) nie działało (czyli dawało "error: 'gotoxy' was not declared in this scope") ani gotoxy() ani _gotoxy(), chociaż mam #include <conio.h>, które działa, bo używam getch, które bez conio.h nie działa.
Do tego co jest w tym linku to nawet nie wiem jak się zabrać.

Ale znalazłem coś tutaj http://projectsofashok.blogspot.com/2010/05/gotoxy-in-codeblocks.html

Skopiowałem i DZIAŁA, tylko że nie bardzo rozumiem co to jest. Widzę, że coord to zmienna typu COORD, ale co to jest GetStdHandle(STD_OUTPUT_HANDLE) to nie wiem. I niezbyt mi się podoba to, że muszę dołączyć windows.h, skoro to gra w oknie DOS-a.

Czy gdy dołączam ciągle nowe include dla jednego polecenia, to program jest gorzej zoptymalizowany, czy to nie ma znaczenia?

Widzę, że z tymi bibliotekami to jest niezły bajzel w C++.

"www.google.com (Zapisz sobie na kartce i powieś na monitorze)
O tym były tu już (co najmniej) 2 tematy. Strasznie trudno samemu pomyśleć i poszukać.."


Trochę szukałem, ale jak się trafia ciągle na porady, które nie działają, niezrozumiałe kody albo porady typu "kto teraz pisze na konsole", to się w końcu chce samemu opisać problem. Poczytałem trochę kursów na tej stronie i zdziwiłem się, że są takie dobre. Czytałem ich wiele, ale tutaj wyjaśnionych jest wiele rzeczy, które są pomijane gdzie indziej. No to wybrałem to forum.

"system( "CLS" );
A o tym w ogóle zapomnij.
1. Powoduje "fałszywe alarmy" w antywirusach
2. Zwiększa miganie"


Czyli teraz, gdy mogę przemieszczać kursor, zamiast system("CLS") czyścić spacjami albo backspace'ami?
P-56492
pekfos
» 2012-05-11 19:58:16
1. To czy ekran miga w dużej mierze zależy od sprzętu.
To chyba największa bzdura w tym temacie :P

2. Spróbuj zamiast wersji debug dać release powinno tak nie mrugać.
Kolejna bzdura.

Czyli teraz, gdy mogę przemieszczać kursor, zamiast system("CLS") czyścić spacjami albo backspace'ami?
Jak coś w buforze się zmieniło to ustaw kursor na 0,0 i zapisz cały ekran konsoli od nowa. (Musisz swój bufor zrobić)

może jest jakaś funkcja na winapi[..]
WriteConsole() ..
P-56508
Admixior
» 2012-05-11 23:52:41
@up:
Wziąłem się i sprawdziłem. Wyniki mnie zdziwiły bo zawsze byłem przekonany że debug działa wolniej release. Jednak masz racje że to nie prawda.
Co do funkcji z write ze strumienia cout to też ona nie przyspiesza pisania :(

Można by powiedzieć że cały pierwszy post był za szybko napisany ;p

A co do WriteConsoleA(...); to działa znacznie szybciej :)
C/C++
#include <iostream>
#include <SFML\System.hpp>

using namespace std;
using namespace sf;

int main()
{
    char tabl[ 10000 ];
    memset( tabl, 'a', 10000 );
    Clock time;
    time.Reset();
    DWORD x;
    if( !WriteConsoleA( GetStdHandle( STD_OUTPUT_HANDLE ), tabl, 10000, & x, 0 ) ) return GetLastError();
   
    cout << endl << time.GetElapsedTime();
    cin.get();
   
    time.Reset();
    for( int i = 0; i < 10000; i++ ) cout << 'a';
   
    cout << endl << time.GetElapsedTime();
    cin.get();
   
}

Wyniki są:
dla WriteConsoleA() ~ 0.0059s - ok. 107x szybsza
dla std::cout       ~ 0.63655s

Ustawiając na początku ekranu kursor i pisząc przez WriteConsoleA() nie powinno być problemów.

//PS thx pekfos za wyprowadzenie z błędu
P-56515
« 1 »
  Strona 1 z 1