Własne rekordy w MMF

Klikipedia - klikowa encyklopedia
Skocz do: nawigacji, wyszukiwarki
Slimaczek.jpg
Pierwotna wersja tego artykułu pochodzi z 7. numeru Ślimaczka (zobacz oryginalny artykuł).


Autor.jpg
Autorem tego artykułu jest
sulge

Czy zastanawiałeś się kiedyś jak zrobić własną listę rekordów, która nie miałaby ograniczeń standardowego obiektu "Hi-Score"? Jeśli tak, to ten kurs jest właśnie dla Ciebie. Uprzedzam, że cały przykład będzie wykonany w MMF, ale będzie można go z powodzeniem przerobić pod TGF. Wystarczy zamiast standardowego obiektu "Array" użyć "Dynamic Array" i "Fast Loop object" dostępnych w TGF.

Wprowadzenie

Na początku zastanówmy się, czym jest lista rekordów, czyli tzw. założenia wstępne. A więc zadaniem listy rekordów jest przechowywanie wyników uzyskiwanych przez graczy. Innymi słowy jest to ranking wyników z gry, który przechowuje najczęściej imię gracza i jego wynik, oraz inne informację o rekordzie. Co więcej lista ta przechowuje jedynie ściśle określoną ilość tych rekordów i aby się dostać na nią musi się uzyskać jakiś dość wysoki wynik. Kolejną bardzo ważną cechą rankingu wyników jest to, że wyniki są posortowane, czyli ułożone w odpowiedniej kolejności w zależności od uzyskiwanego wyniku. Z reguły jest to porządek malejący tzn., że rekord o wyższym wyniku jest wyżej na liście niż rekord o niższym wyniku. Rekordy te są pamiętane nawet po wyłączeniu gry. Oczywiście jedyną metodą zapamiętywania rekordów jest ich zapis w pliku. Aby uniemożliwić ingerencję i manipulację wynikami, przez graczy, plik ten powinien być zakodowany.

Założenia

Jak łatwo zauważyć standardowe "Hi-Score" nie spełnia kilku z naszych założeń. Miedzy innymi pozwala jedynie na przechowanie imienia gracza i jego wyniku i tylko tych dwóch informacji, a przecież czasem przydałaby się jeszcze informacja o rundzie, w której gracz zakończył grę, czy dacie ustanowienia wyniku. Dalej, rekordy przechowywane są w pliku INI, który nie jest w żaden sposób zabezpieczony, co umożliwia oszustwa, które oczywiście nie mają większego sensu. I dodatkowo możemy maksymalnie przechowywać tylko 20 rekordów.

Stworzona przez nas lista rekordów pozbawiona będzie wszystkich tych wad standardowego "Hi-Score". Oczywiście największym problemem w MMF jest sortowanie rekordów. Znanych jest wiele algorytmów sortowania. Niektóre z nich można z powodzeniem wykorzystać w MMF inne nie. My użyjemy najprostszej metody "sortowania bąbelkowego", moglibyśmy użyć innych szybszych metod jak choćby "sortowania przez wstawianie", czy "sortowanie przez kopcowanie", ale przy założeniu, że nasze rekordy będą przechowywane w tablicach, a naraz wstawiać będziemy 1 rekord wszystkie te metody mają podobną złożoność obliczeniową. Oczywiście istnieją inne szybsze metody sortowania jak choćby "sortowanie szybkie", które w większości przypadków jest najszybszym algorytmem sortowania. Jednak w MMF użycie tego algorytmu jest skomplikowane.

Trochę teorii

