Autor Wątek: Wolna konsola - jak przyśpieszyć?  (Przeczytany 6697 razy)

Offline Radomiej

  • Użytkownik
    • Blog

# Marzec 30, 2013, 19:44:00
Witam, jestem w trakcie robienia biblioteki do konsoli. Napotkałem jednak dosyć poważny problem, konsola z C# jest bardzo wolna. Jeśli chcę narysować naraz kilkanaście linii tekstu to widać  jak znaki są rysowane. Dodając do tego jeszcze obsługę kolorów dla poszczególnych znaków zwalnia do prędkości żółwia. Jest sposób by ją jakość przyśpieszyć? np. bezpośrednie odwołanie do biblioteki od konsoli? czy nic się z tym za bardzo nie da zrobić?

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Kebab_u_Turka

  • Użytkownik

# Marzec 30, 2013, 20:29:23
W jaki sposób "wyrzucasz" coś do konsoli ?

Niemożliwe, żeby "wyrzucanie" dużej ilości danych do konsoli było wolne, coś musisz robić źle.

Offline Xirdus

  • Redaktor

# Marzec 30, 2013, 20:55:02
Problemem jest to, że funkcje obsługujące standardowe wyjście są wolne, dlatego trzeba jak najmniej razy je wywoływać i jak najwięcej wypisywać za jednym zamachem. Najprościej jest zaimplementować podwójne buforowanie: robisz tablicę 2D o wielkości okna konsoli i całe rysowanie robisz najpierw na tamtej tablicy, a potem jedną funkcją wypisujesz to wszystko na prawdziwą konsolę. Nie jestem jednak pewien, czy C# ma ku temu odpowiednie narzędzia - przynajmniej ja nie zauważyłem ich nigdzie tutaj. Natomiast jest to możliwe, i nawet proste, przy użyciu C/C++ i WinAPI - robisz tablicę 2D struktur typu CHAR_INFO i wypisujesz ją funkcją WriteConsoleOutput(). Jak chcesz, to przejrzyj sobie źródła mojej ruletki, gdzie tego właśnie użyłem, i efekt jest super (i nie wynika to tylko z faktu użycia C++ - jak robiłem Snake'a na początku swojej nauki, to też miałem problem z wolnym coutem - działo się dokładnie to, co opisałeś).

Offline Radomiej

  • Użytkownik
    • Blog

# Marzec 30, 2013, 22:45:36
No tak myślałem że im mniej wywołań tym lepiej. Ale z drugiej strony potrzebuję żeby istniała możliwość zmiany koloru tła i czcionki dla każdego znaku. Mój kod rysujący jest taki:
     
  public void DrawConsole()
        {
            for (int y = 0; y < sizeY; y++)
            {
                for (int x = 0; x < sizeX; x++)
                {
                    Console.BackgroundColor = bufforColorBackgroundMap[x, y];
                    Console.ForegroundColor = bufforColorForegroundMap[x, y];
                    if (x < sizeX - 1)
                    {
                        Console.Write(bufforCharMap[x, y]);
                    }
                    else
                    {
                        if (y != sizeY - 1)
                        {
                            Console.WriteLine(bufforCharMap[x, y]);
                        }
                        else
                        {
                            Console.Write(bufforCharMap[x, y]);
                        }
                    }
                }
            }
        }
Ale nie wiem jakby to zrobić żeby zachować daną funkcjonalność ale zarazem przyśpieszyć. Chyba faktycznie przerzucę się na C++ jeśli tutaj nie da rady jakoś tego problemu rozwiązać.

Offline Fiołek

  • Użytkownik
    • Blog

# Marzec 30, 2013, 23:00:11
Z System.Console wiele więcej nie wyciągniesz.

Żeby użyć WriteConsoleOutput nie musisz wcale używać C++ - możesz wykorzystać P/Invoke. CHAR_INFO ma prostą strukturę, więc można łatwo to przenieść do C#(czy to z pomocą Marshall czy z wykorzystaniem fixed pointerów i normalnych struktur). Wywołanie WriteConsoleOutput też jest dość proste. Zabawy będzie więcej niż przy C++, ale jeśli reszta kodu korzysta z dobrodziejstw C# to nie widzę sensu przechodzenia ;)

Offline ShadowDancer

  • Redaktor

# Marzec 31, 2013, 03:14:12
Och, na pewno w c# będzie szybciej i mniej bawienia się - z tego prostego powodu, że ktoś już to zrobił:
http://stackoverflow.com/questions/2754518/how-can-i-write-fast-colored-output-to-console

Offline Radomiej

  • Użytkownik
    • Blog

# Marzec 31, 2013, 12:24:35
Och, na pewno w c# będzie szybciej i mniej bawienia się - z tego prostego powodu, że ktoś już to zrobił:
http://stackoverflow.com/questions/2754518/how-can-i-write-fast-colored-output-to-console


