1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
/* $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+1))
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);
}
|