Tak jak wcześniej napisałem do posortowania listy rekordów użyjemy najprostszego algorytmu sortowania, "sortowania bąbelkowego". Omówię w skrócie, na czym polega ten algorytm. Załóżmy, zatem, że mamy jakąś przypadkową listę liczb np.: 4, 9, 1, 4, 5 którą chcemy posortować malejąco. Algorytm, bąbelkowy "postępuje" następująco sprawdza czy 5 liczba jest większa, od 4 jeśli tak zamienia je miejscami, w przeciwnym wypadku przechodzi dalej (u nas 4, 9, 1, 5, 4) następnie sprawdza 4 z 3 (u nas 4, 9, 5, 1, 4), 3 z 2 (u nas 4, 9, 5, 1, 4), 2 z 1 (u nas 9, 4, 5, 1, 4) jak widać po pierwszym wykonaniu takiej pętli lista nie jest posortowana, aby była posortowana należałoby tę samą operacje powtórzyć 4 razy (w ogólnym przypadku n-1 razy, jeśli za n przyjmiemy ilość elementów w liście). Należy jednak zauważyć, że element maksymalny jest na pierwszym miejscu już po pierwszym wykonaniu szeregu powyższych operacji, a to nam wystarczy w zupełności, bo dodawać będziemy po 1 rekordzie, czyli w chwili dodawania rekordu nasza lista będzie posortowana. Nasza lista rekordów na początku będzie pusta, (czyli np. 0, 0, 0, 0, 0), później będziemy dodawać jakiś rekord, (np. 4), zrobimy to w taki sposób, że sprawdzimy czy ostatni element listy jest mniejszy od tego, który chcemy wstawić, jeśli tak to na jego miejsce wstawimy nasz wynik (u nas 0<4, czyli 0, 0, 0, 0, 4) i wywołamy nasz algorytm sortowania bąbelkowego, czyli porównujemy 5 z 4 (0, 0, 0, 4, 0), 4 z 3 (0, 0, 4, 0, 0), 3 z 2 (0, 4, 0, 0, 0), 2 z 1 (4, 0, 0, 0, 0) jak widać nasz wynik znajduje się na początku, czyli tam gdzie powinien:). Nie ma sensu wykonywania jeszcze 3 razy tych samych czynności, bo nic to by nie zmieniło. Aby lepiej zrozumieć ten algorytm do obecnej naszej listy (4, 0, 0, 0, 0) wstawimy liczbę 2, czyli porównujemy 0<2, więc (4, 0, 0, 0, 2) i wykonujemy, algorytm sortowania bąbelkowego. Porównujemy 5 z 4 (4, 0, 0, 2, 0), 4 z 3 (4, 0, 2, 0, 0), 3 z 2 (4, 2, 0, 0, 0) i 2 z 1 (4, 2, 0, 0, 0) dwójka jest mniejsza, od 4 więc nie zamieniamy ich miejscami. Myślę, że po tym przykładzie zrozumiałeś algorytm sortowania bąbelkowego i całą ideę naszej listy rekordów. Teraz pozostał jedynie problem jak to przełożyć na zdarzenia w MMF, ale ten problem pozostawiam tobie .

Jak to zakodować?

W MMF do przechowywania rekordów nie użyjemy listy, a jednowymiarowych tablic, obiektów "Array". Dlaczego użyłem formy mnogiej tablic? Ponieważ nasze rekordy nie będą jedynie suchymi wynikami, bo nie miałoby to większego sensu. Do każdego wyniku będzie przypisane imię, data uzyskania wyniku i numer rundy, w której gracz zakończył grę. Tak, więc każdy rekord składać będzie się z 4 pól (imię, wynik, nr rundy, data), czyli do przechowania naszej listy rekordów użyjemy 4 tablic jednowymiarowych. Pewnie niektórzy z was zadają sobie pytanie: "no oki, ale co to jest ta tablica jednowymiarowa?" więc już wyjaśniam. Tablica jednowymiarowa to tak jakby (sorry, że przypominam o szkole) lista z dziennika, każdy wpis to imię i nazwisko, opatrzone indeksem, lub, jeśli ktoś woli numerem,. Tzn., jeśli np. Alojzy Kleks ma w dzienniku numer 5, to, jeśli chcemy się go pozbyć to wynajmując mordercę powiemy zabij osobę o numerze 5 (operowanie tu nazwiskami jest nie na miejscu), co on zrozumie jako zabij Kleksa:) Podobnie jest z obiektem "Array" w MMF, też składa się on z elementów tego samego typu (albo tekst, albo liczb), które mają swoje indeksy (numery).

Graficznie przedstawię przykładową tablicę "imiona":

INDEX 1 2 3 4 5
imię Jacek Adam Ambroży Stefan Polek

Aby na przykład imię o indeksie jeden wstawić do obiektu "string" po naciśnięciu klawisza "Enter" w MMF wystarczy wstawić następujące zdarzenie:

Jeszcze słowem wstępu
N Zdarzenia
1
+ EZ-keyboard.png Uppon pressing ENTER
EZ-string.png string set alterable string to StrAtX("imiona",1)

Po takiej akcji w obiekcie "string" zostanie wyświetlony napis "Jacek". Sorry za trochę przydługawe wyjaśnienie, ale bez poprawnego zrozumienia obsługi tablic w MMF cały kurs byłby dla was nie zrozumiały.

Realizacja

Utwórzmy nowy poziom "Rekordy" i edytujmy go wstawiając niezbędne obiekty.

Cztery obiekty tablic "Array" o nazwach "imiona", "wyniki", "rundy", "daty" do tych obiektów będziemy wczytywać rekordy i wykonywać operacje sortowania. "Binary object" dzięki temu obiektowi zapiszemy nasze rekordy do pliku po wcześniejszym ich zakodowaniu. Dziewięć obiektów edycji "Edit" z których 4 o nazwach "imie", "wynik", "runda", "data" posłużą do dodawania nowego rekordu, a 5 pozostałych o nazwach "Lpozycje", "Limiona", "Lwyniki", "Lrundy", "Ldaty" do prezentacji naszej listy rekordów. Obiekt "Custom Scrollbar", który posłuży nam do wykonania własnego paska przewijania (własnego czyt. z niestandardową grafiką). Cztery obiekty "Active System Box" o nazwach "Decrease", "Scroller", "Background", "Increase" posłużą do graficznego przedstawienia paska przewijania. Dwa liczniki, obiekty "counter" o nazwach "pom" i "ile_rekordow". Dwa obiekty "string" o nazwach "pom2" i "enter". I wreszcie 2 standardowe przyciski "Button" o nazwach "Dodaj rekord", "reset".