To jest to czego bym potrzebował, ale przydałoby mi się jakieś objaśnienie jak działa parametr attribute?
Z tego co widzę da radę w nim zmienić tło i kolor czcionki ale jak zmodyfikować go modyfikować żeby mieć pełną paletę RGB tła i koloru czcionki?

Offline ShadowDancer

  • Redaktor

# Marzec 31, 2013, 14:17:38
AFAIK bez powershella nie możesz mieć pełnej palety barw w windowsowej konsoli.

Offline Xender

  • Użytkownik

# Marzec 31, 2013, 14:19:38
@Radomiej: Masz 2 opcje:

1. Użyć jakiegoś przeportowanego UNIX-owego terminala, który ma takie ficzery (a dodatkowo frytki do tego). Przy czym nie każdy z nich obsługuje 256 kolorów, a pełne RGB raczej nieliczne. Przy okazji będzie szybszy.
2. Napisać terminal na własne potrzeby. Przy okazji będzie szybszy. Możesz napisać dedykowany dla Twojej gry, lub uniwersalny - jakieś zaczepienie o tym drugim: http://xion.org.pl/2011/01/26/bo-konsola-to-tez-okno/.

Kolorów w Windowsowym terminalu jest 16, chociaż paletę można zdefiniować sammu (ale tylko od Visty wzwyż). http://gynvael.coldwind.pl/n/konsola_w_windowsie_kolory_pl_znaki.

@up: Ach, kiedy wy, Windowsowcy, nauczycie się rozróżniać, co jest zadaniem shella, a co terminala?...
« Ostatnia zmiana: Marzec 31, 2013, 14:22:52 wysłana przez Xender »

Offline Radomiej

  • Użytkownik
    • Blog

# Marzec 31, 2013, 16:14:43
Dobra poszukam może coś jest na C#, chociaż w sumie i te 16 kolorów być może starczy. Dzięki za pomoc.

Offline Xion

  • Moderator
    • xion.log

  • +1
# Marzec 31, 2013, 19:06:43
AFAIK bez powershella nie możesz mieć pełnej palety barw w windowsowej konsoli.
Psh to tylko shell, tj. zwykły program. To, jakie kolory można wyświetlać w "konsoli" to kwestia emulatora terminala, który używamy. Domyślnie i Psh i cmd.exe używa tego standardowego (zwanego dla niepoznaki właśnie 'konsolą') który oczywiście nie jest kompatybilny z ANSI terminalami.

Offline ShadowDancer

  • Redaktor

# Marzec 31, 2013, 21:48:42
Hmm, faktycznie, widocznie oprócz powershella instalowałem jakiś niestandardowy terminal.

Offline Radomiej

  • Użytkownik
    • Blog

# Kwiecień 02, 2013, 14:24:54
Mam jeszcze mały problem, ponieważ przy wyświetlaniu napisów z polskimi znakami w ich miejscu wyświetlają mi się inne znaki. Polskie znaki jednak są ale pod innymi wartościami. Stąd pytanie: jakie jest kodowanie c++ konsoli i czy mogę je łatwo zmienić z poziomu C#? czy może powinienem użyć klasy encoding z bibliotek C# żeby to przekonwenterować?

Offline Xender

  • Użytkownik

# Kwiecień 02, 2013, 15:24:22
No i jak to jest, że trzeba w jednym temacie 2 razy linkować ten sam artykuł? :P
http://gynvael.coldwind.pl/n/konsola_w_windowsie_kolory_pl_znaki

Powinieneś użyć UTF-8, czyli pod Windows strony kodowej 65001 - to jedyne słuszne, standardowe kodowanie (jeśli chcesz wiedzieć, dlaczego - http://kos.gd/2013/02/say-hello-to-unicode/). Więc SetConsoleOutputCP(65001); i jazda.

Przy czym kodowanie plików ze źródłem musi się zgadzać - czyli też UTF-8. Jeśloi z jakichś dziwnych powodów byłby to problem, to zostaje używać escape sequences w literałach.
« Ostatnia zmiana: Kwiecień 02, 2013, 15:28:32 wysłana przez Xender »

Offline Rolek

  • Użytkownik

# Kwiecień 02, 2013, 15:43:01
Powinieneś użyć UTF-8, czyli pod Windows strony kodowej 65001 - to jedyne słuszne, standardowe kodowanie (jeśli chcesz wiedzieć, dlaczego - http://kos.gd/2013/02/say-hello-to-unicode/). Więc SetConsoleOutputCP(65001); i jazda.
Jeśli nie interesuje Cię możliwość przekierowania wyjścia do pliku (a przy kolorowaniu konsoli zapewne nie), to możesz obsługiwać konsolę przy użyciu unicodowych(UTF-16) funckji dedykowanych do konsoli.