Cały "świat" podzielony jest na kwadratowe kratki o boku 100m. Kratki te modelują powierzchnię ziemi. Każda kratka jest opisywana trzema bitami: TGridSquare = record H:byte; {wysokosc rogu kratki 0..2560 m.n.p.m. co 10m} G:byte; {3 bity-surowce, 1 bit-twardosc skaly, 2 bity-klimat, 2 bity-gleba} B:byte; {sposob wykorzystania powierzchni} end; pierwszy z nich opisuje wysokość n.p.m. w 10tkach metrow, dwa pozostałe informują o zawartości danej kratki (geologia, roslinność, rodzaj zabudowy itp). Tak więc mapę można zapisać w postaci obrazka RGB (byle nie jpg ;-) Jeśli chodzi o szczegóły implementacji, to żeby nie obciążać pamięci zbyt wielką statyczną bitmapą, można by podzielić obszar na kwadraty 10x10km czyli macierze 100x100 kratek (reprezentowane jako struktura: array[100,100] of TGridSquare, parametry X0 Y0 dajace bezwgledne odniesienie do pierwszego elementu macierzy, oraz 4 wskaźniki do sasiednich macierzy. I teraz w tę macierz wpisujemy elementy wektorowe - tory, drogi, rzeki, nietypowe budowle itp. Dzieki temu możemy zdefiniować duży obszar ze złożonymi strukturami, nie używając dużej ilości danych. Tego nie daje ani struktura tylko kratkowana, ani struktura czysto wektorowa. Ta pierwsza wymaga dużej ilości elementow (trawa, tor na trawie prosto, tor na trawie w bok, itp) no i nie nadaje się do symulatora jazdy pociągiem, a tylko do gier typu Tranport Tycoon (bo przyjemnie sie zbiera informacje makroekonomiczne). Ta druga - wektorowa - jest bardzo pamięciożerna jesli chodzi o odwzorowanie rzeżby terenu, i łatwo zrobić błędy (dziury itp), jest też przykra w renderingu 3D. Używając struktury hybrydowej możemy np. zrobić gre strategiczno-ekonomiczną typu Tranport Tycoon, a potem jezdzić sobie po stworzonych przez graczy trasach :-) Tworzenie tras dla symulatora też jest proste - w jakimś paintcie można stworzyć bitmape bazową odwzorowywującą teren, a potem wpisać w to elementy wektorowe (oczywiście w takim przypadku wystarczy zdefiniować kwadraty 10x10km istniejące w otoczeniu mapy). Teraz uprzedzę pytania, które się wam cisną na klawiaturę: co z wykopami, nasypami, uskokami itp elementami rzeźby terenu, skoro nasza macierz opisuje raczej łagodne formy - z dokłądnością do 100m. [przy okazji - pierwszy bit macierzy H opisuje wysokoœc nie kratki, ale dolnego lewego rogu tej kratki - tak więc cała kratka złożona jest z 4 trójkątów stykających się w jej środku (koperta), wysokość srodka kratki jest œrednią z wysokości wszystkich czterech rogów.] Otóż nasypy, wykopy itp obiekty nie będą w ogóle osobno definiowane - one będą wynikały z różnicy wysokości obiektu wektorowego nad powierzchnią kratki. Czyli engine programu podczas rysowania będzie dorysowywał nasyp lub wycinał wykop. Przypominam, że obiektem wektorowym nie musi być tor, może to być droga, rzeka (raczej tylko w wykopach, chyba że Holandia :), lub obiekt pusty (nie rysowany, ale wciąż wycinający wykopy - np. żleb :) Wyjątkiem jest dowiązanie do danego obiektu wektorowego jakiegoś 3D modelu obiektu inżynierskiego - muru oporowego, tunelu, mostu itp. Wtedy program modyfikuje swoje działanie, kierując się parametrami tego modelu (wysokość, szerokość itp). Jak dotrwaliście do tego miejsca, to teraz w skrócie przedstawię jak wyglądają takie struktury wektorowe: Każdy obiekt jest osadzony względem jakiejś kratki: TGridRelatedObject = object(TWorldObject) {cos o konkretnych wpolrzednych (zwiazanych z kratka)} BelongTo: longint; {UIN struktury wyzszego rzedu} {to ważne -> } Location:TGridCoordinates; constructor Init(RL:boolean; FirstLocation:TGridCoordinates); constructor InString(InitString:string); function CheckGrid(GridX,GridY:integer):boolean; function GetGridX: integer; function GetGridY: integer; function GetRelativeX: real; function GetRelativeY: real; function GetAbsoluteX: real; function GetAbsoluteY: real; function GetAbsoluteA: real; procedure ShowLocation(var ObjectLocation:TGridCoordinates); end; gdzie TGridCoordinates = record {wspolrzedne obiektu osadzonego w kratce} OffsetX, OffsetY: integer; {wspolrzedne kratki 100x100m} CellPosX, CellPosY: real; {wspolrzedne w kratce} Attitude:real; {wysokosc n.p.m.} end; Tu należy się jeszcze wyjaśnienie co to jest UIN - każdy obiekt ma Unique Identity Number typu Longint. Jeśli obiekt jest powiązany z innym, to odwołuje się do tego właśnie numeru. Przydatne jest to też przy organizacji struktury danych (łatwo przeszukiwać stos). Ujemne wielkości tyczą sie obiektów wirtualnych (np. projekt, prefab itp), dodatnie wartości tyczą się obiektów rzeczywistych. Potomną strukturą jest TConnectedPoint = object(TGridRelatedObject) {cos polaczone z czyms innym} ConnectedTo: TConnectionTable; {Id innych polaczen obiektu} gdzie TConnectionTable = Array[1..maxcon] of longint; Jak teraz tę strukturę wzbogacimy o rekord: TLineDef = record Radius,Len:real; {jak R=0 to mamy prostą - troche ryzykowne - trzeba uważać na div/0} DeltaH: real; {roznica w wysokosci poczatku i konca} PivotPoint: TCoordinates; {wspolrzedne konca (w/m kratki)} end; to mamy prototyp objektu opisujacego tory, drogi, rzeki itp. Wystarczy jeszcze uzupełnić o bajty opisujące własności, tablice możliwych przejść, itp. Dzięki takiej strukturze pociąg może jechać po torach ;-)