Zalecam abyście pozmieniali nazwy obiektów na takie, jakich ja używam będzie wam potem łatwiej .

Edytujemy obiekty tablic. Parametry tablic "imiona" i "daty" ustawiamy w następujący sposób:

rekordy1.gif

(chodzi tu o to, że dane, przechowywane w komórkach tych tablic będą tekstem)

A parametry tablic "wynik" i "runda" tak:

rekordy2.gif

Edytujemy tekst obiektu "enter" wstawiając do niego znak nowej linii (po prostu usuwamy cały tekst i klikamy enter, kursor przeskoczy do nowej linii i właśnie oto nam chodziło, zatwierdzamy).

Edytujemy obiekt "Binary object" wpisując w pole "key" hasło, które będzie wykorzystywane w celu zakodowania pliku.

Edytujemy jeszcze obiekty "Lpozycje", "Limiona", "Lwyniki", "Lrundy", "Ldaty" i ustawiamy ich właściwości w następujący sposób:

rekordy3.gif

Nasz poziom powinien wyglądać następująco:

rekordy4.gif

Teraz możemy przejść do edytora zdarzeń.

Oznaczenia obiektów:

  • EZ-edit.png imie
  • EZ-edit.png wynik
  • EZ-edit.png runda
  • EZ-edit.png data
  • EZ-edit.png Limiona
  • EZ-edit.png Lwyniki
  • EZ-edit.png Lrundy
  • EZ-edit.png Ldaty
  • EZ-edit.png Lpozycje
  • EZ-array.png imiona
  • EZ-array.png wyniki
  • EZ-array.png rundy
  • EZ-array.png daty
  • EZ-counter.png pom
  • EZ-counter.png ile_rekordow
  • EZ-button.png Dodaj rekord
  • EZ-button.png reset
  • EZ-string.png enter
  • EZ-string.png pom 2
  • EZ-binary.png Binary object
  • EZ-customs.png Custom Scrollbar
  • EZ-inne.png Decrease
  • EZ-inne.png Increase
  • EZ-inne.png Scroller
  • EZ-inne.png Background
  • EZ-special.png Special conditions

Edytor zdarzeń

W pierwszym zdarzeniu przy starcie klatki ograniczymy długość teksu, jaki można wpisać do obiektu "imie" na 20, oraz długość tekstu, jaki można wpisać do obiektu "data" na 10 (data ma postać np. 10-12-2006) dzięki temu łatwiej będzie nam potem zapisać wyniki do pliku binarnego. Ustawimy także wartość licznika "ile_rekordow" na ilość rekordów, jaką chcemy przechowywać np. 30.

Kod do edytora zdarzeń
N Zdarzenia
1
+ EZ-special.png run this event once
EZ-counter.png ile_rekordow: set Counter to 30
EZ-edit.png imie: limit text size to 20
EZ-edit.png data: limit text size to 10

Utwórzmy teraz 6 grup o nazwach: "Dodaj rekord", "Wyświetl rekordy", "Zapisz rekordy", "Wczytaj rekordy", "Resetuj rekordy", "Obsluga listy". Wszystkie z grup oprócz grupy "Wczytaj rekordy" mają być nieaktywne przy starcie poziomu.

Zajmijmy się zdarzeniami w grupie "Dodaj rekord".

Grupa ta jest aktywowana po naciśnięciu przycisku "Dodaj rekord" i jej zadaniem jest dodanie rekordu do listy, jeżeli wynik w polu "imie" jest wystarczająco duży. Najpierw sprawdzimy czy ostatni wynik w tablicy "wyniki", (czyli ten o indeksie będącym liczbą wszystkich przechowywanych rekordów), jest większy bądź równy wynikowi w polu "wynik", jeśli warunek ten jest spełniony oznacza to, że rekord jest zbyt mały, aby dodać go do listy, dlatego dezaktywujemy grupę "Dodaj rekord", a aktywujemy grupę "Obsluga listy".

2
+ EZ-array.png ValueAtX("wyniki", value("ile_rekordow"))>= Val(EZ-edit.png Edittext$("wynik"))
EZ-special.png Deactivate group "Dodaj rekord"
EZ-special.png Activate group "Obsługa listy"

