Sprawdzanie znaku na żywo w konsoli

0

Czy istnieje możliwość odczytania znaku w konsoli<ort> ,</ort> podając X i Y ?
Program wczytuje do konsoli na bieżąco znaki z pliku tekstowego<ort> ,</ort> ale dochodzą inne<ort> ,</ort> w zależności od ingerencji ort!. Najbardziej mi zależy<ort> ,</ort> aby sprawdzał<ort> ,</ort> czy jest "< >(różna)" od ' ' czyli spacji. powiem<ort> ,</ort>że jest to prosta gierka i XY będzie pobierany z położenia ludzika<ort> ,</ort> a dalsza część algorytmu będzie opisywała całego ludzika z O,|,/,. Procedura będzie sprawdzała<ort> ,</ort> czy w planszy (zbiorze znaków specjalnych czcionki Terminal)przed ludzikiem jest ścianka. Dałbym sobie z tym radę<ort> ,</ort> tylko to odczytywanie znaku w punkcie XY. Procedura wczytująca opiera się na kojarzeniu plik<ort> ,</ort> i poleceniu readln(plik ,String);

1
  1. Zrób tablicę w pamięci zawierającą to co wyświetlasz na ekran, sprawdzaj w tablice.
  2. http://msdn.microsoft.com/en-us/library/windows/desktop/ms684965%28v=vs.85%29.aspx
1

Chyba źle się do tego zabierasz; Jeśli dobrze zrozumiałem, to współrzędne ścian nigdzie nie są przechowywane, a Ty potrzebujesz sprawdzać co się znajduje w danym miejscu na ekranie konsoli; Nie powinieneś tego robić - dane o planszy musisz gdziesz przechowywać, najlepiej w macierzy dwuwymiarowej i do niej się odnosić, przy wykrywaniu kolizji; A ekran to ekran - ma jedynie wyświetlać obraz;

Opisany wyżej sposób zastosowałem w swojej (niedokończonej) grze SnakeASCII, dość dobrze się to obsługuje i działa wystarczająco szybko, by nie trzeba było narzekać.

0

Niby są przechowywane w pliku tekstowym jako "rysunek' , ALE położenie jako tylko znaki i program musiałby odczytywać je na bieżąco. Warto chyba jednak załadować ten rysuneczek do pamięci. gracz przesuwa planszę w prawo czy w lewo w menu , a algorytm usuwa odpowiednią ilość spacji lub je dodaje na początku każdej linii. Naciśnięcie klawisza J powoduje wyświetlenie za każdym cyklem pętli while(rysowanie planszy ,readkey) w pierwszej linijce danych takich jak życie , punkty , oraz pó. XY ludzika ,numer muzyki. To dodaje automatycznie jedną linijkę do współrzędnych .
Pytanie 2 : Jak programowo włączyć tryb pełnoekranowy [Alt] + [enter].
Pytanie 3 : Jak zmienić (i czy się da ?) rozmiar czcionki w bieżącym okienku
Pytanie 4 : Czy da się stworzyć timer w konsoli? Chciałbym , aby działał jako przerwanie (poruszanie przeciwnikiem ,etc...);
Stosuję bibliotekę CRT z Pascala.

1

Niby są przechowywane w pliku tekstowym jako "rysunek' , ALE położenie jako tylko znaki i program musiałby odczytywać je na bieżąco.

Chodzi właśnie o to, aby dane o ścianach i obiektach trzymać co najmniej w jednej macierzy; Dzięki temu ekran będzie służył jedynie do wyświetlania i nie będziesz musiał tracić czasu; A wszelkie operacje będą wykonywane w pamięci, więc będą szybkie;

Jeżeli Twoja plansza może być większa niż okno konsoli, to dodatkowo polecam skorzystać z dwóch zmiennych liczbowych, które określać będą lewy i górny offset; Z tych offsetów będzie korzystać procedura rysująca obiekty na ekranie, aby dokładnie wiedzieć który fragment mapy narysować w konsoli;

gracz przesuwa planszę w prawo czy w lewo w menu , a algorytm usuwa odpowiednią ilość spacji lub je dodaje na początku każdej linii.

Lepiej by było podać kod, niż go opisywać; Poważnie - opis niewiele daje, bo nie jest tak precyzyjny, jak kod;

Naciśnięcie klawisza J powoduje wyświetlenie za każdym cyklem pętli while(rysowanie planszy ,readkey) w pierwszej linijce danych takich jak życie , punkty , oraz pó. XY ludzika ,numer muzyki.

Tylko pamiętaj o tym, aby odrysowywać jedynie te fragmenty ekranu, które tego wymagają; Rysowanie po konsoli jest potwornie wolne, więc nie przerysowuj całego ekranu, bo będzie to trwało zbyt długo; W swojej grze przerysowuję dosłownie kilka znaków na całym ekranie w każdej klatce, więc całość działa bardzo płynnie - sam też tak powinieneś zrobić;

Pytanie 2 : Jak programowo włączyć tryb pełnoekranowy [Alt] + [enter].

Można zasymulować wciśnięcie tych klawiszy; Zobacz tutaj;

Pytanie 3 : Jak zmienić (i czy się da ?) rozmiar czcionki w bieżącym okienku

