Added part of docs
Some checks failed
docs / deploy (push) Has been cancelled
docs / build (push) Has been cancelled

This commit is contained in:
Patryk Gensch
2026-05-19 20:51:59 +02:00
parent e91fd2e42a
commit df6cf2f3d3
66 changed files with 11821 additions and 0 deletions

View File

@@ -0,0 +1,180 @@
# Arytmetyka
Silnik Piklib/BlooMoo wykonuje obliczenia wyłącznie wewnątrz **wyrażeń arytmetycznych** zamkniętych w nawiasach kwadratowych. Nawiasy okrągłe są zarezerwowane dla list argumentów wywołań metod i nie pełnią roli grupującej w wyrażeniach. Sekcja poniżej opisuje obsługiwane operatory, reguły typowania oraz konwersje pomiędzy typami prymitywnymi.
## Składnia {#skladnia}
Wyrażenie arytmetyczne zapisuje się w nawiasach kwadratowych. Może być użyte wszędzie, gdzie spodziewana jest wartość — w tym jako argument metody lub jako wartość przypisywana do pola:
```
NAZWA_ZMIENNEJ^SET([VAL1+VAL2]);
*["ANIMO_"+_I_]^PLAY();
```
Zagnieżdżanie wyrażeń odbywa się przez kolejne pary nawiasów kwadratowych:
```
[[VAL1+VAL2]*VAL3]
```
## Reguła typowania {#regula-typowania}
Wszystkie operacje binarne w wyrażeniach kierują się jedną zasadą:
> **Typ wyniku oraz typ prawego operandu są wyznaczone przez typ lewego operandu.**
Prawy operand jest rzutowany na typ lewego przed wykonaniem operacji, a wynik również ma ten typ. Przykłady:
```
"Wartosc" + 2.5 → "Wartosc2.50000" # DOUBLE rzutowany do STRING
2 + "3" → 5 # STRING rzutowany do INTEGER
```
Konsekwencja: kolejność operandów ma znaczenie nie tylko dla operatorów nieprzemiennych, ale również dla samego typu wyniku.
## Konwersje typów
W ramach reguły typowania prawy operand jest rzutowany według poniższych zasad.
### Z `STRING`
| Cel | Reguła |
|---|---|
| [`INTEGER`](../reference/INTEGER.md) | Z początkowej części tekstu wyciągana jest liczba całkowita (analogicznie do `parseInt`). Jeżeli tekst nie zaczyna się od liczby, wynikiem jest `0`. |
| [`DOUBLE`](../reference/DOUBLE.md) | Analogicznie do `INTEGER`, ale z zachowaniem części ułamkowej. Separatorem dziesiętnym jest kropka. |
| [`BOOL`](../reference/BOOL.md) | Tekst odpowiadający wartości prawdziwej (`TRUE` lub niezerowa liczba) zwraca `TRUE`; w pozostałych przypadkach `FALSE`. |
```
"5" → 5
"Test" → 0
```
### Z `INTEGER`
| Cel | Reguła |
|---|---|
| [`STRING`](../reference/STRING.md) | Zapis dziesiętny liczby. |
| [`DOUBLE`](../reference/DOUBLE.md) | Liczba z zerową częścią ułamkową (pięć zer po przecinku). |
| [`BOOL`](../reference/BOOL.md) | Wartość różna od `0` daje `TRUE`, równa `0``FALSE`. |
```
5 → "5"
3 → 3.00000
-2 → TRUE
0 → FALSE
```
### Z `DOUBLE`
| Cel | Reguła |
|---|---|
| [`STRING`](../reference/STRING.md) | Zapis dziesiętny z kropką i pięcioma miejscami po przecinku. Dla wartości równych `0.0` część po przecinku jest pomijana. |
| [`INTEGER`](../reference/INTEGER.md) | Zaokrąglenie do najbliższej liczby całkowitej; przy `.5` w górę dla liczb dodatnich i w dół dla ujemnych. |
| [`BOOL`](../reference/BOOL.md) | Pośrednie: najpierw rzutowanie do `INTEGER` (z powyższym zaokrągleniem), potem do `BOOL`. Wartości z przedziału `(-0.5, 0.5)` dają `FALSE`, pozostałe `TRUE`. |
```
3.5 → "3.50000", 4, TRUE
0.0 → "0", 0, FALSE
0.45362 → "0.45362", 0, FALSE
1.00001 → "1.00001", 1, TRUE
-0.5 → "-0.50000", -1, TRUE
```
### Z `BOOL`
| Cel | Reguła |
|---|---|
| [`STRING`](../reference/STRING.md) | `TRUE``"TRUE"`, `FALSE``"FALSE"`. |
| [`INTEGER`](../reference/INTEGER.md) | `TRUE``1`, `FALSE``0`. |
| [`DOUBLE`](../reference/DOUBLE.md) | `TRUE``1.00000`, `FALSE``0.00000`. |
## Operatory arytmetyczne
W wyrażeniach dostępne są następujące operatory binarne:
| Operator | Znaczenie |
|---|---|
| `+` | dodawanie / konkatenacja |
| `-` | odejmowanie |
| `*` | mnożenie |
| `@` | dzielenie |
| `%` | reszta z dzielenia |
### Dodawanie (`+`)
| Typ lewego operandu | Zachowanie |
|---|---|
| [`STRING`](../reference/STRING.md) | Konkatenacja prawego operandu (po rzutowaniu) do lewego. |
| [`INTEGER`](../reference/INTEGER.md) | Suma liczbowa. |
| [`DOUBLE`](../reference/DOUBLE.md) | Suma liczbowa. |
| [`BOOL`](../reference/BOOL.md) | Koniunkcja logiczna (`AND`). `TRUE + FALSE` daje `FALSE`. |
### Odejmowanie (`-`)
| Typ lewego operandu | Zachowanie |
|---|---|
| [`STRING`](../reference/STRING.md) | Brak efektu; wynikiem jest lewy operand. |
| [`INTEGER`](../reference/INTEGER.md) | Różnica liczbowa. |
| [`DOUBLE`](../reference/DOUBLE.md) | Różnica liczbowa. |
| [`BOOL`](../reference/BOOL.md) | Brak efektu; wynikiem jest lewy operand. |
### Mnożenie (`*`)
| Typ lewego operandu | Zachowanie |
|---|---|
| [`STRING`](../reference/STRING.md) | Brak efektu; wynikiem jest lewy operand. |
| [`INTEGER`](../reference/INTEGER.md) | Iloczyn liczbowy. |
| [`DOUBLE`](../reference/DOUBLE.md) | Iloczyn liczbowy. |
| [`BOOL`](../reference/BOOL.md) | Alternatywa logiczna (`OR`). `FALSE * TRUE` daje `TRUE`. |
### Dzielenie (`@`)
| Typ lewego operandu | Zachowanie |
|---|---|
| [`STRING`](../reference/STRING.md) | Brak efektu; wynikiem jest lewy operand. |
| [`INTEGER`](../reference/INTEGER.md) | Iloraz całkowity. |
| [`DOUBLE`](../reference/DOUBLE.md) | Iloraz zmiennoprzecinkowy. |
| [`BOOL`](../reference/BOOL.md) | Brak efektu; wynikiem jest lewy operand. |
Dzielenie przez `0` w typach liczbowych powoduje błąd silnika.
### Reszta z dzielenia (`%`)
| Typ lewego operandu | Zachowanie |
|---|---|
| [`STRING`](../reference/STRING.md) | Brak efektu; wynikiem jest lewy operand. |
| [`INTEGER`](../reference/INTEGER.md) | Reszta z dzielenia. |
| [`DOUBLE`](../reference/DOUBLE.md) | Reszta z dzielenia obcięta do liczby całkowitej, a następnie rzutowana z powrotem do `DOUBLE`. Skutkuje to utratą części ułamkowej, np. `1.5 % 2` daje `1.00000`, nie `1.50000`. |
| [`BOOL`](../reference/BOOL.md) | Brak efektu; wynikiem jest lewy operand. |
Modulo z drugim operandem równym `0` powoduje błąd silnika.
## Operatory porównań
W wyrażeniach dostępne są standardowe operatory porównań: `==`, `!=`, `<`, `<=`, `>`, `>=`. Prawy operand jest najpierw rzutowany na typ lewego (zgodnie z [regułą typowania](#regula-typowania)), a następnie porównywany.
### Równość i nierówność
`==` zwraca `TRUE`, jeżeli oba operandy (po rzutowaniu) są równe; `!=` zwraca przeciwieństwo. Dla typu [`STRING`](../reference/STRING.md) porównanie odbywa się znak po znaku, dla typów liczbowych — wartościami.
### Porównania mniejsze / większe
| Typ lewego operandu | `<` zwraca `TRUE`, jeżeli |
|---|---|
| [`STRING`](../reference/STRING.md) | Leksykograficznie lewy operand poprzedza prawy (porównanie znak po znaku w kodowaniu CP1250). |
| [`INTEGER`](../reference/INTEGER.md) | Wartość liczbowa lewego operandu jest mniejsza. |
| [`DOUBLE`](../reference/DOUBLE.md) | Wartość liczbowa lewego operandu jest mniejsza. |
| [`BOOL`](../reference/BOOL.md) | Lewy operand to `FALSE`, a prawy `TRUE` (`FALSE < TRUE`). |
`>` zwraca `TRUE` w sytuacjach przeciwnych. Operatory `<=` oraz `>=` są równoważne odpowiednio `<` lub `==` oraz `>` lub `==`.
## Operatory logiczne
Operatory `&&` (koniunkcja) i `||` (alternatywa) przyjmują wyłącznie operandy typu [`BOOL`](../reference/BOOL.md). Podanie operandu innego typu (nawet jeżeli mógłby zostać rzutowany) powoduje błąd silnika.
| Operator | Wynik |
|---|---|
| `&&` | `TRUE` tylko jeżeli oba operandy są `TRUE`. |
| `||` | `TRUE` jeżeli przynajmniej jeden z operandów jest `TRUE`. |
W [warunku złożonym instrukcji `@IF`](scripts.md#warunek-zlozony) operatory `&&` i `||` zachowują się tak samo, ale zapisywane są jako część ciągu warunku, nie jako operatory wyrażenia arytmetycznego.

90
docs/pl/engine/events.md Normal file
View File

@@ -0,0 +1,90 @@
# Zdarzenia i sygnały
Silnik Piklib/BlooMoo udostępnia reaktywny model sterowania logiką gry oparty o sygnały. Każdy obiekt może emitować nazwane sygnały, do których w skryptach można podłączyć procedury lub bloki kodu. Niniejszy rozdział opisuje, jak działa ten mechanizm i jakie typowe sygnały są dostępne.
## Podłączanie obsługi sygnału
Sygnał obsługiwany jest analogicznie do dowolnej innej właściwości obiektu — w miejscu wartości podaje się nazwę procedury albo blok kodu:
```
NAZWA_OBIEKTU:ONCHANGED=NAZWA_PROCEDURY
NAZWA_OBIEKTU:ONCHANGED={NAZWA_INNEGO_OBIEKTU^PLAY("TADA");}
```
W ramach jednego obiektu można podłączyć po jednej obsłudze do każdej nazwy sygnału.
## Sygnały parametryzowane {#sygnaly-parametryzowane}
Niektóre sygnały, w szczególności [`ONCHANGED`](#onchanged) oraz [`ONBRUTALCHANGED`](#onbrutalchanged), są emitowane razem z wartością. Wartość ta może być wykorzystana do filtrowania — silnik najpierw szuka obsługi dopasowanej do pary `sygnał + wartość`, a dopiero w przypadku jej braku trafia do uniwersalnej obsługi dla samej nazwy sygnału.
Dyskryminator zapisuje się po nazwie sygnału, oddzielony znakiem daszka `^`:
```
NAZWA_OBIEKTU:ONBRUTALCHANGED^3=OBSLUGA_DLA_TROJKI
NAZWA_OBIEKTU:ONBRUTALCHANGED=OBSLUGA_OGOLNA
```
Dla powyższego: wywołanie `OBIEKT^SET(3)` uruchomi `OBSLUGA_DLA_TROJKI`; dla każdej innej wartości — `OBSLUGA_OGOLNA`.
## Wykonywanie obsługi
System sygnałów jest synchroniczny i jednowątkowy. Emisja sygnału natychmiast przekazuje sterowanie do obsługi: bieżąca procedura jest wstrzymywana, wykonywana jest obsługa sygnału, a po jej zakończeniu sterowanie wraca do miejsca, z którego sygnał został wyemitowany. Sygnały nie są kolejkowane.
Sekwencja zagnieżdżonych wywołań sygnałprocedurasygnałprocedura tworzy drzewo wywołań. Operatory skoku oddziałują na to drzewo w następujący sposób:
- [`@ONEBREAK`](scripts.md#operatory-skoku) — przerywa wyłącznie bieżącą procedurę i wraca do wywołującego.
- [`@BREAK`](scripts.md#operatory-skoku) — przerywa całe drzewo wywołań rozpoczęte przez pierwotną emisję sygnału.
## Argumenty sygnału
Niektóre sygnały emitowane są z dodatkowymi argumentami. Wewnątrz obsługi sygnału argumenty te są dostępne tak samo jak w procedurze — przez `$1`, `$2`, … (numeracja od `1`). Pozwala to obsłudze reagować na konkretną wartość, która wywołała sygnał.
## Sygnały uniwersalne
### ONINIT
Emitowany podczas inicjalizacji zmiennej w trakcie wczytywania jej pliku. Kolejność emisji nie jest przypadkowa — zmienne są inicjalizowane w stałej kolejności typów; szczegóły opisano w sekcji [Inicjalizacja zmiennych](scripts.md#inicjalizacja-zmiennych).
Typowe zastosowania: inicjalizacja [tablic](../reference/index.md), ustawienie początkowego stanu animacji, wczytanie danych z plików zewnętrznych.
### ONSIGNAL
Sygnał ogólnego przeznaczenia, emitowany przez wywołanie globalnej metody `SEND` na rzecz obiektu:
```
NAZWA_OBIEKTU^SEND("MOJ_SYGNAL");
```
Przesłany ciąg znaków jest dostępny w obsłudze sygnału jako pierwszy argument (`$1`). Mechanizm pozwala definiować własne zdarzenia bez konieczności reagowania na zmiany wartości lub zdarzenia animacji.
## Sygnały zmiany wartości
Emitowane są przez typy [prymitywne](../reference/index.md) (oraz inne typy z polem `VALUE`) przy każdej modyfikacji wartości.
### ONCHANGED
Emitowany wyłącznie wtedy, gdy nowa wartość różni się od poprzedniej. Argumentem (`$1`) jest nowa wartość.
### ONBRUTALCHANGED
Emitowany przy każdej modyfikacji wartości, nawet jeżeli nowa wartość jest taka sama jak poprzednia. Argumentem (`$1`) jest nowa wartość.
W praktyce `ONBRUTALCHANGED` przydaje się do wykrywania samego faktu wywołania metody zmieniającej wartość (`SET`, `INC`, `SWITCH`, …), niezależnie od tego, czy wartość faktycznie się zmieniła.
## Sygnały obiektów graficznych i sekwencji
### ONSTARTED
Emitowany po rozpoczęciu odtwarzania animacji lub sekwencji.
- Dla **sekwencji** — emitowany raz, z nazwą bieżącego eventu z pliku `.SEQ` jako argumentem.
- Dla **animacji** — emitowany z nazwą eventu z pliku `.ANN`. Jeżeli animacja sterowana jest przez sekwencję, sygnał może być emitowany wielokrotnie ze względu na zapętlanie.
### ONFINISHED
Emitowany po zakończeniu odtwarzania:
- dla **animacji** — po wyświetleniu ostatniej klatki i zatrzymaniu odtwarzania,
- dla **sekwencji** — po zakończeniu ostatniego eventu (lub dla każdego eventu odtwarzanego po kolei, w zależności od konfiguracji).
W obu przypadkach sygnał jest również emitowany w odpowiedzi na ręczne wywołanie metody `STOP` (bez argumentu lub z `TRUE`).

70
docs/pl/engine/globals.md Normal file
View File

@@ -0,0 +1,70 @@
# Zmienne globalne i wbudowane
Silnik udostępnia kilka kategorii zmiennych i nazw, do których można odwoływać się z dowolnego miejsca w skryptach, niezależnie od ich poziomu w hierarchii kontekstów. Niniejszy rozdział opisuje wbudowane obiekty, zmienne niejawne, specjalne procedury oraz hierarchię widoczności.
## Hierarchia kontekstów
Każdy wczytywany skrypt tworzy kontekst zmiennych. Konteksty są zagnieżdżone: kontekst sceny dziedziczy po kontekście epizodu, ten po kontekście aplikacji, a ten po kontekście globalnym silnika. Wyszukiwanie zmiennej odbywa się od najniższego kontekstu w górę — zmienne z niższych poziomów przesłaniają zmienne o tej samej nazwie z poziomów wyższych, ale zmienne wyższych poziomów są widoczne z poziomów niższych.
## Obiekty wbudowane
Następujące obiekty są tworzone leniwie przez silnik przy pierwszym odwołaniu i są dostępne z dowolnego kontekstu pod stałymi nazwami:
| Nazwa | Typ | Opis |
|---|---|---|
| `MOUSE` | [`MOUSE`](../reference/index.md) | Stan myszy (pozycja, kliknięcia). |
| `KEYBOARD` | [`KEYBOARD`](../reference/index.md) | Stan klawiatury. |
| `RAND` | [`RAND`](../reference/index.md) | Generator liczb pseudolosowych. Dostępny również pod aliasem `RANDOM`. |
| `SYSTEM` | [`SYSTEM`](../reference/index.md) | Interfejs do funkcji systemowych (czas, środowisko). |
Wszystkie cztery obiekty są singletonami w kontekście globalnym — odwołanie do nich z dowolnego skryptu trafia do tej samej instancji.
## Obiekty z `Application.def`
Obiekty zdefiniowane w pliku `Application.def` — typu [`APPLICATION`](../reference/index.md), [`EPISODE`](../reference/index.md) oraz [`SCENE`](../reference/index.md) — są ładowane do kontekstu globalnego silnika i widoczne ze wszystkich skryptów gry. Pozostałe typy w tym pliku są ignorowane (zobacz [Punkt startowy](scripts.md#punkt-startowy)).
## Zmienne niejawne
Silnik wstrzykuje do skryptów kilka zmiennych nie deklarowanych jawnie.
### `_I_`
Licznik pętli ustawiany przez instrukcję [`@LOOP`](scripts.md#loop). Jest zmienną typu [`INTEGER`](../reference/INTEGER.md) tworzoną lokalnie w kontekście bieżącej iteracji. Wartość zmienia się automatycznie wraz z postępem pętli.
Wewnątrz pętli `@LOOP` `_I_` może być odczytywana w wyrażeniach arytmetycznych i jako argument metod:
```
@LOOP({*["ANIMO_"+_I_]^PLAY();}, 0, 10, 1);
```
Pętla [`@FOR`](scripts.md#for-bloomoo) pozwala podać własną nazwę licznika; w takim przypadku `_I_` nie jest ustawiana.
### `THIS`
Referencja do obiektu, który wyemitował aktualnie obsługiwany sygnał. Dostępna wyłącznie w bloku obsługi sygnału i procedurach z niego wywołanych. Szczegóły jej zachowania opisano w sekcji [Zmienna THIS](scripts.md#zmienna-this).
### `$1`, `$2`, … `$N`
Argumenty procedury lub obsługi sygnału (numeracja od `1`). Dostępne tylko w ciele procedury lub bloku obsługującego sygnał:
```
PROCEDURA:CODE={NAZWA_ZMIENNEJ^SET($1);}
```
Powyższa składnia jest opisana również w sekcji [Argumenty procedur](scripts.md#argumenty-procedur).
## Specjalne procedury
Niektóre nazwy procedur mają znaczenie konwencjonalne — silnik wywołuje je automatycznie w określonych momentach cyklu życia.
### `__ONINIT__`
Procedura wywoływana po zakończeniu inicjalizacji wszystkich zmiennych w wczytanym pliku. Zobacz [Inicjalizacja zmiennych](scripts.md#inicjalizacja-zmiennych). Typowe zastosowanie: ustawienie stanu początkowego sceny po tym, jak wszystkie obiekty są już dostępne.
### `__INIT__`
Procedura wywoływana po załadowaniu sceny i wykonaniu inicjalizacji zmiennych — bezpośrednio przed przekazaniem sterowania do logiki gry. Wykorzystywana do ustawiania stanu sceny zależnego od bieżącego epizodu lub aplikacji.
## Konwencja nazewnictwa
Nazwy poprzedzone i zakończone dwoma podkreślnikami (`__NAZWA__`) są zarezerwowane dla silnika oraz dla konwencjonalnych nazw rozpoznawanych globalnie (np. `__KEYB__`, `__INIT__`, `__ONINIT__`). W praktyce skrypty AidemMedia używają tego formatu również dla własnych zmiennych globalnych, których nie chcą przypadkowo przesłonić w kontekstach lokalnych.

38
docs/pl/engine/index.md Normal file
View File

@@ -0,0 +1,38 @@
# Silnik
**Piklib** (później **BlooMoo**) to 32-bitowy silnik graficzny stworzony przez firmę Aidem Media na potrzeby polskich gier przygodowych z lat 2000. Niniejsza dokumentacja opisuje wewnętrzną logikę silnika i sposób, w jaki wykonuje on skrypty gry.
## Czego dotyczy ta dokumentacja
Dokumentacja koncentruje się na **języku skryptowym** silnika i **modelu wykonania** widzianym z poziomu skryptów — czyli na tym, co programista treści gry musi wiedzieć, żeby zrozumieć działanie istniejących skryptów lub pisać własne.
Nie jest to dokumentacja kodu źródłowego silnika ani pełna specyfikacja wszystkich struktur danych; są to obszary, które będą uzupełniane stopniowo.
## Struktura
Dokumentacja silnika podzielona jest na pięć rozdziałów:
- [Skrypty](scripts.md) — składnia skryptów, parser, kolejność wczytywania i inicjalizacji obiektów.
- [Arytmetyka](arithmetic.md) — wyrażenia obliczeniowe, operatory i reguły konwersji między typami prymitywnymi.
- [Zdarzenia i sygnały](events.md) — model reaktywny silnika, podłączanie obsługi, propagacja przez drzewo wywołań.
- [Zmienne globalne](globals.md) — wbudowane obiekty (`MOUSE`, `KEYBOARD`, `RAND`, `SYSTEM`), zmienne niejawne (`_I_`, `THIS`, `$N`) i specjalne procedury.
- [Dziwactwa silnika](quirks.md) — niestandardowe zachowania, które łatwo przeoczyć.
Pełną listę dostępnych typów danych zawiera [Referencja typów](../reference/index.md).
## Gry wykorzystujące silnik
Lista jest niekompletna i będzie uzupełniana w miarę identyfikowania kolejnych tytułów.
| Gra | Wersja silnika |
|---|---|
| Reksio i Skarb Piratów | Piklib 8 |
| Reksio i Ufo | Piklib 7.1, Piklib 8 |
| Reksio i Czarodzieje | Piklib 8 |
| Reksio i Wehikuł Czasu | Piklib 8 |
| Reksio i Kapitan Nemo | BlooMoo |
| Reksio i Kretes w Akcji | BlooMoo |
| Poznaj Mity: Wyprawa po Złote Runo | Piklib 7.1 |
| Poznaj Mity: Wojna Trojańska | Piklib 7.2 |
| Poznaj Mity: Przygody Odyseusza | Piklib 8 |
| Poznaj Mity: Herkules | Piklib 8 |

118
docs/pl/engine/quirks.md Normal file
View File

@@ -0,0 +1,118 @@
# Dziwactwa silnika
Silnik Piklib/BlooMoo zawiera szereg niestandardowych zachowań, które mogą zaskoczyć programistę przyzwyczajonego do popularnych języków skryptowych. Niniejszy rozdział zbiera najczęstsze z nich w jednym miejscu.
## Wyrażenia i operatory
### Tylko nawiasy kwadratowe grupują obliczenia
W wyrażeniach arytmetycznych grupowanie wykonuje się wyłącznie za pomocą `[ ]`. Nawiasy okrągłe `( )` są zarezerwowane dla list argumentów wywołań metod i nie pełnią funkcji grupującej (zobacz [Arytmetyka](arithmetic.md#skladnia)).
### `@` zamiast `/` dla dzielenia
Operator dzielenia to znak małpki `@`, nie `/`. Próba użycia `/` w wyrażeniu nie zostanie zinterpretowana jako dzielenie.
### Typ wyniku zależy od typu lewego operandu
Wszystkie operacje binarne rzutują prawy operand na typ lewego. Wynik również ma typ lewego operandu. Skutki kolejności są nietrywialne (zobacz [Reguła typowania](arithmetic.md#regula-typowania)):
```
"Wartosc" + 2.5 → "Wartosc2.50000"
2 + "3" → 5
```
### Operatory na `BOOL` mają odwróconą logikę
Operator `+` na [`BOOL`](../reference/BOOL.md) działa jak koniunkcja logiczna (`AND`), a `*` jak alternatywa (`OR`). Operatory `-`, `@` i `%` na `BOOL` nie mają efektu (zobacz [Operatory arytmetyczne](arithmetic.md#operatory-arytmetyczne)).
### `%` na `DOUBLE` traci część ułamkową
Reszta z dzielenia w typie [`DOUBLE`](../reference/DOUBLE.md) jest najpierw obliczana, a następnie obcinana do liczby całkowitej i ponownie rzutowana na `DOUBLE`. W efekcie `1.5 % 2` daje `1.00000`, a nie `1.50000`.
### `&&` i `||` przyjmują wyłącznie `BOOL`
Operatory logiczne nie wykonują niejawnego rzutowania nawet wtedy, gdy operand byłby konwertowalny do `BOOL`. Próba użycia wartości innego typu jako operandu kończy się błędem silnika.
### Dzielenie przez `0` w wyrażeniach kończy się błędem
W odróżnieniu od metod typów liczbowych (gdzie `DIV` i `MOD` zwracają wartość bez zmian), dzielenie operatorem `@` lub `%` przez `0` w wyrażeniu arytmetycznym powoduje wyjście do pulpitu.
## Składnia skryptów
### Bloki kodu muszą być w jednej linii
Cały blok kodu pomiędzy `{` a `}` musi się zmieścić w jednej linii pliku skryptu. Wieloliniowe bloki nie są obsługiwane.
### Każda instrukcja musi kończyć się średnikiem
Również ostatnia instrukcja w bloku kodu. Pominięcie końcowego średnika może spowodować, że instrukcja nie zostanie wykonana.
### Komentarze: `#` dla linii, `!` dla instrukcji
Linia rozpoczynająca się od `#` jest pomijana w całości. Pojedyncza instrukcja poprzedzona znakiem `!` jest wykomentowana aż do najbliższego średnika.
### Komparator równości zmienia się w warunkach złożonych
W [warunku prostym `@IF`](scripts.md#warunek-prosty) równość zapisuje się jako `_`. W [warunku złożonym `@IF`](scripts.md#warunek-zlozony) ten sam komparator zapisuje się jako apostrof `'`. Pozostałe komparatory (`<`, `>`, `<_`/`<'`, `>_`/`>'`) zachowują się analogicznie.
### Tekst bez cudzysłowów jest najpierw szukany jako zmienna
Wartość zapisana bez cudzysłowów najpierw jest interpretowana jako nazwa zmiennej. Jeśli zmienna o takiej nazwie istnieje, użyta zostanie jej wartość; w przeciwnym razie tekst zostanie potraktowany jako literał typu [`STRING`](../reference/STRING.md). Może to prowadzić do trudnych do wykrycia kolizji, gdy literał przypadkowo zbieżny jest z nazwą zmiennej.
### Wielokrotna deklaracja obiektu scala właściwości
Powtórzenie linii `OBJECT=NAZWA` w tym samym pliku nie nadpisuje wcześniejszej definicji — silnik dołącza nowe właściwości do istniejącej i nadpisuje wpisy o tych samych kluczach.
### `Application.def` powinien kończyć się pustą linią
Brak pustej linii na końcu pliku `Application.def` może spowodować, że ostatnia scena nie zostanie poprawnie zinterpretowana, co objawia się czarnym ekranem.
## Liczby
### `DOUBLE` akceptuje literę `d` jako znak wykładnika
W notacji wykładniczej zarówno `e`, jak i `d` są rozpoznawane jako separator wykładnika: `1.23e4` i `1.23d4` są równoważne.
### `DOUBLE → INTEGER` zaokrągla, a nie obcina
Przy rzutowaniu [`DOUBLE`](../reference/DOUBLE.md) na [`INTEGER`](../reference/INTEGER.md) liczba jest zaokrąglana do najbliższej liczby całkowitej, a nie obcinana. Dla wartości dodatnich `.5` zaokrąglane jest w górę, dla ujemnych — w dół, więc `-0.5 → -1`, a `0.5 → 1`.
### `STRING → INTEGER` zwraca `0` zamiast błędu
Konwersja tekstu nie będącego liczbą do [`INTEGER`](../reference/INTEGER.md) (lub [`DOUBLE`](../reference/DOUBLE.md)) zwraca `0` (`0.00000`), a nie generuje błędu. Może to maskować błędy w wyrażeniach łączących literały tekstowe z liczbowymi.
## Metody typów
### `DOUBLE.MOD` obcina część ułamkową
Analogicznie do operatora `%`, metoda [`MOD`](../reference/DOUBLE.md#mod) typu `DOUBLE` zwraca część całkowitą reszty z dzielenia.
### `DOUBLE.SGN` zwraca `INTEGER`, nie `DOUBLE`
Metoda [`SGN`](../reference/DOUBLE.md#sgn) jest jedyną metodą typu `DOUBLE`, która nie zmienia wartości zmiennej i jako wartość zwraca [`INTEGER`](../reference/INTEGER.md).
### `INTEGER.RANDOM(min, max)` jest obustronnie włączne
Wariant dwuargumentowy metody [`RANDOM`](../reference/INTEGER.md#random) zwraca wartość z przedziału `[min, max]`, włącznie z oboma końcami. Wariant jednoargumentowy zwraca `[0, bound)`.
### `INTEGER.DIV` i `INTEGER.MOD` z `0` nie modyfikują zmiennej
W odróżnieniu od dzielenia operatorem `@`/`%` w wyrażeniu, metody [`DIV`](../reference/INTEGER.md#div) i [`MOD`](../reference/INTEGER.md#mod) na typie `INTEGER` z dzielnikiem `0` zwracają niezmienioną wartość bieżącą zamiast generować błąd. Analogicznie zachowują się metody na typie `DOUBLE`.
### `STRING.COPYFILE` ignoruje obiekt-odbiorcę
Metoda [`COPYFILE`](../reference/STRING.md#copyfile) na typie [`STRING`](../reference/STRING.md) nie korzysta z wartości zmiennej, na której została wywołana — operuje wyłącznie na dwóch argumentach reprezentujących ścieżki źródłową i docelową.
### `STRING.CHANGEAT` zastępuje dokładnie jeden znak
Niezależnie od długości ciągu w drugim argumencie, [`CHANGEAT`](../reference/STRING.md#changeat) usuwa jeden znak z bieżącej wartości na podanej pozycji i wstawia w jego miejsce cały ciąg argumentu. Długość ciągu po operacji może być inna niż przed.
## `THIS` w obsłudze sygnałów
### `THIS` zwraca `"temp"` dla `GETNAME`
Mimo że `THIS` jest referencją do obiektu, który wyemitował sygnał, próba pobrania jego nazwy metodą `GETNAME` zwraca ciąg `"temp"`, co wskazuje na wewnętrzną reprezentację jako obiekt tymczasowy.
### Nie wszystkie metody typu działają na `THIS`
Bezpiecznie działają `GET`/`SET` (dla typów prymitywnych) oraz `SHOW`/`HIDE`/`PLAY`/`PAUSE`/`STOP`/`RESUME` (dla obiektów graficznych). Wywołanie metod specyficznych dla typu obiektu (np. [`GETCFRAMEINEVENT`](../reference/index.md) na `ANIMO`) zazwyczaj kończy się błędem silnika. Szczegóły opisano w sekcji [Zmienna THIS](scripts.md#zmienna-this).

280
docs/pl/engine/scripts.md Normal file
View File

@@ -0,0 +1,280 @@
# Skrypty
Silnik Piklib/BlooMoo wykonuje logikę gry interpretując skrypty tekstowe. W tym rozdziale opisana jest składnia tych skryptów, sposób w jaki silnik je wczytuje oraz kolejność inicjalizacji obiektów.
## Format plików
Skrypty zapisywane są w plikach o rozszerzeniach `.CNV`, `.DEF`, `.CLASS` oraz `.SEQ`. Wszystkie mają tę samą podstawową strukturę tekstową — różnią się jedynie kontekstem użycia.
Silnik traktuje cały kod jak wielkie litery i nie rozróżnia ich wielkości. Konwencjonalnie skrypty zapisuje się wielkimi literami.
### Szyfrowanie
Pliki dystrybuowane z grą są domyślnie zaszyfrowane szyfrem przestawieniowym o zmiennym przesunięciu. Plik zaszyfrowany rozpoczyna się nagłówkiem postaci:
```
{<X:N>}
```
gdzie `X` to litera określająca kierunek przesunięcia (`D` oznacza przesunięcie ujemne), a `N` to wartość przesunięcia. Silnik wykrywa ten nagłówek automatycznie i odszyfrowuje resztę pliku przed parsowaniem. Pliki nieszyfrowane (bez tego nagłówka) są wczytywane bezpośrednio.
## Deklaracja obiektów
Obiekt zaczyna się od linii ze słowem kluczowym `OBJECT`:
```
OBJECT=NAZWA_OBIEKTU
```
Linie pomiędzy kolejnymi `OBJECT=` definiują właściwości aktualnego obiektu. Definicja obiektu trwa do końca pliku lub do napotkania kolejnej linii `OBJECT=`.
Jeżeli ten sam obiekt zostanie zadeklarowany ponownie w tym samym pliku, jego właściwości zostaną scalone — nowsze wpisy nadpisują wcześniejsze.
## Właściwości obiektów
Właściwości zapisuje się po nazwie obiektu i znaku dwukropka:
```
NAZWA_OBIEKTU:WLASCIWOSC=WARTOSC
```
Sygnały mogą przyjmować dodatkowy parametr po znaku daszka `^`:
```
NAZWA_OBIEKTU:ONBRUTALCHANGED^3=NAZWA_PROCEDURY
```
W obu przypadkach silnik akceptuje wokół znaku `=` zarówno brak spacji (`KLUCZ=WARTOSC`), jak i spacje po obu stronach (`KLUCZ = WARTOSC`).
## Typ zmiennej
Typ jest kluczowy — bez niego silnik nie wie, jak obsłużyć obiekt, i najczęściej kończy się to wyjściem do pulpitu. Typ deklaruje się właściwością `TYPE`:
```
NAZWA_OBIEKTU:TYPE=STRING
```
Pełna lista dostępnych typów znajduje się w [Referencji typów](../reference/index.md).
## Literały i ciągi znaków
Sposób interpretacji literału zależy od kontekstu:
- Tekst w cudzysłowach (`"..."`) traktowany jest zawsze jako wartość typu [`STRING`](../reference/STRING.md).
- Tekst bez cudzysłowów najpierw jest sprawdzany jako nazwa istniejącej zmiennej — jeżeli zmienna istnieje, używana jest jej wartość. W przeciwnym razie tekst przyjmowany jest dosłownie.
Liczby zmiennoprzecinkowe akceptują notację standardową (`1.234`) oraz wykładniczą z literą `e` lub `d` (`1.23e4`, `1.23d4`).
## Bloki kodu
Bloki kodu — używane jako wartość sygnału lub jako ciało procedury — zapisuje się w nawiasach klamrowych. Instrukcje rozdzielone są średnikami; ostatnia instrukcja również musi kończyć się średnikiem, w przeciwnym razie może nie zostać wykonana.
```
NAZWA_OBIEKTU:ONCHANGED={ZMIENNA2^PLAY("TADA");}
```
Cały blok kodu musi być zapisany w jednej linii — silnik nie obsługuje wieloliniowych bloków bezpośrednio w pliku skryptu.
## Komentarze
Silnik rozpoznaje dwie formy komentarzy:
- **Komentarz liniowy** — linia zaczynająca się od znaku `#` jest pomijana w całości.
- **Komentarz blokowy** — pojedyncza instrukcja poprzedzona znakiem `!` jest traktowana jako wykomentowana; obowiązuje do najbliższego średnika.
## Wywoływanie metod
Metody wywołuje się przy pomocy znaku `^`:
```
NAZWA_OBIEKTU^METODA(arg1, arg2);
```
## Wyrażenia arytmetyczne
Wyrażenia obliczeniowe zapisuje się w nawiasach kwadratowych:
```
NAZWA_ZMIENNEJ^SET([NAZWA_ZMIENNEJ^GET()+"2"]);
```
Szczegóły operatorów i typowania znajdują się w rozdziale [Arytmetyka](arithmetic.md).
## Wskaźniki tekstowe
Znak `*` przed nazwą zmiennej lub wyrażeniem oznacza, że wartość ma zostać użyta jako nazwa innej zmiennej. Pozwala to dynamicznie odwoływać się do zmiennych skonstruowanych z tekstu:
```
*NAZWA_ZMIENNEJ^PLAY();
*["ANIMO_"+_I_]^PLAY();
```
W pierwszym przypadku `NAZWA_ZMIENNEJ` powinna być typu [`STRING`](../reference/STRING.md) i zawierać nazwę faktycznego obiektu. W drugim — nazwa obiektu konstruowana jest z wyrażenia arytmetycznego.
## Argumenty procedur
Wewnątrz ciała procedury argumenty dostępne są przez znak dolara z numerem (numeracja od `1`):
```
PROCEDURA:CODE={NAZWA_ZMIENNEJ^SET($1);}
```
## Zmienna THIS
W bloku obsługującym sygnał dostępna jest niejawna zmienna `THIS`, ustawiona na referencję do obiektu, który sygnał wywołał. Zmienna jest dostępna również w procedurach zagnieżdżonych wewnątrz takiego bloku.
`THIS` zachowuje się nietypowo: na żądanie nazwy (`GETNAME`) zwraca ciąg `"temp"`, co sugeruje, że pod spodem jest to obiekt tymczasowy. Bezpiecznie działają na niej:
- metody `GET` i `SET` dla typów prymitywnych,
- metody `SHOW`, `HIDE`, `PLAY`, `PAUSE`, `STOP` i `RESUME` dla obiektów graficznych ([`ANIMO`](../reference/index.md)).
Wywołanie innej metody specyficznej dla typu obiektu (np. `GETCFRAMEINEVENT` na [`ANIMO`](../reference/index.md)) zazwyczaj kończy się błędem silnika. Aby tego uniknąć, w skryptach AidemMedia stosowane było obejście: nazwa obiektu była najpierw zapisywana do zmiennej typu [`STRING`](../reference/STRING.md), a następnie wywoływana była `^RUN(nazwa_zmiennej, nazwa_metody)`, która wewnętrznie rozwiązuje wskaźnik tekstowy do faktycznego obiektu.
## Pętle
### @LOOP
```
@LOOP(BEHAVIOUR code, INTEGER start, INTEGER delta, INTEGER increment)
```
Wykonuje `code` dla wartości licznika `_I_` z przedziału `[start, start + delta)` z krokiem `increment`. W pseudokodzie:
```
for (int _I_ = start; _I_ < start + delta; _I_ += increment) {
code;
}
```
### @FOR (BlooMoo)
```
@FOR(INTEGER counter, BEHAVIOUR code, INTEGER start, INTEGER delta, INTEGER increment)
```
Identyczna do `@LOOP`, z tą różnicą, że pierwszy argument wskazuje zmienną pełniącą rolę licznika zamiast domyślnej `_I_`.
### @WHILE
```
@WHILE(mixed value1, STRING comparator, mixed value2, BEHAVIOUR code)
```
Wykonuje `code` tak długo, jak prawdziwy jest warunek `value1 comparator value2`. Listę komparatorów opisano poniżej w [Instrukcji warunkowej](#instrukcja-warunkowa).
## Instrukcja warunkowa
Silnik udostępnia dwa warianty instrukcji `@IF`.
### Warunek prosty
```
@IF(mixed value1, STRING comparator, mixed value2, BEHAVIOUR codeTrue, BEHAVIOUR codeFalse)
```
Dostępne komparatory:
| Komparator | Znaczenie |
|---|---|
| `_` | równa się |
| `!_` | różne niż |
| `<` | mniejsze niż |
| `<_` | mniejsze lub równe |
| `>` | większe niż |
| `>_` | większe lub równe |
### Warunek złożony {#warunek-zlozony}
```
@IF(STRING condition, BEHAVIOUR codeTrue, BEHAVIOUR codeFalse)
```
W warunku złożonym dostępne są operatory logiczne:
- `&&` — koniunkcja (i)
- `||` — alternatywa (lub)
W warunku złożonym znak równości jest zapisywany jako apostrof (`'`) zamiast podkreślnika (`_`):
| Komparator | Znaczenie |
|---|---|
| `'` | równa się |
| `!'` | różne niż |
| `<` | mniejsze niż |
| `<'` | mniejsze lub równe |
| `>` | większe niż |
| `>'` | większe lub równe |
## Dynamiczne tworzenie zmiennych
Wewnątrz bloku kodu można utworzyć zmienną na bieżąco:
```
@INT(STRING name, INTEGER value)
@DOUBLE(STRING name, DOUBLE value)
@STRING(STRING name, STRING value)
@BOOL(STRING name, BOOL value)
```
Każda z instrukcji tworzy zmienną odpowiedniego typu o podanej nazwie i wartości początkowej.
## Operatory skoku
Wewnątrz pętli oraz procedur można sterować przepływem instrukcjami:
- `@CONTINUE()` — pomija pozostałe instrukcje w bieżącej iteracji pętli i przechodzi do następnej.
- `@BREAK()` — przerywa całe drzewo wywołań rozpoczęte przez bieżący sygnał lub wywołanie.
- `@ONEBREAK()` — przerywa wyłącznie bieżącą procedurę.
- `@RETURN(mixed value)` — ustawia wartość zwracaną przez procedurę, ale nie przerywa jej wykonywania.
## Kolejność wczytywania skryptów
Skrypty silnika są zorganizowane hierarchicznie: skrypty z niższych poziomów hierarchii widzą zmienne swoje i wszystkich przodków, ale nie odwrotnie.
### Punkt startowy
Silnik rozpoczyna od pliku `Application.def` w podkatalogu `dane`. Plik ten zawiera definicje obiektów typu [`APPLICATION`](../reference/index.md), [`EPISODE`](../reference/index.md) oraz [`SCENE`](../reference/index.md) — pozostałe typy w tym pliku są ignorowane.
Przykładowa zawartość:
```
OBJECT=GAME
GAME:TYPE=APPLICATION
GAME:PATH=GAME
GAME:EPISODES=PRZYGODA
GAME:STARTWITH=PRZYGODA
OBJECT=PRZYGODA
PRZYGODA:TYPE=EPISODE
PRZYGODA:PATH=GAME\PRZYGODA
PRZYGODA:SCENES=START,CREDITS,LEBIODKA
PRZYGODA:STARTWITH=START
OBJECT=START
START:TYPE=SCENE
START:PATH=GAME\PRZYGODA\START
```
### Ładowanie kolejnych plików {#ladowanie-kolejnych-plikow}
Po wczytaniu `Application.def` silnik ładuje plik `.CNV` dla każdego zdefiniowanego obiektu. Ścieżkę pliku konstruuje z atrybutu `PATH` obiektu (relatywnie do katalogu `dane`), nazwy obiektu i rozszerzenia `.CNV`. Jeśli plik nie istnieje, jego ładowanie jest pomijane bez błędu.
Kolejność ładowania:
1. Plik powiązany z obiektem `APPLICATION`.
2. Plik pierwszego epizodu (atrybut `STARTWITH` w `APPLICATION`).
3. Plik pierwszej sceny tego epizodu (atrybut `STARTWITH` w `EPISODE`).
Przy lokalizowaniu plików silnik dodatkowo uwzględnia aktualnie ustawiony język (zobacz [`APPLICATION.SETLANGUAGE`](../reference/APPLICATION.md#setlanguage)) — wybrany identyfikator języka wskazuje podkatalog z lokalizowanymi zasobami, konsultowany podczas wczytywania plików gry.
### Inicjalizacja zmiennych
W ramach każdego pliku zmienne są tworzone i inicjalizowane w stałej kolejności typów:
1. Procedury.
2. Typy prymitywne ([`STRING`](../reference/STRING.md), [`DOUBLE`](../reference/DOUBLE.md), [`INTEGER`](../reference/INTEGER.md), [`BOOL`](../reference/BOOL.md)).
3. Tablice oraz warunki.
4. Animacje, obrazy, dźwięki i fonty.
5. Przyciski, pola tekstowe, sekwencje, mysz, klawiatura, obserwator kanwy.
Dla każdej zmiennej w tej fazie wywoływany jest sygnał `ONINIT`. Na koniec, po zakończeniu inicjalizacji wszystkich zmiennych, wywoływana jest procedura `__ONINIT__`, jeśli została zdefiniowana.