Skoro wynik w polu edycji "wynik" jest większy od ostatniego w tablicy, to zamienimy ostatni rekord na ten nowy o większym wyniku, czyli zmienimy wartość komórki tablicy "imiona" o ostatnim indeksie (ilości wszystkich rekordów) na tekst pobrany z obiektu "imie", wartość ostatniej komórki tablicy "wyniki" na wartość pobraną z obiektu "wynik", wartość ostatniej komórki tablicy "rundy" na wartość pobraną z obiektu "runda", a tekst ostatniej komórki tablicy "daty" na tekst pobrany z obiektu "data". Oraz wywołamy pętlę "sort" ilość rekordów mniej 1 razy (n-1 razy jak to wynika z wcześniejszej analizy sortowania bąbelkowego)

3
+ EZ-array.png ValueAtX("wyniki", value("ile_rekordow")) < Val(EZ-edit.png Edittext$("wynik"))
EZ-array.png imiona: Write String Edittext$("imie") to (value("ile_rekordow"))
EZ-array.png wyniki: Write Value Edit Value("wynik") to (value("ile_rekordow"))
EZ-array.png rundy: Write Value Edit Value("runda") to (value("ile_rekordow"))
EZ-array.png daty: Write String Edittext$("data") to (value("ile_rekordow"))
EZ-special.png Special conditions: Start loop "sort” (value("ile_rekordow") - 1) times;

Pętla "sort" będzie sortować nam naszą listę (a właściwie umieści nasz nowo dodany wynik na odpowiednim miejscu). Będzie ona porównywać pary liczb pobranych z tablicy "wyniki" i jeśli wartość w komórce n będzie większa od wartości w komórce n-1 to te komórki zostaną zamienione miejscami wraz z komórkami o tym samym indeksie (n) tablic "imiona", "rundy", "daty" (gdzie n to indeks pętli "sort"). Zamiana ta dla tablic "wyniki" i "rundy", a więc przechowujących wartości liczbowe nastąpi w taki sposób, że wartość z komórki n zostanie zapisana do licznika "pom", następnie wartość komórki n-1 zostanie zapisana do komórki n, a wartość z licznika „pom” do komórki n-1. Natomiast dla tablic "imiona" i "daty", a więc przechowujących w swoich komórkach tekst nastąpi w taki sposób, że tekst z komórki n zostanie zapisana do obiektu string o nazwie "pom 2", następnie tekst z komórki n-1 zostanie zapisany do komórki n, a tekst z obiektu string "pom 2" do komórki n-1.

4
+ EZ-special.png on loop sort
+ EZ-array.png ValueAtX("wyniki", value("ile_rekordow") - LoopIndex("sort"))> EZ-array.png ValueAtX("wyniki", value("ile_rekordow") - LoopIndex("sort") - 1)
EZ-counter.png pom: Set Counter to ValueAtX("wyniki", value("ile_rekordow") - LoopIndex("sort") - 1)
EZ-array.png wyniki: Write Value ValueAtX("wyniki", value("ile_rekordow") - LoopIndex("sort")) to value("ile_rekordow") - LoopIndex("sort") – 1
EZ-array.png wyniki: Write Value value("pom") to value("ile_rekordow") - LoopIndex("sort")
EZ-string.png pom2: Set alterable string to StrAtX("imiona", value("ile_rekordow") - LoopIndex("sort") - 1)
EZ-array.png imiona: Write String StrAtX("imiona", value("ile_rekordow") - LoopIndex("sort")) to value("ile_rekordow") - LoopIndex("sort") – 1
EZ-array.png imiona: String string$("pom2") to value("ile_rekordow") - LoopIndex("sort")
EZ-string.png pom2: Set alterable string to StrAtX("daty", value("ile_rekordow") - LoopIndex("sort") - 1)
EZ-array.png daty: Write String StrAtX("daty", value("ile_rekordow") - LoopIndex("sort")) to value("ile_rekordow") - LoopIndex("sort") – 1
EZ-array.png daty: String string$("pom2") to value("ile_rekordow") - LoopIndex("sort")
EZ-counter.png pom: Set Counter to ValueAtX("rundy", value("ile_rekordow") - LoopIndex("sort") - 1)
EZ-array.png rundy: Write Value ValueAtX("rundy", value("ile_rekordow") - LoopIndex("sort")) to value("ile_rekordow") - LoopIndex("sort") – 1
EZ-array.png rundy: Write Value value("pom") to value("ile_rekordow") - LoopIndex("sort")

Kiedy już lista rekordów zostanie posortowana dezaktywujemy grupę "dodaj rekord", a aktywujemy grupę "Zapisz rekordy".

5
+ EZ-special.png Always
EZ-special.png Deactivate group dodaj rekordy
EZ-special.png Activate group zapisz rekordy

Teraz zajmiemy się zdarzeniami w grupie "Zapisz rekordy".

Zapis naszych rekordów do pliku można zrobić bardzo prosto po prostu skorzystać ze standardowej akcji obiektu "Array", (Save array to file), ale tak zapisane rekordy wymagałyby aż 4 plików, bo są cztery tablice, a ponadto niespełnione było by jedno z naszych założeń a mianowicie o zabezpieczeniu rekordów przed ingerencją użytkownika (pliki te są nie kodowane). My posłużymy się obiektem "Binary object", do którego wczytamy wszystkie dane z tablic, a następnie zakodujemy i zapiszemy do pliku.