Fontu, nie czcionki; Zobacz tutaj - ja tego jeszcze nie testowałem, więc w razie czego dopytuj @vpiotr;

Pytanie 4 : Czy da się stworzyć timer w konsoli? Chciałbym , aby działał jako przerwanie (poruszanie przeciwnikiem ,etc...);
Stosuję bibliotekę CRT z Pascala.

Da się w bardzo prosty sposób, i to nawet kilka, działających "jednocześnie" :]

Za dużo było by tłumaczenia jak na post, więc pobierz sobie archiwum SnakeASCII_full_source.zip i zobacz jak to jest zaimplementowane; Klasa pojedynczego timera znajduje się w module Timer.pp, a używana jest w klasie TGame z modułu Game.pp; Zobacz jak główna pętla w metodzie TGame.Play używa tych dwóch liczników;

Ogólnie chodzi o to, że główna pętla zamraża program w każdej iteracji na 40ms; W każdej iteracji zostają także wywołane metody Step w dwóch timerach; Każdemu timerowi nadawana jest ilość klatek do odliczenia - im więcej klatek (więcej razy 40ms), tym dłużej trzeba czekać na odliczenie pełnego interwału; Aby sprawdzić, czy dany licznik doliczył już zadaną ilość klatek, należy skorzystać z metody ItsTime i jeśli zwróci True - można wykonać jakąś akcję;

Takich timerów możesz obsługiwać w jednej pętli i 20, a program nadal będzie jedno-wątkowy; To jest sposób podpatrzony z konstrukcji starych gier na Pegasusa - jest bardzo prosty do zrealizowania i dla prostej gry wystarczy;

0

Podaję kod odpowiedzialny za centrowanie :
-Korzysta on z procedury LOAD(deklarowana ręcznie) -odczytuje ona zawartość dokumentu aż do pustej lini (repeat i UNTIL):
PROCEDURA WCZYTUJACA- LOAD:

  procedure Load;
 var
  Plik : TextFile;  // nowa zmienna
  S : String;
begin
writeln('');
 // otworz plik
  AssignFile(Plik, plansza);
  Reset(Plik);

    repeat // petla
      Readln(Plik, S); // odczytaj plik
    writeln(horizontal+S); // dodaj linie ;-komentarz
    until S = ''; // jeżeli napotkasz na pusta linie zakończ działanie pętli
  CloseFile(Plik); // zamknij plik
   end;

Procedura USTAWIAJĄCA ŚRODEK(ręcznie):

 procedure modyf;
