/* $Id: map.cpp 23740 2012-01-03 21:32:51Z $ */ /* Это модуль, для возможности полноценной игры в трех измерениях (подземелье, метро, итп.) Плоское игровое поле выглядит примерно так: *-----------* | | | | | | *-----------* Мысленно нарежем его на одинаковые части: *---*---*---* | | | | | | | | | | | | *---*---*---* Мысленно соберем части в вертикальную стопочку: *---* | *---* | | *---* | | | | * | | | * | | *---* Таким образом имея плоскую карту мы описываем 3д пространство. Для простоты вся карта делится только по оси Y (разрезы параллельны оси X) Деление происходит на 1, 2, 4, или 8 кусочков. Например было выбрано поле 64х64, с 4-мя слоями: Создается карта 64х256, подразумевается, что: X Y верхний слой 0--63 0--63 второй слой 0--63 64--127 третий слой 0--63 128--191 четвертый слой 0--63 192--255 Обычная карта MapSizeX х (MapSizeY) Представление в виде слоев LayerSizeX x (LayerSizeY x LayerCount) Иными словами игровые координаты "плоского" пространства MapX, MapY, MapZ переходят в координаты нового "3д" пространства // Константы LayerCount = число кусочков... (1, или 2, или 4, итд.) LayerSizeZ = сдвиг слоя по вертикали (например 1) // Аксиомы MapSizeX == LayerSizeX MapSizeY == LayerSizeY * LayerCount // Расчет координат LayerIndex = MapY / LayerSizeY WorldX = MapX WorldY = MapY - LayerIndex*LayerSizeY WorldZ = MapZ + LayerIndex*LayerSizeZ */ /** @file map.cpp Base functions related to the map and distances on them. */ #include "stdafx.h" #include "debug.h" #include "core/alloc_func.hpp" #include "void_map.h" #include "layer_func.h" #include "layer_type.h" #include "landscape.h" #if defined(_MSC_VER) /* Why the hell is that not in all MSVC headers?? */ extern "C" _CRTIMP void __cdecl _assert(void *, void *, unsigned); #endif uint _layer_size_x; ///< Size of the map along the X uint _layer_size_y; ///< Size of the map along the Y uint _layer_count; ///< The number of tiles on the map uint _layer_count_log; uint _layer_size; ///< Layer size (sizeX * sizeY) void InstallLayerSystem(uint size_x, uint size_y, uint layer_count) { if (!IsInsideMM(layer_count, MIN_LAYER_COUNT, MAX_LAYER_COUNT)) error("invalid layer count"); _layer_size_x = size_x; _layer_size_y = size_y; _layer_size = size_x * size_y; _layer_count = layer_count; _layer_count_log = FindFirstBit(layer_count); } void FixUndergroundHeights() { uint width = MapSizeX(); uint height = MapSizeY(); /* Layer correct */ for (uint row = 0; (uint)row < height; row++) { /* Граница между слоями */ if (!(row % LayerSizeY())) for (uint x = 0; x < width; x++) MakeVoid(width * row + x); for (uint col = 0; (uint)col < width; col++) { uint tile = TileXY(row, col); if (IsUnderground(tile)) SetTileHeight(tile, 0); } } } uint8 calculateLayer(const ViewPort *vp) { // Функция ViewportDoDraw вызывается несколько раз с разными параметрами // Нужно же найти только один слой. // Опираемся на вьюпорт. Point pt = InverseRemapCoords(vp->virtual_left+(vp->virtual_width >> 1),vp->virtual_top+(vp->virtual_height >> 1)); TileIndex center = TileVirtXY(pt.x, pt.y); return LayerIndex(center); }