Na początku wyczyścimy pamięć obiektu "Binary", tak, aby nie znajdowały się tam żadne śmieci, oraz zajmiemy pamięć niezbędną do wczytania rekordów. Wiemy, że każdy rekord składa się z 4 pul, imienia gracza, które maksymalnie może mieć 20 znaków (jeden znak zajmuje w pamięci 1B, więc jedno imię 20B); wyniku, z jakim gracz ukończył rundę, przyjąłem, że wartość ta będzie przechowywana jako zmienna typu long, która przyjmuje wartości z zakresu [–2147483648..2147483647] i zajmuje w pamięci 4B; nr. rundy, w której gracz zakończył grę reprezentowaną także jako zmienną long; oraz daty, kiedy gracz ustanowił rekord reprezentowanej jako tekst maksymalnie 10 znakowy, czyli 10B. Zatem jeden rekord zajmuje 20B+4B+4B+10B=38B bajtów, więc cały nasz plik będzie zajmować 38B*liczba rekordów. Na koniec wywołamy pętlę "zapisz_imiona" tyle razy ile jest pamiętanych rekordów.

6
+ EZ-special.png Always
EZ-binary.png Binary object: Remove all
EZ-binary.png Binary object: Resize binary to (38*value("ile_rekordow"))
EZ-special.png Start loop zapisz imiona value("ile_rekordow") times

Pętla "zapisz_imiona" będzie po kolei zapisywać w pamięci obiektu "Binary" imiona przechowywane w tablicy "imiona", pamiętajmy o tym, że imię zajmuje 20B, zatem pierwsze imię zaczyna się od pozycji 0, drugie 20, trzecie 40 itd., Czyli ogólnie n*20, gdzie n to indeks pętli "zapisz_imiona".

7
+ EZ-special.png on loop zapisz_imiona
EZ-binary.png Binary object: Set String StrAtX("imiona", LoopIndex("zapisz_imiona") + 1) at LoopIndex("zapisz_imiona") * 20

Kiedy już imiona zostały zapisane wywołamy pętlę "zapisz_wyniki" tyle razy ile jest pamiętanych rekordów

8
+ EZ-special.png Always
EZ-special.png Start loop zapisz_wyniki value("ile_rekordow") times

Pętla "zapisz_wyniki" zapisuje wyniki z tablicy "wyniki". Wynik przechowywany jest w zmiennej typu long zajmującej 4B, ale w pamięci obiektu "Binary" znajdują się już imiona zajmujące 20*ilość rekordów bajtów, zatem pierwszy wynik zaczyna się od pozycji 20*ilość rekordów, drugie od 20*ilość rekordów + 4, trzecie od 20*ilość rekordów + 8 itd., czyli ogólnie 20*ilość rekordów + n*4 (gdzie n to indeks pętli ”zapisz_wyniki”).

9
+ EZ-special.png on loop zapisz_wynik
EZ-binary.png Binary object:Set long ValueAtX("wyniki", LoopIndex("zapisz_wyniki") + 1) at 20 * value("ile_rekordow") + LoopIndex("zapisz_wyniki") * 4;

Kiedy już wyniki zostały zapisane wywołamy pętlę "zapisz_rundy" tyle razy ile jest pamiętanych rekordów

10
+ EZ-special.png Always
EZ-special.png Start loop zapisz_rundy value("ile_rekordow") times

Pętla "zapisz_rundy" zapisuje numery rund z tablicy "rundy". Numer rundy przechowywany jest w zmiennej typu long zajmującej 4B, ale w pamięci obiektu "Binary" znajdują się już imiona, i wyniki zajmujące razem (20+4)*ilość rekordów bajtów, zatem pierwszy numer rundy zaczyna się od pozycji (20+4)*ilość rekordów, drugie od (20+4)*ilość rekordów + 4, trzecie od (20+4)*ilość rekordów + 8 itd., czyli ogólnie (20+4)*ilość rekordów + n*4 (gdzie n to indeks pętli "zapisz_rundy").

11
+ EZ-special.png on loop zapisz_rundy
EZ-binary.png Binary object: Set long ValueAtX("rundy", LoopIndex("zapisz_rundy") + 1) at (20+4)*value("ile_rekordow") + LoopIndex("zapisz_rundy")*4

Kiedy już numery rund zostały zapisane wywołamy pętlę "zapisz_daty" tyle razy ile jest pamiętanych rekordów

12
+ EZ-special.png Always
EZ-special.png Start loop ”zapisz_daty” value("ile_rekordow") times