begin
while z<>'x' do
begin
crt.ClrScr;
SetConsoleTitle('TEXTMAN -Ustawienia');
{
//-------------TRYB PRŁNOEKRANOWY ALT + ENTER-----
 PostMessage(GetStdHandle(STD_OUTPUT_HANDLE), KF_ALTDOWN, 0, 0);
  PostMessage(GetStdHandle(STD_OUTPUT_HANDLE), 256, 0,integer(#13));
  PostMessage(GetStdHandle(STD_OUTPUT_HANDLE), 257, 0, integer(#13));
 PostMessage(GetStdHandle(STD_OUTPUT_HANDLE), KF_UP, 0, 0);
 PostMessage(GetStdHandle(STD_OUTPUT_HANDLE),  18, 0, 0); }
//------------------------------------------------
writeln('MODYFIKACJA GRY');
writeln('1.Centrowanie POZIOME');
writeln('Nacisnij prawy lub lewy klawisz.Ustaw środek');
crt.TextColor(11);
writeln('<- -> ,Q-podglad, X-koniec');
writeln('Ustawienia jakości obrazu : Z -niska jakość V -wysoka jakość');
crt.TextColor(12);
writeln(horizontal+'Ĺ');
Z:=crt.ReadKey;
crt.TextColor(7);
if z='q' then begin load; readkey; end;

if length(horizontal)<79 then if z='M' then horizontal:=horizontal+' '; //prawo dodaj spacje
if z='K' then Delete(horizontal, length(horizontal)-1, 1); //lewo  -usuń ostatni znak
if z='z' then crt.LowVideo;
if z='v' then crt.HighVideo;
end;
Z:=' '; //resetuj ,aby ostatni znak to nie x
end;

ostatnim znakiem nie może być po zakończeniu X , bo wtedy dojdzie do zakończenia gry.Dzięki temu cofamy się tylko z bieżących ustawień.
Zmienna horizontal (string) przechowuje łańcuch -spacje ,które dodawane są na początku lini menu , planszy , etc...

0

Ok ! Mam już jeden problem z głowy : tryb pełnoekranowy , jak widać miałem dobry tok myślenia -symulacja wciśnięcia klawiszy (kawałek błędnego kodu oznaczony jako komentarz) Wystarczyło :

        keybd_event(VK_MENU, MapVirtualKey(VK_MENU, 0), 0, 0);
        keybd_event(VK_RETURN, MapVirtualKey(VK_RETURN, 0), 0, 0);
        keybd_event(VK_RETURN, MapVirtualKey(VK_RETURN, 0), KEYEVENTF_KEYUP, 0);
        keybd_event(VK_MENU, MapVirtualKey(VK_MENU, 0), KEYEVENTF_KEYUP, 0); 

**DZIĘKI ! ** Aplikacja waży już sobie ok 400 KB :-) . Opanowałem kolorowanie pojedynczych znaków za pomocą CRTka , oddtwarzanie dźwięków WAW (rozszerzenie zmienione na MUS dla niepoznaki ) ,stworzę jeszcze z dwa zegary , nauczę przeciwnika iść w kierunku mnie (sprawdzanie pozycji mnie , wroga i ewentualna korekcja przez +1 / -1 XY)
Ma ktoś jeszcze pomysł , jak rozwiązać problem strzelania pociskami ? Nie chodzi tutaj czym , czy zmiana koloru , prosta animacja tylko o to jak tworzyć nowe zaraz po wystrzeleniu , żeby usser nie miał nad nim już kontroli. Lot jego to chyba na timerze trzeba zrobić , bo nie ma jak.

0

@programista97 - możesz pokazać zrzut tej gry? Bo póki co nie rozumiem w ogóle co chcesz osiągnąć; Czemu linie z pliku czytasz "na żywo", zamiast załadować sobie cały plik do pamięci?

0

Tak wygląda całość : sorry za jakość. W kodzie jak zwykle muszę zrobić porządek. Na szczęście , po ostatnich waszych namowach nauczyłem się pisać w miarę czytelnie kod , więc poprawki będą dotyczyły tylko usunięcia poleceń "serwisowych"( sprawdzających coś , które nie działały , etc) oznaczonych jako komenty oraz zrobienie odpowiednich wcięć.
Na żywo miało wczytywać z dwóch powodów : plansze miały być potężne (Ile Microsoft Windows wierszy i kolumn dał), więc aby nie zapychać pamięci , dwa to modyfikacja w czasie gry : naciśnięcie klawisza , zrobienie jakiejś czynności miało modyfikować planszę ( tworzenie drzwi , przejść , nowych pomieszczeń czy nawet rysowanie planszy podczas gry. Obawiałem się ,że gdy ktoś będzie to odpalał na małej ilości pamięci , to może strasznie mulić

1

No i co teraz potrzebujesz zrobić z tym wczytywaniem linii z pliku?

[...] więc poprawki będą dotyczyły tylko usunięcia poleceń "serwisowych"( sprawdzających coś , które nie działały , etc) oznaczonych jako komenty [...]

Nie rób tego komentarzami, bo za dużo z tym roboty... Polecam zrobić sobie prosty mechanizm logowania "serwisowych" informacji do pliku tekstowego; W tych miejscach, w których chcesz podglądnąć jakieś dane, wstaw instrukcje wpisujące wymagane dane do pliku; Na końcu zdefiniuj sobie symbol, np.:

{$DEFINE DEBUG_GAME}

i dyrektywami $IFDEF obejmij te linijki, np.:

{$IFDEF DEBUG_GAME}
LogData('[Coords] X: ', intX, ', Y: ', intY);
{$ENDIF}

Gdzie instrukcja LogData dopisuje nową linijkę do pliku logu, a zmienne intX i intY to współrzędne jakiegoś obiektu;

Takich symboli możesz utworzyć więcej, aby móc logować informacje tylko danego typu; Dzięki temu będziesz mógł włączyć/wyłączyć dane logowanie za pomocą zaremowania lub odblokowania definicji;

W źródłach RTL i LCL jest sporo zaremowanych intrukcji DebugLn; Wiadome - można ręcznie odblokowywać/blokować pojedyncze wywołania, jednak aby to zrobić ze wszystkimi - trzeba znaleźć wszystkie wywołania i coś z nimi zrobić.

0

Nie mam takich chyba poleceń , co musiałbym włączać i wyłączać - zostały stare śmieci przykład : z próby wywołania fullscreena ,nie udało się to dodałem to jako komentarz , aby dwa razy nie pisać ,jak znajdę błąd. Ale metoda jest genialna ! Dzięki , kiedyś ją wykorzystam ! No ! Kod wygląda coraz lepiej. Teraz już widać zagnieżdżone procedury ,instrukcje warunkowe. jeszcze z 30 minut i będzie czytelny , jak Michał Anioł namalował (nie chodzi o tego troyana :-) )

1

Teraz już widać zagnieżdżone procedury ,instrukcje warunkowe.

Unikaj zagnieżdżania procedur/funkcji, a tym bardziej zagnieżdżania wielopoziomowego; Zaletą jest oczywiście czytelność i wydzielenie "uniwersalnego" fragmentu kodu do zastosowań lokalnych, ale kompilator potrafi wygenerować przez to niezłą siekę, czasem mocno nieoptymalną; Choć wiadome - są przypadki, w których jest to sensowne i uzasadnione;

Najlepiej by było, gdybyś całość pisał obiektowo - podzielił kod na czytelne klasy, bez używania globalnych elementów, czy luźno deklarowanych procedur, rozległych typów itd.; Łatwiej Ci będzie zarządzać kodem, no i czytelność wzrośnie;

Możesz zobaczyć na kod mojej gry - tam mam wszystko rozdzielone na moduły, a konkretne elementy gry, jak np. obsługa rozgrywki, malowania ekranu, timerów itd. opakowane są w czytelne klasy; Łatwo się ich używa i łatwo się też je modyfikuje czy rozwija.

0

Oto kodzik. Upiększałem go ręcznie , po program do modelowania kodu uszkodził mi poprzedni , nie mniej jest o wiele czytelniejszy niż poprzednio :

 
program game;

{$APPTYPE CONSOLE}

uses
  SysUtils,windows,crt,MMSystem;

 var
        z:char; //przechowuje znak nac. klawisza
        horizontal,life, points, pasek, znak, plansza :string;
        x, x2, y, y2, metoda :byte; //metoda -metoda rysowania ludzika 0 lub 1;
        showbar, mute :boolean;
        muzyka :integer;

//////////////////////////////////////////////////////////////// K O D /////////////////////////////////////////////////////////////////
procedure FULLSCREEN;
begin
        keybd_event(VK_MENU, MapVirtualKey(VK_MENU, 0), 0, 0);
        keybd_event(VK_RETURN, MapVirtualKey(VK_RETURN, 0), 0, 0);
        keybd_event(VK_RETURN, MapVirtualKey(VK_RETURN, 0), KEYEVENTF_KEYUP, 0);
        keybd_event(VK_MENU, MapVirtualKey(VK_MENU, 0), KEYEVENTF_KEYUP, 0);
 end;



 procedure fizyka ;//główne procedury gry
begin
// UPS ! TUTAJ MIAŁY ZNALEŹĆ SIĘ POLECENIA ODNOŚNIE FIZYKI.
 end;



 procedure Load;
 var
        Plik : TextFile;  // nowa zmienna
        S : String;
begin
        writeln('');
        AssignFile(Plik, plansza);
        Reset(Plik);

repeat // petla
        Readln(Plik, S); // odczytaj plik
        writeln(horizontal+S); // dodaj linie ;-komentarz
until S = ''; // jeżeli napotkasz na pusta linie zakończ działanie pętli
        CloseFile(Plik); // zamknij plik
 end;



 procedure bar;
 begin
        TextColor(9); //jniebieski
        writeln('Life : '+life);
        GotoXY(length('Life : '+life)+10,1);
        TextColor(10);
        writeln('Points : '+points);
        GotoXY((length('Points : '+points)+length('Life : '+life)+20),1);
        TextColor(13);
        writeln('X_Y_KEY_MUSIC : '+inttostr(X)+'_'+inttostr(Y)+'_'+z+'_'+inttostr(muzyka));
        TextColor(7);//normalny
 end;



 procedure postac;
 begin

        if metoda=0 then  begin //podstawowa
                crt.TextColor(12);
                if showbar then begin
                        gotoXY(x+2,y+2);write('O');
                        gotoXY(x+1,y+3);write('/ł\');
                        gotoXY(x+2,y+4);write('/');
                        gotoXY(x+3,y+4);write('\');
                end else begin
                        gotoXY(x+2,y+1);write('O');
                        gotoXY(x+1,y+2);write('/ł\');
                        gotoXY(x+2,y+3);write('/');
                        gotoXY(x+3,y+3);write('\');
                        end;
                end;
        if metoda=1 then begin
                gotoXY(x+2,y+3);
                writeln('Ü');
                end;
        crt.TextColor(7);
 end;

  procedure postac2;
 begin
        if metoda=0 then  begin //podstawowa
        crt.TextColor(1);
        if showbar then begin
                 gotoXY(x2+2,y2+2);write('O');
                 gotoXY(x2+1,y2+3);write('/ł\');
                 gotoXY(x2+2,y2+4);write('/');
                 gotoXY(x2+3,y2+4);write('\');
        end else begin
                 gotoXY(x2+2,y2+1);write('O');
                 gotoXY(x2+1,y2+2);write('/ł\');
                 gotoXY(x2+2,y2+3);write('/');
                 gotoXY(x2+3,y2+3);write('\');
                 end;
        end;
 if metoda=1 then begin
        gotoXY(x+2,y+3);
        writeln('Ü');
        end;
 TextColor(7);
 end;


 procedure audio;
 begin
        while z<>'x' do begin
                Z:=crt.ReadKey;
                TextColor(15);
                clrscr;
                writeln(horizontal+'Glosnosc dla WAV zmien : +/- , M-off/on mute');
                if NOT mute then writeln(horizontal+'ł'+pasek) else writeln('ł');
                gotoxy(52,2);
                writeln('ł');
                gotoxy(0,0);

                if z='=' then if length(pasek)<51 then pasek:=pasek+'Ű';
                if z='-' then if length(pasek)>0 then Delete(pasek, length(pasek)-1, 1);//usun ostatni znak
                if z='m' then if mute  then mute:=false else mute:=true;

                if NOT mute then waveOutSetVolume(WAVE_MAPPER, Integer((length(pasek)*5 shl 24) or (length(pasek)*5 shl 8))) else
                waveOutSetVolume(WAVE_MAPPER, Integer((0 shl 24) or (0 shl 8)));
                end;
 textColor(7);
 z:=' ';
 end;


 procedure setmusic; //procedura ustawiająca aktualną melodię
 begin
        if NOT mute then begin
        if muzyka=0 then PlaySound('music4.mus', 0, SND_ASYNC or SND_LOOP);
        if muzyka=1 then PlaySound('music3.mus', 0, SND_ASYNC or SND_LOOP);
        if muzyka=2 then PlaySound('music2.mus', 0, SND_ASYNC or SND_LOOP);
        if muzyka=3 then PlaySound('music1.mus', 0, SND_ASYNC or SND_LOOP);
        end;
 end;
 //--------------KOD GRY------------------------------------
 procedure gra;
 begin
        setmusic;
        while z<>'x' do begin
                clrscr;
                if showbar then bar;
                load;
                postac;
                postac2;
                z:=readkey;
               ////////////////ograniczenia obszarow konsoli , po któerych można się poruszać////////////////

                if x<75 then if z='M' then x:=x+1;
                if x>0 then if z='K' then x:=x-1;
                if y<21 then if z='P' then y:=y+1;
                if y>0 then if z='H' then y:=y-1;  //ograniczenie o rozmiarów konsoli dla ludzika 1

                if x2<75 then if z='d' then x2:=x2+1;
                if x2>0 then if z='a' then x2:=x2-1;
                if y2<21 then if z='s' then y2:=y2+1;
                if y2>0 then if z='w' then y2:=y2-1;  //ograniczenie o rozmiarów konsoli dla ludzika 2

                if z='j' then if showbar then showbar:=false else showbar :=true; //pokaż ukryj pasek
                if z='Q' then if muzyka>0 then muzyka:=muzyka-1; //pagedown - zmień na poprzednią melodię
                if z='I' then if muzyka<3 then muzyka:=muzyka+1; //pageup -zmień na następną melodię
                if ((z='Q') or (z='I')) then  setmusic; //jeśli naciśnięto pagedown lub pageup ,to zacznij oddtwarzanie melodii /przerwij odtwarzanie bierzącej

                if z='t' then if plansza='plansza2.txt' then  plansza:='plansza.txt' else plansza:='plansza2.txt'; //zmaina planszy
                if z='b' then FullScreen; //włacz pełny ekran

                end;
 z:=' '; //reset ostatniego, naciśniętego klawisza - znaku
end;
 //------------------------KONIEC KODU GRY--------------------------------

procedure modyf;
begin
        while z<>'x' do begin
                ClrScr;
                SetConsoleTitle('TEXTMAN -Ustawienia');
                writeln('MODYFIKACJA GRY');
                writeln('1.Centrowanie POZIOME');
                writeln('Nacisnij prawy lub lewy klawisz.Ustaw środek');
                TextColor(11);
                writeln('<- -> ,Q-podglad, X-koniec');
                writeln('Ustawienia jakości obrazu : Z -niska jakość V -wysoka jakość');
                TextColor(12);
                writeln(horizontal+'Ĺ');
                Z:=crt.ReadKey;
                TextColor(7);
                if z='q' then begin
                        load;
                        readkey;
                        end;

                if length(horizontal)<79 then if z='M' then horizontal:=horizontal+' '; //prawo dodaj spacje
                if z='K' then Delete(horizontal, length(horizontal)-1, 1); //lewo  -usuń ostatni znak
                if z='z' then crt.LowVideo;
                if z='v' then crt.HighVideo;
        end;
Z:=' '; //resetuj ,aby ostatni znak to nie x
end;


 procedure configmenu;
 begin
        while z<>'x' do begin
                clrscr;
                SetConsoleTitle('TEXTMAN -Main menu');
                writeln(horizontal+'ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»');
                writeln(horizontal+'ş------------->CONFIGURATION<-------------ş');
                writeln(horizontal+'ĚÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍą');
                writeln(horizontal+'ş               CONFIG MENU               ş');
                writeln(horizontal+'ČÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍĽ');
                TextColor(9);
                writeln(horizontal+'         '+'ÉÍÍ»');
                writeln(horizontal+'         '+'ş 1ş- Ustawienia audio');
                writeln(horizontal+'         '+'ČÍÍĽ');
                TextColor(10);
                writeln(horizontal+'         '+'ÉÍÍ»');
                writeln(horizontal+'         '+'ş 2ş- Ustawienia grafiki');
                writeln(horizontal+'         '+'ČÍÍĽ');
                TextColor(14);
                writeln(horizontal+'         '+'ÉÍÍ»');
                writeln(horizontal+'         '+'ş Xş- Wyjscie');
                writeln(horizontal+'         '+'ČÍÍĽ');
                TextColor(7);
                Z:=crt.ReadKey;

                if z='1' then audio ;
                if z='2' then modyf ;
        end;
 z:= ' ';
 end;
////////////////////////B O O T   GRY//////////////////////////////////////
begin
        SetConsoleTitle('TEXTMAN');
        windows.beep(300,100);
        windows.beep(400,100);
        windows.beep(300,100);
        windows.beep(400,100);
        windows.beep(500,50);
        windows.beep(300,50);
        writeln('Witamy w GRZE. Copyright by ');
        GotoXY(29 ,1);
        TextColor(12);
        writeln('Adam Xxxxxx');
        GotoXY(0 ,2);
        TextColor(7);
        writeln('Press ');
        GotoXY(7 ,2);
        TextColor(11);
        writeln('enter ');
        GotoXY(14 ,2);
        TextColor(7);
        writeln('to continue...'); //kolorowanie tekstu
        readln;

////////////////////////////////////   ustawienia poczatkowe  ///////////////
        pasek:='ŰŰŰŰŰŰŰŰŰŰŰŰŰŰŰŰŰŰŰŰ'; //głośność 50 %
        plansza:='plansza.txt'; //pierwsza plansza
        life:='*****';  //życie
        x:=29+length(horizontal);
        y:=10;
        x2:=11+length(horizontal);
        y2:=20;     //położenie ludzikow
        metoda:=0;  //metoda obrazowania ludzikow
        horizontal:='                     '; //centrowanie
        points:='0';  //ustawienia początkowe
        showbar:=false; //nie pokazuj na poczatku paska
////////////////////////////////////////////

        waveOutSetVolume(WAVE_MAPPER, Integer((100 shl 24) or (100 shl 8))); //ustaw glośńóść na ok 50 %
        PlaySound('music5.mus', 0, SND_ASYNC or SND_LOOP); //odtworz muzykę dla menu
        while ((z<>'s') or (z<>'a') or (z<>'x')) do begin
                if NOT mute then if z=' ' then PlaySound('music5.mus', 0, SND_ASYNC or SND_LOOP);
                ClrScr;
                SetConsoleTitle('TEXTMAN -Main menu');
                writeln(horizontal+'ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»');
                writeln(horizontal+'ş------------->TEXTMAN<-------------ş');
                writeln(horizontal+'ĚÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍą');
                writeln(horizontal+'ş             MAIN MENU             ş');
                writeln(horizontal+'ČÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍĽ');
                TextColor(10);
                writeln(horizontal+'         '+'ÉÍÍ»');
                writeln(horizontal+'         '+'ş Sş- Start Gry');
                writeln(horizontal+'         '+'ČÍÍĽ');
                TextColor(14);
                writeln(horizontal+'         '+'ÉÍÍ»');
                writeln(horizontal+'         '+'ş Aş- Ustawienia Gry');
                writeln(horizontal+'         '+'ČÍÍĽ');
                TextColor(9);
                writeln(horizontal+'         '+'ÉÍÍ»');
                writeln(horizontal+'         '+'ş Xş- Wyjscie');
                writeln(horizontal+'         '+'ČÍÍĽ');
                TextColor(7);
                Z:=crt.ReadKey;

                if z='s' then GRA ;
                if z='a' then configmenu ;
                if z='x' then exit ;
        end;


end.

niestety -zrobiłem już paczkę z grą , ale jet duuużo większa niż 20MB , -głównie muzyka najwięcej zajmuje
O ! Program nie zajmuje już 400 KB tylko 57 KB :O

0

A co do ASCI wężyka to ekstra gra ! Szacun !

0

To jeszcze nie jest gra - póki co można sztywną rozgrywkę zagrać; Wszystko jest obsługiwane - sterowanie wężem, łapanie złotka, wydłużanie, obsługa przechodzenia przez moduły, w których było złapane złotko, tryb turbo (tymczasowy i trwały), liczenie czasu w sekundach; Jednak docelowo ma wyglądać jak normalna gra - menu, lista graczy, różne tryby rozgrywki, zapisywanie wyników i inne bajery;

Jednak aby móc skompilować kod u siebie, trzeba dodać do projektu paczkę do obsługi plików TreeStructInfo - paczkę ze stabilnym API pobrać można stąd; Jeszcze wiele w tej grze będzie kiedyś dodane, ale potrzebuję czasu; A jak wiadomo, wolnego czasu zawsze zbyt mało.

0

czasu to każdy (a może nie ?) ma za mało. Menu to pikuś w porównaniu z samą grą.
-Co więc sądzisz o kodzie ? procedurę odtwarzania muzyki możesz wyłączyć i grę skompilować , albo ja ją skompiluję , bo nie zajmuje już więcej niż 59 KB więc jako załącznik spokojnie przejdzie.

1

-Co więc sądzisz o kodzie ?

Hmm... Kod jest typowo proceduralny, momentami nieoptymalny;

Sugerowałem Ci wcześniej, abyś wszystko opakował w klasy - gra stricte obiektowa będzie łatwiejsza w zarządzaniu i rozwijaniu; Poza tym kod nie jest sformatowany, do tego zawiera zarówno polskie, jak i angielskie identyfikatory, a to błąd; Wybierz jeden język (najlepiej angielski) i wszystko w nim nazywaj; Do tego wstawiasz komentarze, które opisują czym jest kod, zamiast oznaczać co gdzie jest; Na przykład tu:

repeat // petla
        Readln(Plik, S); // odczytaj plik
        writeln(horizontal+S); // dodaj linie ;-komentarz
until S = ''; // jeżeli napotkasz na pusta linie zakończ działanie pętli
        CloseFile(Plik); // zamknij plik

Opisujesz w komentarzach coś, co jest oczywiste;


Jeśli chodzi o inne kawałki kodu, to niedocięgnięć wcale nie jest tak mało; Ale może po kolei;

uses
  SysUtils,windows,crt,MMSystem;
 
 var
        z:char; //przechowuje znak nac. klawisza
        horizontal,life, points, pasek, znak, plansza :string;
        x, x2, y, y2, metoda :byte; //metoda -metoda rysowania ludzika 0 lub 1;
        showbar, mute :boolean;
        muzyka :integer;

Góra zmiennych globalnych... Nie może tak być - opakuj wszystko w klasy i używaj ich pól, a w metodach tylko zmiennych lokalnych (ewentualnie pól klasy i stałych); Stałe mogą być globalne, ale pod warunkiem, że będą używane w całej aplikacji, lub przynajmniej w kilku jej modułach; Poza tym identyfikatory znów w róznych językach;


procedure FULLSCREEN;

Powinieneś ją nazwać SetConsoleFullScreen; Przyjęło się, że samymi wielkimi literami nazywa się tylko i wyłącznie stałe; Poza tym polecam Ci używać pustych nawiasów w przypadku procedur, funkcji lub metod, które nie posiadają parametrów; Dzięki temu od razu widać, która instrukcja to procedura/funkcja/metoda, a które to zmienne; I jeszcze jedna rzecz - nazwy procedur, funkcji i metod powinny w pierwszym członie zawierać czasownik, np. Set*, Get*, Add*, Remove*, Init* itd.; To pozwoli po samej nazwie zrozumieć co "podprogram" wykonuje;


procedure Load;
{...}
repeat // petla
        Readln(Plik, S); // odczytaj plik
        writeln(horizontal+S); // dodaj linie ;-komentarz
until S = ''; // jeżeli napotkasz na pusta linie zakończ działanie pętli
        CloseFile(Plik); // zamknij plik
 end;

Tego typu operacje powinieneś umieścić w bloku Try Finally, aby zabezpieczyć się przed ewentualnymi wyciekami pamięci, w przypadku zaistnienia wyjątku wewnątrz pętli;


 procedure bar;
 begin
        TextColor(9); //jniebieski
        writeln('Life : '+life);
        GotoXY(length('Life : '+life)+10,1);
        TextColor(10);
{...}

Używasz cyferek do ustawienia kolorów, które nie wiadomo jaki kolor określają; Korzystaj ze zdefiniowanych stałych, np. Blue, White, Yellow itd.; Wszystkie te stałe zadeklarowane są w module Crt;


procedure postac;
 begin
 
        if metoda=0 then  begin //podstawowa
                crt.TextColor(12);
                if showbar then begin
                        gotoXY(x+2,y+2);write('O');
                        gotoXY(x+1,y+3);write('/ł\');
                        gotoXY(x+2,y+4);write('/');
                        gotoXY(x+3,y+4);write('\');
                end else begin
                        gotoXY(x+2,y+1);write('O');
                        gotoXY(x+1,y+2);write('/ł\');
                        gotoXY(x+2,y+3);write('/');
                        gotoXY(x+3,y+3);write('\');
                        end;
                end;
        if metoda=1 then begin
                gotoXY(x+2,y+3);
                writeln('Ü');
                end;
        crt.TextColor(7);
 end;

Źle formatujesz kod, łamiesz zasadę DRY, nie korzystasz z instrukcji wyboru Case, poza tym nazwa procedury kompletnie nic nie mówi jej przeznaczeniu; Możesz tę procedurę napisać w ten sposób:

procedure DrawHero();
var
  intOffset: Byte;
begin
  case metoda of // nazwij tę zmienną sensowniej
    0: begin
         TextColor(12); // tu użyj stałej
         intOffset := Byte(Boolean(ShowBar)) + 1;

         GoToXY(X + 2, Y + intOffset + 1); Write('O');
         GoToXY(X + 1, Y + intOffset + 2); Write('/ł\');
         GoToXY(X + 2, Y + intOffset + 3); Write('/');
         GoToXY(X + 3, Y + intOffset + 3); Write('\');
       end;
    1: begin
         GoToXY(X + 2, Y + 3);
         WriteLn('Ü');
       end;
  end;

  TextColor(7); // użyj stałej
end;

W przypadku procedury postac2 zrób to samo, albo połącz te dwie procedury w jedną, bo różni je jedynie kolor, ustawiany na początku;


procedure audio;
{...}
if z='=' then if length(pasek)<51 then pasek:=pasek+'Ű';
if z='-' then if length(pasek)>0 then Delete(pasek, length(pasek)-1, 1);//usun ostatni znak
if z='m' then if mute  then mute:=false else mute:=true;

Użyj instrukcji wyboru, bo za każdym razem i tak wszystkie warunki są sprawdzane - trzy razy sprawdzasz wartość zmiennej z i nigdzie nie masz Else, więc cała drabinka jest sprawdzana;


procedure setmusic; //procedura ustawiająca aktualną melodię
 begin
        if NOT mute then begin
        if muzyka=0 then PlaySound('music4.mus', 0, SND_ASYNC or SND_LOOP);
        if muzyka=1 then PlaySound('music3.mus', 0, SND_ASYNC or SND_LOOP);
        if muzyka=2 then PlaySound('music2.mus', 0, SND_ASYNC or SND_LOOP);
        if muzyka=3 then PlaySound('music1.mus', 0, SND_ASYNC or SND_LOOP);
        end;
 end;

To da się mocno skrócić:

procedure SetMusic();
begin
  if not Mute then
    PlaySound(Format('music%d.mus', [4 - Muzyka]), 0, SND_ASYNC or SND_LOOP);
end;

Magia...


procedure gra;
{...}
if x<75 then if z='M' then x:=x+1;
if x>0 then if z='K' then x:=x-1;
if y<21 then if z='P' then y:=y+1;
if y>0 then if z='H' then y:=y-1;  //ograniczenie o rozmiarów konsoli dla ludzika 1
 
if x2<75 then if z='d' then x2:=x2+1;
if x2>0 then if z='a' then x2:=x2-1;
if y2<21 then if z='s' then y2:=y2+1;
if y2>0 then if z='w' then y2:=y2-1;  //ograniczenie o rozmiarów konsoli dla ludzika 2
 
if z='j' then if showbar then showbar:=false else showbar :=true; //pokaż ukryj pasek
if z='Q' then if muzyka>0 then muzyka:=muzyka-1; //pagedown - zmień na poprzednią melodię
if z='I' then if muzyka<3 then muzyka:=muzyka+1; //pageup -zmień na następną melodię
if ((z='Q') or (z='I')) then  setmusic; //jeśli naciśnięto pagedown lub pageup ,to zacznij oddtwarzanie melodii /przerwij odtwarzanie bierzącej
 
if z='t' then if plansza='plansza2.txt' then  plansza:='plansza.txt' else plansza:='plansza2.txt'; //zmaina planszy
if z='b' then FullScreen; //włacz pełny ekran
{...}

Znowu - użyj instrukcji Case... Poza tym do inkrementacji używaj Inc, a do dekrementacji Dec; No i taką konstrukcję:

if showbar then showbar:=false else showbar :=true;

można zamienić na prostą negację:

ShowBar := not ShowBar;

Krócej, prościej i szybciej;


procedure modyf;
{...}
if z='q' then begin
  load;
  readkey;
end;
 
if length(horizontal)<79 then if z='M' then horizontal:=horizontal+' '; //prawo dodaj spacje
if z='K' then Delete(horizontal, length(horizontal)-1, 1); //lewo  -usuń ostatni znak
if z='z' then crt.LowVideo;
if z='v' then crt.HighVideo;
{...}

Znowu Case czeka na użycie;


procedure configmenu;
{...}
writeln(horizontal+'ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»');
writeln(horizontal+'ş------------->CONFIGURATION<-------------ş');
writeln(horizontal+'ĚÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍą');
writeln(horizontal+'ş               CONFIG MENU               ş');
writeln(horizontal+'ČÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍĽ');
TextColor(9);
writeln(horizontal+'         '+'ÉÍÍ»');
writeln(horizontal+'         '+'ş 1ş- Ustawienia audio');
writeln(horizontal+'         '+'ČÍÍĽ');
TextColor(10);
writeln(horizontal+'         '+'ÉÍÍ»');
writeln(horizontal+'         '+'ş 2ş- Ustawienia grafiki');
writeln(horizontal+'         '+'ČÍÍĽ');
TextColor(14);
writeln(horizontal+'         '+'ÉÍÍ»');
writeln(horizontal+'         '+'ş Xş- Wyjscie');
writeln(horizontal+'         '+'ČÍÍĽ');
TextColor(7);
{...}

Wpakuj te literały do macierzy i wyświetlaj w pętlach;


windows.beep(300,100);
windows.beep(400,100);
windows.beep(300,100);
windows.beep(400,100);
windows.beep(500,50);
windows.beep(300,50);

Te wartości także - zadeklaruj macierz dwuwymiarową i wywołuj procedurę Beep w pętli;


while ((z<>'s') or (z<>'a') or (z<>'x')) do begin

Korzystaj ze zbiorów:

while not (z in ['s', 'a', 'x']) do

Poza tym używasz literałów, więc nie będzie możliwości zmiany klawiszy sterowania;


if NOT mute then if z=' ' then PlaySound('music5.mus', 0, SND_ASYNC or SND_LOOP);

Łącz warunki, zamiast tworzenia osobnych instrukcji warunkowych:

if (not Mute) and (z = '') then
  PlaySound('music5.mus', 0, SND_ASYNC or SND_LOOP);

if z='s' then GRA ;
if z='a' then configmenu ;
if z='x' then exit ;

Znowu **Case**a brakuje;


No i ciągle używasz dwóch instrukcji - GoToXY w połączeniu z Write; Stwórz sobie procedurę, która będzie od razu przenosić kursor w odpowiednie miejsce i wyświetlać tekst:

procedure DrawText(AX, AY: Byte; const AText: String);
begin
  GoToXY(AX, AY);
  Write(AText);
end;

Ewentualnie przyjmuj jeszcze w parametrze kolory tekstu i tła; Choć lepiej by było zaklearować drugą taką procedurę, i ją przeładować:

procedure DrawText(AX, AY: Byte; const AText: String); overload;
procedure DrawText(AX, AY: Byte; const AText: String; ATextColor, ABackColor: Byte); overload

To na początek tyle - wszystkiego nie sposób opisać w jednym poście :]

0

No sporo niedociągnięć , ale tutaj po to właśnie jestem , aby ktoś dobrze mi podpowiedział. Myślę że jak wszystko poprawię , to wielkość programu będzie tak mała , że można by się pokusić ,żeby ją wgrać do jakiegoś procka :-) . Przede mną sporo jeszcze nauki.

0

Myślę że jak wszystko poprawię , to wielkość programu będzie tak mała , że można by się pokusić ,żeby ją wgrać do jakiegoś procka

Do jakiego procka? Masz na myśli jakiś mikrokontroler? Co prawda jest mikroPASCAL, więc można pisać w Pascalu i takie programy; Ale nie robiłem tego nigdy - jakiś czas temu poczytałem trochę z ciekawości.

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