Pętla "zapisz_daty" zapisuje daty z tablicy "daty". Data przechowywany jest jako tekst zajmujący 10B, ale w pamięci obiektu "Binary" znajdują się już imiona, wyniki i numery rund zajmujące razem (20+8)*ilość rekordów bajtów, zatem pierwsza data zaczyna się od pozycji (20+8)*ilość rekordów, druga od (20+8)*ilość rekordów + 10, trzecie od (20+4)*ilość rekordów + 30 itd., czyli ogólnie (20+8)*ilość rekordów + n*10 (gdzie n to indeks pętli "zapisz_daty").

13
+ EZ-special.png on loop zapisz_daty
EZ-binary.png Binary object: Set long ValueAtX("rundy", LoopIndex("zapisz_rundy") + 1) at (20+4) * value("ile_rekordow") + LoopIndex("zapisz_rundy") * 4
14
+ EZ-special.png on loop zapisz_daty
EZ-binary.png Binary object: Set String StrAtX("daty", LoopIndex("zapisz_daty") + 1) at (20+8) * value("ile_rekordow") + LoopIndex("zapisz_daty") * 10;

Kiedy już wszystko jest wczytane do pamięci obiektu "Binary" zakodujemy jego zawartość i zapiszemy do pliku "rekordy.txt", a także dezaktywujemy grupę "Zapisz rekordy", a aktywujemy grupę "Wyswietl rekordy"

15
+ EZ-special.png Always
EZ-binary.png Binary object: Encrypt using blowfish
EZ-binary.png Binary object: Save binary to file Appdrive$ + Appdir$ + "rekordy.txt"
EZ-special.png Deactive group "Zapisz rekordy"
EZ-special.png Active group "Wyswietl rekordy"

Teraz zajmiemy się zdarzeniami w grupie "Wczytaj rekordy", która jest jedyną aktywną grupą przy starcie poziomu.

Grupa ta będzie mieć odwrotne zadanie do grupy "Zapisz rekordy", a więc wszystkie zdarzenia będą analogiczne, ale odwrotne.

Na początku wczytamy do pamięci obiektu "Binary" plik "rekordy.txt", zdekodujemy go i wywołamy pętlę "wczytaj_imiona" tyle ile jest rekordów.

16
+ EZ-special.png Always
EZ-binary.png Binary object: Load binary from file Appdrive$ + Appdir$ + "rekordy.txt"
EZ-binary.png Binary object: Decrypt using blowfish, start loop "wczytaj_imiona" value( "ile_rekordow" ) times;

Pętla "wczytaj_imiona" będzie wczytywać imiona z pamięci obiektu "Binary" do tablicy "imiona". Pamiętamy, że kolejne imiona w zaczynały się od pozycji n*20 (n- indeks pętli), a każde zajmowało 20B.

17
+ EZ-special.png On loop "wczytaj_imiona”
EZ-binary.png Binary object: Load binary from file Appdrive$ + Appdir$ + "rekordy.txt"
EZ-array.png imiona: Write String string$("Binary object",LoopIndex("wczytaj_imiona") * 20, 20) to LoopIndex("wczytaj_imiona") + 1;

Po wczytaniu imion do tablicy wywołujemy pętlę "wczytaj_wyniki" tyle razy ile jest rekordów.

18
+ EZ-special.png Always
EZ-special.png start loop "wczytaj_wyniki" value("ile_rekordow") times;

Pętla ta wczytuje wyniki z obiektu "Binary" do tablicy "wyniki". Pamiętajmy kolejne wyniki miały pozycje 20*liczba rekordów + n*4 (n- indeks pętli) w obiekcie "Binary".

19
+ EZ-special.png On loop "wczytaj_wyniki”
EZ-binary.png Write Value long("Binary object", 20 * value("ile_rekordow") + LoopIndex("wczytaj_wyniki") * 4) to LoopIndex("wczytaj_wyniki") + 1;

Kolejne 2 pętle wczytujące numery rund i daty działają analogicznie do omawianych dwóch poprzednich, więc zaprezentuję jedynie ich kod bez omawiania.

20
+ EZ-special.png Always
EZ-special.png start loop "wczytaj_rundy” value("ile_rekordow") times
21
+ EZ-special.png On loop "wczytaj_rundy”
EZ-binary.png Write Value long("Binary object", (20+4) * value("ile_rekordow") + LoopIndex("wczytaj_rundy") * 4) to LoopIndex("wczytaj_rundy") + 1
22
+ EZ-special.png Always
EZ-special.png start loop "wczytaj_daty” value("ile_rekordow") times
23
+ EZ-special.png On loop "wczytaj_daty”
EZ-binary.png Write String string$("Binary object",(20 + 8)*value("ile_rekordow") + LoopIndex("wczytaj_daty") * 10, 10)) to LoopIndex("wczytaj_daty") + 1

Kiedy wszystkie rekordy zostaną wczytane do odpowiednich tablic dezaktywujemy grupę "Wczytaj rekordy", a aktywujemy grupę "Wyswietl rekordy".

24
+ EZ-special.png Always
EZ-special.png Deactivate group "Wczytaj rekordy"
EZ-special.png Activate group "Wyswietl rekordy"

Zajmijmy się zdarzeniami w grupie "Wyswietl rekordy".

W grupie tej dane z tablic przechowujących rekordy zostaną wczytane do obiektów edycji w celu umożliwienia ich przeglądania. Na początku wyczyścimy obiekty edycji tak aby nic w nich się nie znajdowało następnie wywołamy tyle razy pętlę "wyswietl" ile jest rekordów.

25
+ EZ-special.png Always
EZ-edit.png Limiona: Set text „”, Lwyniki: Set text „”
EZ-edit.png Lrundy: Set text „”, Ldaty: Set text „”
EZ-special.png Start loop "wyswietl" value("ile_rekordow") times

Pętla "wyswietl" będzie wczytywać kolejne komórki z tablic do odpowiadających im obiektów edycji oddzielając je znakiem nowej linii przechowywanym w obiekcie string "enter". Dodatkowo w pole edycji "Lpozycje" zostaną w ten sam sposób wczytane kolejne indeksy pętli "wyswietl" powiększone, o jeden, które reprezentować będą pozycje wyniku na liście rekordów.

26
+ EZ-special.png on loop wyswietl
EZ-edit.png Lwyniki: Edittext$("Lwyniki") + Str$(ValueAtX("wyniki", LoopIndex("wyswietl") + 1)) + string$("enter")
EZ-edit.png Limiona: Edittext$("Limiona") + StrAtX("imiona", LoopIndex("wyswietl") + 1) + string$("enter")
EZ-edit.png Lrundy: Edittext$("Lrundy") + Str$(ValueAtX("rundy", LoopIndex("wyswietl") + 1)) + string$("enter")
EZ-edit.png Ldaty: Edittext$("Ldaty") + StrAtX("daty", LoopIndex("wyswietl") + 1) + string$("enter")
EZ-edit.png Lpozycje: Edittext$("Lpozycje") + Str$(LoopIndex("wyswietl") + 1) + "." + string$("enter")

Po wczytaniu do obiektów edycji danych dezaktywujemy grupę "Wyświetl rekordy" i aktywujemy grupę "Obsluga listy".

Teraz zajmiemy się zdarzeniami w grupie "Obsluga listy".

Grupa ta zawiera kod pozwalający na przewijanie listy rekordów, a także aktywuje odpowiednie grupy po klikniecie przycisku "Dodaj rekord", bądź "Resetuj".

Po naciśnięciu klawisza dodaj rekord zostaje dezaktywowana grupa "Obsluga listy", a aktywowana zostaje grupa "Dodaj rekord"

27
+ EZ-button.png "Dodaj rekord” clicked
EZ-special.png Activate group "Dodaj rekord"
EZ-special.png deactivate group "Obsluga listy"
28
+ EZ-button.png "Reset” clicked
EZ-special.png Activate group "Resetuj rekordy"
EZ-special.png deactivate group "Obsluga listy"

Teraz zajmiemy się paskiem przewijania.

Zanim to jednak uczynimy przejdźmy jeszcze do edytora poziomu i wzbogaćmy nasze obiekty: "Decrease", "Scroller", "Background", "Increase" o lepszą grafikę. Zmieńmy ich rozmiary i ustawmy odpowiednią pozycję np.:

rekordy14.gif

Teraz możemy zająć się zdarzeniami obsługującymi nasz pasek.

Na początku należy ustawić wszystkie parametry obiektu "Custom Scrollbar", który załatwi za nas większość obsługi paska przewijania. A więc minimalną wartość, jaką osiąga pasek przewinięty do samej góry (u nas 0), maksymalną wartość (pasek przewinięty do samego dołu, u nas liczba rekordów pomniejszona o liczbę rekordów jaka jest widoczna w obiektach edit bez przewijania), pozycję Y paska na pozycję Y obiektu "Decrease" (górnego przycisku), rozmiar całego paska (u nas jego wysokość) na wysokość obiektu "Background", rozmiar przycisku górnego na rozmiar obiektu "Increase", rozmiar przycisku dolnego na rozmiar obiektu "Decrease", wysokość przesuwaka, za który łapiemy myszką (nie znam fachowej nazwy ) na wysokość obiektu "Scroller".

29
+ EZ-special.png Run this event once
EZ-customs.png Custom Scrollbar: Set minimum value to 0
EZ-customs.png Custom Scrollbar: Set maximum value to value("ile_rekordow") – 15
EZ-customs.png Custom Scrollbar: Set the scrollbars offset position to Y("Decrease")
EZ-customs.png Custom Scrollbar: Set the scrollbars size to Height("Background")
EZ-customs.png Custom Scrollbar: Set the icrease button size to Height("Increase")
EZ-customs.png Custom scrollbar: Set the decrease button size to Height("Decrease")
EZ-customs.png Custom Scrollbar: Set the scrollbars bar size to Height("Scroller")

Zawsze powinniśmy aktualizować pozycję obiektu "Scroller" naszego przesuwaka na pobraną z obiektu "Custom Scrollbar".

30
+ EZ-special.png Always
EZ-customs.png Scroller: Set Y position to barpos("Custom Scrollbar 1.0")

W przypadku, kiedy użytkownik trzyma lewy klawisz myszy wciśnięty i jednocześnie wskaźnik myszy znajduje się nad obiektem "Scroller", a flaga "Drag" obiektu jest opuszczona (off) to ustawiamy pozycję przesunięcia na pozycję Y myszy i podnosimy flagę Drag.

31
+ Repeat while left mouse button is pressed
+ Mouse is over "Scroller"
+ negate(Custom "Scrollbar” is dragging)
EZ-customs.png "Custom Scrollbar”: Set drag ofset to YMouse
EZ-customs.png "Custom Scrollbar”: Set dragging flag on

Kiedy flaga "Drag" obiektu "Custom Scrollbar" jest podniesiona to wartość paska (przewinięcia) ustawiamy na przekonwertowaną przez obiekt "Custom Scrollbar" pozycję Y myszy (obciętą od odpowiedniego zakresu).

32
+ EZ-customs.png Custom "Scrollbar” is dragging
EZ-customs.png Custom Scrollbar: Set value to Barposconvert("Custom Scrollbar", YMouse)

Kiedy użytkownik zwolni lewy przycisk myszy należy podnieść flagę "Drag" obiektu "Custom Scrollbar" jeśli była podniesiona, aby pasek nie był niepotrzebnie przesuwany.

33
+ negate(Repeat while left mouse-key is pressed)
+ EZ-customs.png Custom Scrollbar is dragging
EZ-customs.png Custom Scrollbar: Set dragging flag off

Kiedy użytkownik trzyma wciśnięty lewy klawisz myszy i jednocześnie wskaźnik myszy znajduje się nad obiektem "Increase” (dolny przycisk) to należy zwiększyć wartość obiektu "Custom Scrollbar" o jeden (przesunąć w dół).

34
+ Repeat while left mouse-key is pressed
+ Mouse is over "Increase"
EZ-customs.png Custom Scrollbar: Set value to getvalue("Custom Scrollbar") + 1

Kiedy użytkownik trzyma wciśnięty lewy klawisz myszy i jednocześnie wskaźnik myszy znajduje się nad obiektem "Decrease" (górny przycisk) to należy zmniejszyć wartość obiektu "Custom Scrollbar" o jeden (przesunąć do góry).

35
+ Repeat while left mouse-key is pressed
+ Mouse is over "Decrease"
EZ-customs.png Custom Scrollbar: Set value to getvalue("Custom Scrollbar") - 1

Kiedy wartość obiektu "Custom Scrollbar" uległa zmianie należy przewinąć tekst wszystkich obiektów edycji reprezentujących listę do numeru linii który jest wartością obiektu "Custom Scrollbar", należy również opuścić flagę "Drag" obiektu "Custom Scrollbar";

36
+ EZ-customs.png Custom Scrollbar value changed
EZ-customs.png Custom Scrollbar: modified flag off
EZ-edit.png Limiona: Scroll to Line getvalue("Custom Scrollbar")
EZ-edit.png Lwyniki: Scroll to Line getvalue("Custom Scrollbar")
EZ-edit.png Lrundy: Scroll to Line getvalue("Custom Scrollbar")
EZ-edit.png Ldaty: Scroll to Line getvalue("Custom Scrollbar")
EZ-edit.png Lpozycje: Scroll to Line getvalue("Custom Scrollbar")

Została nam już ostania grupa "Resetuj rekordy" aktywowana przez przycisk "Resetuj". Co ona robi nie trzeba wyjaśniać . Wywołujemy pętlę "reset" tyle razy ile jest rekordów.

37
+ EZ-special.png Always
EZ-special.png Start loop "reset” value("ile_rekordow") times

Pętla "reset" we wszystkie komórki tablic przechowujących rekordy wstawi wartości oznaczające wartości puste.

38
+ EZ-special.png On loop "reset”
EZ-array.png imiona: Write String "Pusty" + "Pusty" + Str$( LoopIndex("reset") + 1) to LoopIndex("reset") + 1
EZ-array.png wyniki: Write Value 0 to LoopIndex("reset") + 1, rundy: Write Value 0 to LoopIndex("reset") + 1
EZ-array.png daty: Write String „

Po wyczyszczeniu tablic dezaktywujemy grupę "Resetuj rekordy", a aktywujemy grupę "Zapisz rekordy";

39
+ EZ-special.png Always
EZ-special.png Deactivate group "Resetuj rekordy"
EZ-special.png Activate group "Zapisz rekordy"

Tak to już koniec .